STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。
! Q" V+ X" [( [9 a9 }
6 q& O1 L7 L# B! @. _ 鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。. |% L; t- C" l. E* n
增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号
4 l5 S* x3 S6 R7 _) q& G7 @* Y# r1 d
% h0 E6 `7 |/ t) ]0 t$ N 手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下. h3 q, C& J+ K
8 S* l. S: H- p1 ~( ]5 A0 N. C
- static void MX_UART4_Init(void)5 Z4 F6 M. {1 H* B* b2 w
- {
8 g* X5 R% ^' c - 1 a' i; E' Z. _( E5 o5 I
- /* USER CODE BEGIN UART4_Init 0 */
( v$ y2 t* k' _* B2 z
+ y) B4 Y" ?0 [0 I4 N9 M- /* USER CODE END UART4_Init 0 */
9 u; Z3 d3 Y9 B1 P8 C! `) M6 H - ! a: u9 I. k \- s* i+ w% N& Z
- /* USER CODE BEGIN UART4_Init 1 */
: r: ]2 J; o' a, a1 t$ a
2 {0 ?& B+ t6 ~' F- /* USER CODE END UART4_Init 1 */
& O5 u" J/ } j - huart4.Instance = UART4;. }* K$ ?/ r- G% ~( r
- huart4.Init.BaudRate = 115200;
1 Y$ p3 v$ a2 l: ^& K4 Q( L5 y* r: c - huart4.Init.WordLength = UART_WORDLENGTH_8B;
2 g8 x, A+ Y( j2 |( k" O+ B - huart4.Init.StopBits = UART_STOPBITS_1;8 [' m$ B8 W3 i% H; J
- huart4.Init.Parity = UART_PARITY_NONE;
. v( D) ^+ P1 S9 p* o0 g - huart4.Init.Mode = UART_MODE_TX_RX;
0 l* D" z H6 K/ _5 F - huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE; S' _& _! _% y) ~& o# @& q
- huart4.Init.OverSampling = UART_OVERSAMPLING_16;! C2 i3 t- h2 B- v j9 J% W
- huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;& d9 ^* ?! [5 P2 J4 O$ k
- huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
6 d$ h+ u3 Z' e7 b, v& A$ h - huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;5 ], S; l' O8 O& g3 a6 `/ }
- if (HAL_UART_Init(&huart4) != HAL_OK)" }- \7 }8 f1 `6 C' `& c" u
- {+ j5 i6 F& {& X3 i, A1 P
- Error_Handler();
. U1 v- `, U6 u/ R4 o7 N# a" I - }2 H, v& N. ^- f9 S$ E3 @
- if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
" w( R- [+ D( i6 V4 _( m - {3 a5 _0 J% h/ x; l1 k: k8 X4 r
- Error_Handler();2 {- Y6 H, H" f- C" z0 h
- }
2 R! z6 b6 `4 _) v: X - if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)0 s' T2 o8 K! k. q4 E1 s
- {
# _& x+ T; S, y+ R - Error_Handler();
* H2 s t' l" r/ }; g( U' } - }* L7 v# n; o7 g0 K0 t9 I" @8 z9 A
- if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)) g! m/ A2 O5 x- C& I5 Z- B a
- {
# T! `' M- e- e$ L5 G - Error_Handler(); ?4 N8 J& g% c# D$ N; p3 C4 I' ~
- }' ~" u7 f+ b% |, @& H0 _
- /* USER CODE BEGIN UART4_Init 2 */! r+ j3 _* W3 }" S" L E
n/ e% _1 j' ?7 u8 K. c: O- /* USER CODE END UART4_Init 2 */& W- I& f+ F- q, {7 h
- % g- K0 ^8 r5 z t3 R+ m4 z
- }
复制代码- void HAL_UART_MspInit(UART_HandleTypeDef* huart)
% N6 t# K+ J. r* X - {8 M8 q) l! z: h) u! p+ Q2 u
- GPIO_InitTypeDef GPIO_InitStruct = {0};: |4 [; F8 T* v
- RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};& X7 S" g( @+ z, p: }) O& K
- if(huart->Instance==UART4)0 X/ K( W0 i: V! o% a# u0 ^3 v! L
- {. T6 K( j8 b6 x, f5 K) P( s
- /* USER CODE BEGIN UART4_MspInit 0 */
+ o6 _, _5 F: C, P4 ? \ - A- y* ~" x. g$ V9 m4 i
- /* USER CODE END UART4_MspInit 0 */. O2 F$ }- E) g; S
, S1 x/ f5 Q! N0 U4 k+ Q2 C2 [- /** Initializes the peripherals clock
1 ~; @# T* k. z- C" E* K _; s. k - */5 e9 c6 S! m+ n3 O( z
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;; M3 x; E6 S, P, c' i' g
- PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;
# \$ y4 ?0 D2 p8 s M. l - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)0 W+ A+ e& x: ] m
- {: o! \8 c, K. q
- Error_Handler();
8 x" Q, {' Z1 x! o9 }; T - }
5 ^$ i( C; _+ G0 V/ @ - 8 F0 i% B9 C6 w+ i. d
- /* Peripheral clock enable */8 Z, j+ }$ G m
- __HAL_RCC_UART4_CLK_ENABLE();
; K5 g+ e5 V) T' H1 \" u6 ^
9 @: L- T* `2 g+ p% Q4 H- __HAL_RCC_GPIOD_CLK_ENABLE();
4 r' R* O9 b7 t" E# u ^. g - /**UART4 GPIO Configuration
& T- n' {+ t& V. ~ - PD1 ------> UART4_TX
; l8 S( D8 }* T7 k u4 R& g - PD0 ------> UART4_RX" I% X, d- c% b6 j- k; ]7 ]; H
- */
* Z p& ?8 \# l F( G' `1 E - GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
+ K3 R; X' z' F( u3 j - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;/ a# D/ Z6 n+ ]( y/ [: V4 {, Y
- GPIO_InitStruct.Pull = GPIO_NOPULL;& O7 Q/ a# [" s4 G( g( b
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;8 }5 E/ a( Q2 _# M4 x m+ w
- GPIO_InitStruct.Alternate = GPIO_AF8_UART4;& o4 x$ V$ H9 U* D7 f5 k7 y& ]
- HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
2 I* ?7 J9 i. P% h$ A - $ g# h- ?7 N# v3 h
- /* USER CODE BEGIN UART4_MspInit 1 */ C( |, D( W6 _1 I' m/ u2 a
- 6 Q3 l! O/ F2 b2 ~1 s$ k
- /* USER CODE END UART4_MspInit 1 */
- r: @$ ?6 K* K8 ^% x
6 |7 o- _) w: D& H5 a" h# f( E3 R l% J- }
5 P* H& M9 {2 Z* z9 q - & c: c! h4 C' j2 s# l
- }
6 |) B* A. I4 N) N0 O
复制代码- 使用cubeIDE
5 Z! K, V7 B2 P3 d* b; {7 @9 T0 o - __io_putchar(int ch)! k8 _7 K" b# F0 v4 l9 X* ~7 h: n
- {2 T. }$ X X3 y* R( L: u( ^8 U
- HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);) }4 w) f$ {) ^7 t' i3 k
- return ch;
8 x: U2 S( s D) X ?; ^8 h - }
复制代码 代码修改完还是不能打印出信息的。需要IDE也作下配置,如下2 u/ _" I3 \7 t3 }: ^, Z
2 V! ], i8 I1 S
添加输入输出头文件stdio后,就可以试试程序如何了。! z) b1 k4 ~" V' v: j
- P0 c6 a, b( n- l9 o 以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。
9 [* V) {, G# a0 r. Y2 d+ e# E+ G, w3 U
' k. g$ B x f$ }7 h" V- static void ViewRootDir(void)0 P" c3 f& ~7 ~& ]* y: r
- {9 h. I* i, V& h9 ~
- FRESULT result;- C# v/ _- H& [
- uint32_t cnt = 0;" |( v! J: ~$ ~) S/ U# p/ i" E$ d
- FILINFO fno;
& Z$ G$ J2 r* Z y7 T - ; q7 a7 ` @9 C: y0 R
- ' P1 v0 k8 N9 R( D3 d# F
- /* 挂载文件系统 */9 T' c1 W. b% I6 \% V
- result = f_mount(&fs, DiskPath, 0); /* Mount a logical drive */
8 x0 C/ B v( U5 J - if (result != FR_OK)
: k* q# k# L0 G0 g' k, _" @ - {
+ u& C2 ? ?- E% [! p - printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
& P7 i2 ?% L' Z$ E% I - }
: ~" A/ l' `: k7 _7 |% B - 0 n- ]& u4 B3 _: e' s5 L
- /* 打开根文件夹 */
) q/ I! D+ @& p& m( e9 F - result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */- H" C( h+ [* p# Z5 h
- if (result != FR_OK)
+ s3 I5 ^/ [) _) ~% B5 ~+ C - {: H, a, I1 U+ o5 T9 W. y# C6 c
- printf("打开根目录失败 (%s)\r\n", FR_Table[result]);
, Y1 I+ V4 [# f- I9 ]. g$ j - return;) w! |3 z# L Q
- }, |2 H; A+ V% N
- 8 r4 _0 o: [3 a+ }; d$ d
- printf("属性 | 文件大小 | 短文件名 | 长文件名\r\n");8 x/ n9 T2 [! z! L) |) p
- for (cnt = 0; ;cnt++) ?% P- v, k* W( W: i0 j0 ?
- {+ W7 s, D+ T$ x: @ n( L
- result = f_readdir(&DirInf, &FileInf); /* 读取目录项,索引会自动下移 */
s5 D T+ a/ g3 F! k2 o - if (result != FR_OK || FileInf.fname[0] == 0)) ]) m* z' I- `+ c5 C
- {
: j) E! m' _2 ]/ `7 t& d - break;
3 \- v. f3 o3 d. m# ~, ?* E - }
/ M( J( Z$ Q: O/ H1 { D" Y0 a. b; X
# t9 i, h: F0 A ?* T- if (FileInf.fname[0] == '.')( h8 ^) K s' U
- {
/ W/ g# u" j8 n( u( P - continue;* t2 s9 x, n6 d! J3 u! s( c
- }2 b* X3 k5 `: {* [
$ I: Y3 Y9 h- k' v- /* 判断是文件还是子目录 */& G- E6 o5 @ D# u+ q- P. @
- if (FileInf.fattrib & AM_DIR)
5 a# L1 l! h7 t! p - {
` P9 e% x. [ - printf("(0x%02d)目录 ", FileInf.fattrib);
7 Z6 _' `) [/ ~9 K8 I0 v - } q1 q* ]" D% Q) R( d: o
- else+ Y" ]5 X- p6 U; x6 |% M( H/ k) d
- {
: y# Y2 Q/ H7 N: P - printf("(0x%02d)文件 ", FileInf.fattrib);
+ K8 J, g( H, k% V! @) |& h8 h2 P - }( x9 c1 Z4 T5 r% q! u4 N. _
+ r" {& H- \8 y! {5 z/ h- f_stat(FileInf.fname, &fno);' [* ^! _+ k9 E2 s& v, u: L
- $ ?1 ~1 n/ c3 A, \; \8 J O! i
- /* 打印文件大小, 最大4G */
; M# M( V8 h, Q# S/ O* Q3 ^ - printf(" %10d", (int)fno.fsize);
! @% G( T1 K; t% j9 A: e6 X, a - ' r# x' m5 T8 x4 S% D( e' f7 L+ ?
1 J& w% I6 Y" M- printf(" %s\r\n", (char *)FileInf.fname); /* 长文件名 */3 T( [. v: b* T. B
- }$ o X" c" O% p5 i6 s6 S- n
- 5 @+ Q' T( L3 @6 l5 Z- M4 M
- /* 打印卡速度信息 */
2 s6 w g) H1 b. p: z - if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)) P3 q, s% U4 g9 D% O# X1 K
- {
8 ]0 R! r. u, t - printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");2 A: m% t! ?) y% I- E f
- }) H" o6 g; a6 a7 M7 M/ b5 r
- else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)$ g5 u Q' K5 l' G
- {
8 M+ E6 ^1 M( }+ N- d$ b$ | - printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");+ L& E* u2 N2 Z3 I* O1 N' N3 O
- }6 `; C6 w0 A# U* W& W+ ?: z& s/ m
- else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)1 z$ x' u H" Z% r8 t- j& e5 [
- {9 ~ o$ h/ l$ h
- printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
7 m9 G, o$ u) X# P) V( g' o, c/ P - printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");5 q3 {' j' y+ u2 y& R: K
- }; H" r. [1 n( n! J a
1 v% ^% z9 \# T, i. e9 ]0 v
2 Y2 U( f" d6 l2 [4 P! o0 p- /* 卸载文件系统 */
r* `9 [) z, O' e/ u) _' L. T - f_mount(NULL, DiskPath, 0);
. z" R6 Z0 B7 [4 O: L4 D3 A3 Y3 v - }
复制代码 函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。/ e( Q6 j: q: b
7 l/ i T( M: o5 j) f& | 中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。
7 u0 i, ]% C5 u/ u2 C$ _$ T; J 添加的内容为 -fexec-charset=GBK,还是修改编码的意思。
6 d0 ^0 b' z4 A& e% \9 _. F" l! \
7 p1 F$ e# W4 j+ b
接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了/ n) ]6 H) A. \. M# c
* s, N+ \# {) o5 K! k6 Y; G 很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可7 ?: t& J3 S# s: C+ P
$ a: \; F4 l6 M0 `6 E6 N
料想这次应该没毛病了。结果,新的意外又出现了。
& G) H& m3 o, P% P( P z
, J0 k- C1 s8 @' ?6 R 还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。+ n+ ]7 Y9 E9 C( i1 T
* ~- x$ }& h% f9 x' _+ F8 n
满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。! }+ p" q2 Y/ D3 c/ i1 [
" ^9 E& \7 z7 G2 | 9 s* N1 M1 ]2 j7 E
# u. ]+ F# Y1 |3 ?5 @+ {$ i3 y
" @; z& b/ c# v2 _4 F5 }0 m7 L# r6 s% }' t/ G
5 \; t7 v# Q$ D9 r" O- ^& `6 {
|