STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。/ g! a+ Z% C6 T4 A- W1 `
' I+ \" G# P0 X- Q# N3 q- n% x
鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。* n* S( R6 P8 B
增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号, V4 ^; R4 X; `' X" I A; Y
4 ~3 Q. T1 Q$ j. e3 J 手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下; H6 |/ t7 _* B
5 n- ^# Q8 @+ @3 O v. B6 j$ D
- static void MX_UART4_Init(void)" @3 h- P' N: ?+ v
- {+ D+ k- }8 m4 S$ I
- " f1 d# L- G& P1 G4 K; N
- /* USER CODE BEGIN UART4_Init 0 */
6 u( b! ~$ M* W& X5 U
% I: h. ~7 k `8 o6 T: a- /* USER CODE END UART4_Init 0 */
g# F! ?9 I* P' }+ k4 Y - % Y8 y, @7 U7 G& Z
- /* USER CODE BEGIN UART4_Init 1 */4 p/ v9 Y8 T' n. ]
& d0 ^9 f9 e4 u* i) b- /* USER CODE END UART4_Init 1 */
. t) W- X( s; \* a1 ]+ }! {: }2 d - huart4.Instance = UART4;% i5 F) [( u. I# t6 Q2 k5 g( H
- huart4.Init.BaudRate = 115200;
$ c; U0 I! U) e - huart4.Init.WordLength = UART_WORDLENGTH_8B;
5 Q& k6 K% b! W$ Z$ A3 l q. Y - huart4.Init.StopBits = UART_STOPBITS_1;1 c2 j) w% M) z! N3 }6 d& |
- huart4.Init.Parity = UART_PARITY_NONE;! q) r3 ?" g7 B% @
- huart4.Init.Mode = UART_MODE_TX_RX;/ b. @4 b A( E9 I* Z
- huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
x/ z3 u8 h/ D# \5 o( q - huart4.Init.OverSampling = UART_OVERSAMPLING_16;
; R8 f( j; _) G1 c- ]; ~, F6 e - huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;6 ]" N9 N0 g5 K+ G% F7 Z
- huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
7 d% K+ u# n, x6 D. V" T - huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;/ r/ N* V, W, g {# s
- if (HAL_UART_Init(&huart4) != HAL_OK)1 }4 u9 z" E& m+ t) S8 u
- {
# o2 b0 w8 F. [1 ?9 y - Error_Handler();* j/ J# d; t7 O% _! {" _& o
- }
4 T0 C2 @9 A2 P$ _ - if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
4 A! j. D9 w2 L$ |3 y - {/ N" W' N4 @' j* ?/ d) n9 K
- Error_Handler();
% e* [8 I: h& r- p - }
- |7 \$ _! ~ V' k/ q L - if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
8 r) w3 d* v% Q; d - {- B" Z0 s- G; R$ V0 C) p9 s
- Error_Handler();
, l, K& h( H- @1 X - }! @( u) m8 `0 D" U8 U
- if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)6 z8 I4 O& |. z' B) L/ Q
- {+ E+ r5 ]# a; j: ]) j6 l; F- U
- Error_Handler();& y2 E9 i7 h# `1 t( R! r
- }% a$ o! a& y: G, c( b* A$ g
- /* USER CODE BEGIN UART4_Init 2 */4 [; j( `8 \# g6 K+ j8 C
" K! O1 [/ s1 w) e( ?- /* USER CODE END UART4_Init 2 */& f. T- A$ f2 n* y$ B
( F% ]* E$ E3 u+ _. N9 o- }
复制代码- void HAL_UART_MspInit(UART_HandleTypeDef* huart)' z/ b2 E( A5 ^! A( R
- {
3 N3 ]. W9 `+ ^0 g - GPIO_InitTypeDef GPIO_InitStruct = {0};
3 N+ K! s1 ]% j9 w- z - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/ t& m) \# {+ x0 ?8 u( s- B - if(huart->Instance==UART4)" L1 |# R9 U- x; D/ H
- {
) j |# x M; c1 _: o5 K& U0 r - /* USER CODE BEGIN UART4_MspInit 0 */- e- d5 }% h7 s1 s& ~
. Z7 F/ f. B6 _- /* USER CODE END UART4_MspInit 0 */. m. [, L/ z' P: F
- ; {/ L8 z: }' V4 f
- /** Initializes the peripherals clock' K5 [% A9 `( s5 P
- */% g$ ]) v+ N9 `9 {
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;
6 _3 B1 T% i$ t) {2 e3 x, N - PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;
1 `, x; @& \2 j - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)9 S( H s: ~/ ?9 D2 J1 N+ i. [6 K) G
- {
& V6 g: x1 e( f" L1 u1 |7 _ - Error_Handler();
; {' U0 N5 b) U! _. z - }6 s; M0 e7 w% O6 U5 ]
: y: x8 r# d6 f$ {8 j4 h2 F- /* Peripheral clock enable */( a- d" N8 j3 E3 c
- __HAL_RCC_UART4_CLK_ENABLE();" g4 f; ?/ _! `% B, w [5 d# W
& p+ f# Z% P2 A( X. M+ W$ _- __HAL_RCC_GPIOD_CLK_ENABLE();
' q( Y4 B4 M) L' S( H4 F1 k - /**UART4 GPIO Configuration
+ @! P% J8 L8 L" k* \/ d - PD1 ------> UART4_TX6 k0 D" {! b3 W. v
- PD0 ------> UART4_RX
" h& r8 o C) l$ v- m' ] - */: U. k1 ? r' L2 l2 D
- GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
# v+ }( f6 k! v4 w l, f/ S - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
# w/ u( A2 D" F# y, \1 q6 R' A - GPIO_InitStruct.Pull = GPIO_NOPULL;
2 p* u) O; n8 G1 s3 |) \ F: y8 m" i - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;) z/ G. }! u# @4 q, j) b }' `
- GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
: y1 T5 e0 A, ]- N4 r C - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);5 f9 @6 p3 t. K! g/ d
8 m6 Y; v) \8 a+ Z* M- /* USER CODE BEGIN UART4_MspInit 1 */' _& O c8 g8 m% P) R) K/ O1 J9 W8 A
- ' G2 |8 S) O: C8 g1 y4 n+ U
- /* USER CODE END UART4_MspInit 1 */1 J( m( ]: g* Y9 u$ o% l! m
0 s! F5 ?- g' h- }, p; V& K" [; I8 i8 R
- 0 j$ ]! P# ~8 ]" `- `* K5 Z
- }* y, ^( I" t' ]- y& a
复制代码- 使用cubeIDE- [9 ?6 G* f5 c
- __io_putchar(int ch)& i6 V- s' i! x! N8 O Z* G+ O* b+ Y
- {
9 |" z! k4 E$ G1 f+ P3 o' u - HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);* N1 ]9 ^5 t; D* o
- return ch;
* }* p' ~: D: r) S: ~ - }
复制代码 代码修改完还是不能打印出信息的。需要IDE也作下配置,如下6 R- R2 V7 I1 X) V: o8 Q3 g3 ?' q
- y& i3 I, g" R) W# i( x4 M
添加输入输出头文件stdio后,就可以试试程序如何了。
8 d3 F( }4 U1 J' J
4 H1 V7 ]( {4 y* [. a* I5 b1 N5 _ 以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。
3 x6 A8 [% l0 |6 O Q$ }6 a3 B Z6 p
( i! T% i& J- M+ r% {3 r2 V- static void ViewRootDir(void). v' O+ y& m/ v S7 \% L
- {
, A7 j7 k9 N: x* }5 W3 f u+ ~' f9 O - FRESULT result;5 d* x/ v, |7 u+ J: G* ^
- uint32_t cnt = 0;
3 a. c5 b4 w9 z0 C - FILINFO fno;' C) B! [# S7 A6 {" E
- 6 N1 V A9 ` r5 @$ g* s
2 t$ \- |, l& k- /* 挂载文件系统 */6 A v8 G6 x2 j% p& c+ ?6 }
- result = f_mount(&fs, DiskPath, 0); /* Mount a logical drive */
# v. d' P; f2 O - if (result != FR_OK). m0 n1 _+ c+ u2 V2 l0 s' M8 B/ i1 n5 t) H8 V
- {
B. s: X) b$ K, ] - printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
/ V4 ^2 R) l( k/ D8 `5 y1 b - }
0 ]- Q' O3 V* _: O8 ]4 q7 s2 { - - f( ^/ ^7 ]8 S1 ~7 s/ R. Q3 `
- /* 打开根文件夹 */
3 v- n; M0 P/ Q; J6 k2 f& D - result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */
8 g" ? e2 @! `; Q9 f - if (result != FR_OK)/ P) l' L7 V1 h2 V6 L' J1 c! g
- {
+ y! t7 P" E( c: g - printf("打开根目录失败 (%s)\r\n", FR_Table[result]);; F" [8 A4 `$ M# a
- return;) r M3 s' U5 H! a4 Z& X
- }0 y, E! N) l5 D+ ]% }: d
- ' u T+ |/ O# ?1 [$ f# R
- printf("属性 | 文件大小 | 短文件名 | 长文件名\r\n"); g0 [6 x) z: ^( I+ E$ @
- for (cnt = 0; ;cnt++)
1 H! N a z8 J# d8 a+ z- R - {
5 Z5 u* J6 J* {4 l - result = f_readdir(&DirInf, &FileInf); /* 读取目录项,索引会自动下移 */
* S9 c/ I* C- K+ s. w4 S- }0 b - if (result != FR_OK || FileInf.fname[0] == 0)3 u) }$ K i2 F4 j* b1 w R$ S: \
- {: W' T* H2 o- C$ o7 {
- break;2 Q* ~ `% r: ?+ F7 M
- }* ^6 v7 m7 @' U1 p; j% ~; c5 o
4 i t) G! \$ G# X5 k0 f- if (FileInf.fname[0] == '.')
2 {4 z$ s X: v% o: Q - {
4 E" F8 w' M6 S: S4 ?, T - continue;
9 S4 a, u, @8 J9 m8 p/ J: S - }
4 G0 R, y4 E# u# Q- j1 J0 S - & [% e6 j0 s C- ^3 r2 ]/ R( I
- /* 判断是文件还是子目录 */
% E; N2 {$ f. {9 X9 C+ [2 n' t+ p7 X2 Z - if (FileInf.fattrib & AM_DIR): \0 f' Z3 E% u) C3 W4 j8 J
- {7 ~0 R* X8 y& m( I, h; w! N! g
- printf("(0x%02d)目录 ", FileInf.fattrib); p$ N& y( C8 b* y9 w) [% D! J
- }4 D* }: f3 O& d: w) W0 Z' y
- else
7 X+ M/ o. f* J, N0 L - {
7 e$ J) D5 ]5 k* w0 r2 e - printf("(0x%02d)文件 ", FileInf.fattrib);* W1 B$ P {( M2 l) a8 Q6 _; G5 c
- }' i) E6 @& t/ g& x% h6 I; F" E
- x+ F" }6 h5 _# N
- f_stat(FileInf.fname, &fno);! k2 i1 F% @8 h" @
- & n4 J+ f8 d# ^- r+ Z0 M
- /* 打印文件大小, 最大4G */
+ E! N$ |4 m6 ] - printf(" %10d", (int)fno.fsize);
7 c. G$ \9 H' f# v- o! x# [0 l - / C$ P! L& C8 T7 A2 M
- ( j( x4 o! J- ?$ L: w
- printf(" %s\r\n", (char *)FileInf.fname); /* 长文件名 */
* h0 T4 E) ~( Q$ N! u - }
* I( F3 l2 b/ ?4 v+ b5 \" v( B - 9 B; @0 E3 h% ?9 ~3 `: \6 I& P
- /* 打印卡速度信息 */8 U6 F8 l' m( @
- if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED); N" a9 i" q! \; ~& M0 |# [
- {( t T3 E2 t; l) M% p5 T: ~: q
- printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");
! r3 D2 V9 ]. W" L: m1 z - }
1 B4 v' X# ~& ~3 g4 r - else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED); B0 Y8 W. P( ~- ]& R4 @
- {
- j4 _; K; N7 x: R6 |4 a - printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");5 A0 W& ?) G$ q2 q% O/ ^, Y6 T
- }7 j$ e6 Y. [$ ?( H
- else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)4 f9 ?/ h. j% O3 i
- {* k" Q& B/ g; i8 }) e
- printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");0 D+ I) j9 f3 |, w. M
- printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");
1 U$ A3 R Q- u3 v1 R3 ? - }/ M' P( a+ `. P$ u9 @( v
; J9 d3 {0 S5 a- ~' ^% H# y* Q- ; D) b& n+ a/ i$ u
- /* 卸载文件系统 */
2 T6 |( E* T" { - f_mount(NULL, DiskPath, 0);! N5 b } B6 u( e5 | A) `& r- ~
- }
复制代码 函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。
9 E1 h+ {3 G# ]- t5 t
+ D2 p- a5 h0 B4 M1 P+ p& {' Z7 C2 i% _ 中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。- T T# Z9 o' ~5 f; A& \- s
添加的内容为 -fexec-charset=GBK,还是修改编码的意思。( I6 `# c6 \, Y4 w. h
* ^2 y4 b: [9 ?# d4 q2 ? 接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了
1 h, |" }: F/ h6 [5 U
* u5 d3 t# f. Z
很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
! C7 x. v9 ^) d+ H, M0 P* Z% f9 u
3 h! [; v& `* |6 S6 R
料想这次应该没毛病了。结果,新的意外又出现了。
- ^2 a5 P+ g8 B: @7 `
0 E) e+ z a0 t 还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。9 `& x- R4 A$ a5 x" J& h
?; y3 y( d1 ? j3 C" F) g 满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。 A2 K; L5 U9 ~2 ]
; p. r. g' f8 ^5 k! V7 V0 E# U8 e 6 B' B& f7 ^( d! O
! l: M" I1 B7 ?
/ w5 C& ^( [+ T; j0 p0 `6 c% ~" ~. r4 v, M
' Q- |/ C7 b, H V' T7 h
|