你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32H7S78-DK评测】使用FatFs文件系统读取SD卡文件

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。
+ \" |) m& n) A; m' {& u. r  N; K
% S! `) b! D2 O- H  H/ ~    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。
5 {+ l( \3 ~& _) a  b    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号
' H6 r) {- X2 D1 G. R( o/ w0 t      b.png
+ R% z. c* ^  a5 ~- T1 P1 e     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下
1 X) G: b+ Q# m& z      
2 m6 y7 Y$ a6 B; N, }2 |
  1. static void MX_UART4_Init(void)" {8 ]8 I/ D0 e4 G
  2. {
    1 M3 A5 S$ x. J5 @3 P

  3. , Y4 q) ^" R9 k. f5 D: W& ^& K
  4.   /* USER CODE BEGIN UART4_Init 0 */9 t( C6 K# L8 o) s* I
  5. / g, i& i, ^1 [' x" L
  6.   /* USER CODE END UART4_Init 0 */
    - P6 o' Y& q8 E2 _0 U
  7. + C2 m) K, [8 v' O
  8.   /* USER CODE BEGIN UART4_Init 1 */
    ) J8 t4 Z: x  g" z3 w% W: A
  9. " l# b# @+ p/ e3 U: m6 f
  10.   /* USER CODE END UART4_Init 1 */) v* p: v( U, V5 J! Z1 c( c' J
  11.   huart4.Instance = UART4;9 r6 E) ~% ~: q- g& u- }$ _
  12.   huart4.Init.BaudRate = 115200;9 n6 d/ D9 S6 E" w2 C/ d
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    8 K$ V' v% ^" m# e1 O/ H2 `4 H
  14.   huart4.Init.StopBits = UART_STOPBITS_1;" t0 P2 m0 J, z8 B! \9 w, }
  15.   huart4.Init.Parity = UART_PARITY_NONE;
      M, F' @2 Q9 Y4 S: r
  16.   huart4.Init.Mode = UART_MODE_TX_RX;
    0 s( v% _3 I( i& c' X3 F+ o
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;* ^$ k5 F$ H! O4 X4 [* j4 E# M, _
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;8 k5 P& J4 m: Y* W/ P
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;. d( A. Z7 \1 R( q3 p! w
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    ! b. \4 z( [& X+ V- b$ \
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    , @. P; S" S" \% E6 @
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)
    " ?  O0 X0 F; S- H
  23.   {
      G2 K4 B. t3 F1 o4 r$ B
  24.     Error_Handler();
    5 Z" [" z* s" U7 G. P: {2 r7 d
  25.   }
    1 t0 _9 s! M4 a& P( I
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
    * j9 c2 j% i2 h; v; T4 k# m" d
  27.   {  I* [6 I# o8 [7 g
  28.     Error_Handler();
    4 }4 S; g" m6 k
  29.   }
    6 a- I) e. N. E- |2 {* K2 j
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)) p! u: P( v0 ?4 e2 E* c  _/ A
  31.   {6 d/ F* c) y3 \% S& w
  32.     Error_Handler();/ a' h* h* e+ c: d1 p
  33.   }
    4 p$ ^6 z/ e& M* t- s5 C
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)7 G/ h2 O9 B* x6 d$ |
  35.   {  i$ K; N. R6 k' R( z
  36.     Error_Handler();
      o% W7 \- [6 |6 Q
  37.   }8 n8 _7 w, p6 y9 x8 r
  38.   /* USER CODE BEGIN UART4_Init 2 */* G2 O: W4 y9 k& c; v  r2 [7 u% H

  39. : P: k& y" j5 h; T, w3 W% X" a! r
  40.   /* USER CODE END UART4_Init 2 */
    3 Z) A9 L( ~3 ?3 W' ]" |7 C
  41. 3 {) H/ v8 s/ F* }) d  Y. H2 m
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)
    6 ^- e. p) k/ \0 U& Q7 d6 \
  2. {! Y$ i1 K1 `  Q- r  E# F; i
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};. A; u4 t2 R" L, g
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    % ?$ e5 w/ n5 W* L& ^& e: I
  5.   if(huart->Instance==UART4)% P) Y. k+ m- Z& x' K- I. }$ J5 i
  6.   {  B5 w& m7 q& x
  7.   /* USER CODE BEGIN UART4_MspInit 0 */
    0 y5 g2 G3 |- v% e; y( U* H; i2 d

  8. ( H+ G! {. d6 d+ Z5 A' o$ r
  9.   /* USER CODE END UART4_MspInit 0 */8 ]2 y# ~+ M- {' p

  10. ! w; {8 {5 p* ~, U2 o+ N1 @
  11.   /** Initializes the peripherals clock
    / J0 Q8 B& R/ {& U0 ~; u  w
  12.   */+ K$ Q2 t! a) m, w7 p7 J7 }0 l
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;
    / {& Z/ b& n7 c/ l
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;+ F  @6 h) ~1 N' l, t4 l
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    5 u/ m7 R5 u$ c1 [0 G9 C1 I
  16.     {6 v6 R7 B' H/ i
  17.       Error_Handler();( E2 t! a9 f9 w/ G$ ^/ T+ c. i
  18.     }
    3 L. m) w3 y# B: A. U8 x

  19. % x" ?' g$ w; a2 V* M8 V6 r: C& t
  20.     /* Peripheral clock enable */
    1 J) y3 Y9 L* h$ d+ C8 ~( V3 P
  21.     __HAL_RCC_UART4_CLK_ENABLE();. ~( P0 `; L$ x4 S- f

  22. % W4 r* ]; x* y5 P$ h5 h& k, K
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    & P/ R, _( J2 x! H3 y
  24.     /**UART4 GPIO Configuration6 L) h3 A* J# z- P  L
  25.     PD1     ------> UART4_TX1 v/ J6 i. R0 Q- k1 k2 m$ _: Q3 ]
  26.     PD0     ------> UART4_RX
    7 {+ e9 B: {( @( A7 Y
  27.     */  v8 k; V9 L% F3 G. S8 ^: l
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
    ' k, `" O: P9 ~& D9 q9 ?0 p9 D
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    8 H! c& Q( f4 X* f7 \
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;. y4 v5 Q$ @! ~1 N" Z7 d" M
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;- w& Q9 n* w! b* C& g& C: h
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    " m4 b6 }' ~0 H* k
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    % F) N& {: P$ O3 ?, _5 b* L  W# G
  34. 3 g$ U( b7 |7 A1 s( A6 I
  35.   /* USER CODE BEGIN UART4_MspInit 1 */
    7 w* d! ]! m$ Q, {, ^
  36. . k" x7 `2 Z6 v' |: F2 r
  37.   /* USER CODE END UART4_MspInit 1 */3 Y$ c' `$ H, V9 J

  38. 2 f" o6 C7 C6 h2 f0 d
  39.   }
    3 }( X: L- {  V/ I

  40. - u. t3 G4 q- W& n7 {" |
  41. }
    * B7 f6 F7 y- Y7 g8 b8 C4 B
复制代码
  1. 使用cubeIDE
    ; e7 }- d& F) h! s
  2. __io_putchar(int ch)
    ! }* B2 t1 j2 c# f) h
  3. {- `3 W! y  |& z0 c- R& J
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);& n, y! p  s. W/ U
  5.   return ch;
    7 J' n: y6 ^9 n( u8 F7 k; h5 `! T
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下
5 H% p) h) [7 D$ u$ M0 H( H8 A       c.png , h, q/ b- ~/ e: v% f
       添加输入输出头文件stdio后,就可以试试程序如何了。: Q$ E% Y2 q/ `+ \- `0 _5 f5 T
       d.png 4 |' Y. g- V" V3 V& v7 w9 Z; L7 S
       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。
9 F4 K$ @+ ]3 B1 V5 N& z/ D- u: C8 i      
6 z: Z; v7 M$ w3 Q7 m
  1. static void ViewRootDir(void)3 t; p2 G$ {+ R+ t4 q! h8 H& A! j
  2. {& n2 P7 L; q; o7 s1 R) o# ^
  3.         FRESULT result;! H3 P2 }- m# l1 z
  4.         uint32_t cnt = 0;
    ' Q8 e" b7 l- T3 S* a  r
  5.         FILINFO fno;6 r9 U5 [' u- u) A& v

  6. ( J0 v6 X& _/ W

  7. ; s" X0 \1 u- |7 G9 t( [
  8.         /* 挂载文件系统 */+ b) O' e1 b& d4 M3 k8 I5 i
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */' {5 ^2 n! n6 w# n
  10.         if (result != FR_OK)8 q) v+ |5 o! \( H; t! ~2 ?
  11.         {: y7 Q) @1 X/ p
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
    - w; D6 u8 J: ~: @3 }- Z0 m0 d
  13.         }
    2 x4 p' R7 b1 Q  _. [- X+ t  M+ G2 f6 B
  14. $ ]8 z3 ^, k  g( j$ Y0 \) h# t/ S% I2 x
  15.         /* 打开根文件夹 */, D, }. m" D; G4 e! [
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */
    ) ?/ T3 O' w& `% y, N
  17.         if (result != FR_OK)% ^4 h+ s) E: @% S4 j# F
  18.         {
    5 V9 E1 o+ c1 B3 C% N* k
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);. R3 ?6 V( a5 |. J3 _6 n' [$ D
  20.                 return;3 l1 z! [+ U# ^9 @: \% D
  21.         }( c# K7 G2 ?2 a3 h' s' P
  22. * A1 H7 @  U0 {( N: \
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");
    4 g! ]' t) h( U# ]# e; |! ^' f
  24.         for (cnt = 0; ;cnt++)6 z; a* Q. ?$ o" B6 Y. _. w6 i* i) h
  25.         {
    7 M- i: R: |! {: [# B
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */
    % x- B$ h4 b( }; N4 t
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)
    / C  u9 Z. e' D2 M
  28.                 {
    ' [( p& z) Z# V, n" D% }+ I/ J
  29.                         break;# u8 D( v" v& {' v
  30.                 }+ p+ v$ R- K% @& I
  31. ; q- c& }& N5 Z! N6 |" q
  32.                 if (FileInf.fname[0] == '.')
    ) N! ^+ m+ x% p# {
  33.                 {
    , T7 F) f) \8 u' C/ @
  34.                         continue;) M- |, G, S- @( D* D2 j; s
  35.                 }6 `# P+ \: R7 o) Q

  36. 0 q; V- g8 j3 g* W5 D
  37.                 /* 判断是文件还是子目录 */( c% F3 E) d  v' P! @. p
  38.                 if (FileInf.fattrib & AM_DIR)
    6 ]6 x2 z$ E0 _/ H/ w; B* m9 x
  39.                 {
    * e1 ^* X( {7 y% R( s7 q
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);7 w/ i0 J8 \0 v. b- h7 Y3 @0 I$ j
  41.                 }3 c/ h7 ?+ o* C: Y" }% X- x
  42.                 else' P5 K7 b9 @. W, w5 }. Y
  43.                 {0 M' S, y" ?9 z; ^1 h, U* w+ L2 q/ j
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);
    9 Z; ~: b" }* B) L. [, W# L% u
  45.                 }5 j4 {3 [1 X$ N

  46. & Y8 ]- U. e: P  u3 l
  47.                 f_stat(FileInf.fname, &fno);
    3 g" q' y1 y: K+ \
  48. % w: ~' f, Q" ]* h$ b
  49.                 /* 打印文件大小, 最大4G */4 M( v+ z& H. K* j
  50.                 printf(" %10d", (int)fno.fsize);
    7 @' ?! z& y) o9 l; ~( h/ K

  51. - F0 k1 q2 d- L$ E" E3 n" z( N

  52. 3 Y1 M: Q0 t6 P% I8 j9 n" N
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */
    - P6 f. p7 `9 l6 v! _
  54.         }7 _) o! F8 O* s& X2 I1 F

  55. % \9 R# G1 m5 i; x5 K
  56.     /* 打印卡速度信息 */
    1 C8 M' i" Q* j3 B; c: O$ b- k- ^
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)& W% g. P8 R9 |
  58.     {+ q- ]: e: Q6 U$ Y+ j  O
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");
    9 X1 X9 j0 S- B+ P/ }
  60.     }5 Y* @5 l( f- U& w) T$ j
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)% M9 w$ t: B' J
  62.     {/ B0 a0 r5 Z" C# `6 g: F
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");
    1 ^3 i4 T, G* Y' x/ T. c
  64.     }4 V8 c4 |* B  r4 |8 i7 z
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)3 `! N  F. j* _- b8 t- N
  66.     {
    $ q/ M+ v* a# h  _
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    9 v! i# R' @- h! I
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");# ~* X! r6 l2 P3 G0 X
  69.     }
    ; [" h) v: H, x" V( M+ `
  70. ) D! _( x* Q' K6 s

  71. % Q+ k1 ?' Q) [, V8 D
  72.         /* 卸载文件系统 */
    0 g$ ?- G2 [# f
  73.          f_mount(NULL, DiskPath, 0);
    4 n0 }0 G* m  K5 H( B1 u& m2 I
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。
+ V( {  v  g+ b2 F; ~+ O+ R      e.png
6 S2 t  O0 P) v6 W$ j, @     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。
- s6 \9 _% ?, f; ?, j1 T( Y 添加的内容为 -fexec-charset=GBK,还是修改编码的意思。2 k! j& [; k, p8 \9 o
      f.png
- C3 r# _# M; G+ R     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了
4 }+ Z+ a. d3 L8 B+ |( U; `       g.png 0 E  T: M( f% `$ b+ [
      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可* h0 k( H4 D8 \) U/ F. S
       h.png   e- K4 \9 j( K* s
      料想这次应该没毛病了。结果,新的意外又出现了。
/ Y/ f$ p$ X- h9 z, L  t, V. Z$ J+ _       i.png
- S( Y/ i. Y. T- v       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。  y1 Q* E4 b5 }, B
      j.png k.png
0 h: j* \0 m& M6 W; G    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。4 w" h" J& _2 q8 \

2 D" t1 q. {9 G' r9 Q% U      ; d! m( k- N. G  w7 C( I
4 _5 Q# R& }: |: ^, p3 a

& _$ }. E' ^' s, D$ r( B
' d' A: b; M1 S; E
! G# q( V( D: R+ A1 v8 Y6 f
收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版