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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。
' O' m4 o7 i3 T- L' \1 X2 V3 D4 d
0 b' [. u9 t  _* I/ n    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。0 `* z8 o( S8 y8 ]# ]" k% V1 y4 U+ S
    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号
+ j3 y/ V! W  d1 j$ ?      b.png 2 |- J  c0 k3 n* L+ i# k
     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下
' \+ E) _3 Y9 O2 x% O; o      ) l8 g% C! C1 O2 z# @% D
  1. static void MX_UART4_Init(void)
    1 G$ J# N- I3 x0 O! f, b) L! J$ j
  2. {, X7 p* y1 P0 @) w1 S. R8 Q' ]2 |

  3. 3 A% h, n( e  h% V* o" U. c
  4.   /* USER CODE BEGIN UART4_Init 0 */
    2 S8 e2 @5 `+ [
  5. + N/ p8 ~- q' m3 ~* h7 ?7 D
  6.   /* USER CODE END UART4_Init 0 */
    $ O# Q9 A  V- L4 |& ]) i( P( ]6 @

  7. 3 D! y% ?: j  \/ U5 d
  8.   /* USER CODE BEGIN UART4_Init 1 */! y7 v& G0 h2 o; m: [6 `+ U, L. ?
  9. / `3 x! Q. x5 X! e/ E7 Q) _
  10.   /* USER CODE END UART4_Init 1 */+ Z# H1 y; |$ C7 Z6 F3 B1 a
  11.   huart4.Instance = UART4;
    6 U9 @: h& m4 t4 \2 j2 E
  12.   huart4.Init.BaudRate = 115200;3 U# f9 k9 q1 h' j, K3 i
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;$ E$ d9 i: o+ x2 C2 }
  14.   huart4.Init.StopBits = UART_STOPBITS_1;: j- \7 t" |$ {& w/ H7 E
  15.   huart4.Init.Parity = UART_PARITY_NONE;
    * G, g' E$ N4 P, R+ q
  16.   huart4.Init.Mode = UART_MODE_TX_RX;  k0 h; j( ^0 Y2 [
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;/ k( K6 f6 m+ s, {; d- n
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    , H+ G6 U  T1 e% l9 V4 K3 Q
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;, g0 i& P3 x& ]2 Y, [/ W
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    / ?: j* G" p  `: A7 A$ `  M, v
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;8 @$ n& d9 S+ s4 U* v
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)1 S' |2 Q# \# s: O& K
  23.   {- F2 d$ _0 J, J
  24.     Error_Handler();
    ; q: M4 G" G$ R% F
  25.   }
    ! G( M3 H' s! _
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
    " Z: _' |8 v6 i1 B& c2 ?6 L8 `
  27.   {5 z  g9 g4 ^3 o( C7 `3 l; h+ {1 y
  28.     Error_Handler();- C, h# e. U) s! d' x" S5 \
  29.   }
    + K% n% f- G' @. C
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
    6 s/ L$ m) q9 `. d! p4 v
  31.   {! X: h2 z5 G% V( R+ V5 [# ~/ F
  32.     Error_Handler();8 @2 ^* h3 u2 t0 w; e; m4 P8 o0 I
  33.   }! G: e% M1 ^5 b
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)! Z0 b; l7 q5 P+ `3 p9 T: x, C) ?
  35.   {
    6 O) d$ c" i% e; m
  36.     Error_Handler();" A5 E! h8 B. \* ]$ ]( ]
  37.   }
    & S' B! k# |; Q
  38.   /* USER CODE BEGIN UART4_Init 2 */
    2 _. ]9 X" H* ~& p) a: Z

  39. % n7 X( q) \0 c& g+ {
  40.   /* USER CODE END UART4_Init 2 */
    8 J8 q7 v/ Q6 ^2 g$ t

  41. 4 e% G& o7 R- @# L. I
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart). w3 F, z6 @' R9 Y7 J6 f6 v& h
  2. {' p) \, K  K, y$ @8 Z, g- U
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};/ c" c& z6 T- W4 N" L0 ]
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    $ }) `# G: }+ c
  5.   if(huart->Instance==UART4)4 i3 a) M" l# J9 [, w9 e
  6.   {
    % N* C9 J7 d- T! @5 l( J5 h4 F
  7.   /* USER CODE BEGIN UART4_MspInit 0 */+ u6 ?6 ]% a5 B9 Z  i
  8. 2 c, ]# v2 p5 ^, a% p. q- v
  9.   /* USER CODE END UART4_MspInit 0 */
      O0 t: d7 Y" d6 H$ _0 Z
  10. / U2 J2 q3 s4 x/ O& U+ V
  11.   /** Initializes the peripherals clock
    ' e4 h0 S$ I( t: p2 G
  12.   */* C' b$ T0 D6 I" Q4 \( }
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;( @( j+ F* N) _' w
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;
    - T- h" O! Z4 i* @
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    , k/ q; N9 ?- l/ z
  16.     {
    " M8 b1 a: ]  M/ D( C5 W
  17.       Error_Handler();
    : j0 w/ G& O8 x4 z% y' Y# Q. t# H0 K
  18.     }! W' D/ E4 b+ v

  19.   _7 l' E9 X/ ?5 |' x
  20.     /* Peripheral clock enable */! b, ~* a% N6 P1 N1 k0 R1 v8 O; `
  21.     __HAL_RCC_UART4_CLK_ENABLE();
    * I9 C; B+ i: T4 t* `# ]0 Z3 m) F
  22. $ K" H. ]( @2 I  I7 c! I& }1 K
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    ; p$ u# C4 F: c' X
  24.     /**UART4 GPIO Configuration
    ! F" N, L5 m( k
  25.     PD1     ------> UART4_TX
    - p7 B( O0 ?3 h
  26.     PD0     ------> UART4_RX
    " l/ b8 [! O/ A. u& q4 I
  27.     */+ T; w5 L* h8 k* v
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;2 ~" i: d# U7 a! f- @
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    * G/ O+ J" f9 i& L9 A" \! g7 Q
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;, n% o& J- I: E  \6 @
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;0 n* A6 a# b; Y( K
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    ' _! n" J5 Q( L4 u# g8 i- a, Q
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    ; f! N2 q2 c  L: n+ @) K

  34. + {( f/ F  {$ {* C  ]6 z7 i, J
  35.   /* USER CODE BEGIN UART4_MspInit 1 */& v" [+ k8 H" G  Y
  36. % F+ B- `5 g- z% h! y
  37.   /* USER CODE END UART4_MspInit 1 */+ s- b1 X  h7 P4 K2 p7 r0 U& v
  38. 8 z; a7 A$ a5 K0 [6 m$ A
  39.   }
    0 @' f/ m+ D( {

  40. 9 B. [% N) U: |. s, r( a+ `9 D0 V! k
  41. }
    % g8 J2 C, e) n" g- f
复制代码
  1. 使用cubeIDE$ F8 \8 u1 q) [& p0 y! j
  2. __io_putchar(int ch)( v6 c3 M3 \9 Y5 W
  3. {: X9 E) Y1 P7 X3 q* u* r& d
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);
      f6 K6 t- ?( l; \! Z0 v" c
  5.   return ch;6 d8 ?( W+ ]- W
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下
* A4 I5 J* F$ w       c.png
  d1 c2 t, B5 K5 h( Q/ ]       添加输入输出头文件stdio后,就可以试试程序如何了。
& x9 u& i  Y) x' Q/ J9 m- B5 z! [       d.png
# x' t# H2 V4 B: W& H- [5 F  r% C       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。- ?5 k6 T2 b/ I" t! ^# C- ~
      
& }* Z3 q; [. Y3 a
  1. static void ViewRootDir(void), m8 x$ T/ B/ h, N
  2. {5 y* T% ~: `- `" U1 Z
  3.         FRESULT result;
    $ r% ~) v2 D4 u: k$ M
  4.         uint32_t cnt = 0;
    3 Y' K: q5 l2 F) d4 q7 z
  5.         FILINFO fno;# O3 R8 m8 N$ g3 |2 t+ y
  6. 2 z' V( |& n5 W! P

  7. + B3 |5 V6 O$ T7 S' v5 |
  8.         /* 挂载文件系统 */
    " u9 A' c, _, b: L1 I1 p& h- i. }: B! g
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */
    6 l3 h# E  K  p
  10.         if (result != FR_OK)
    ' B- v  B6 M( Y, C  [+ T- R
  11.         {
    $ H; q4 \4 ~  t: a
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
    5 g9 v- H+ _2 E
  13.         }# `, S/ i* o: d- A6 S( m
  14. + d4 |: R5 e0 W; V' d
  15.         /* 打开根文件夹 */# p: R. s/ o( z8 ~# [
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */
    : K% T; w+ \( `+ n4 v) e; O# J
  17.         if (result != FR_OK): h) S  l: ?/ q* y1 |
  18.         {
    3 }  d$ W: N" u0 A6 a3 F
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);4 y0 ~, Z) N$ w# R' a+ L2 }
  20.                 return;- ?: G# a$ l/ ~& O: N/ k4 {
  21.         }: r- b7 p, d) f- W  D5 N( f! `* Z
  22. 3 B1 e) Y5 N8 ^& |+ {% Y$ H
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");$ M6 @1 ?* |- E/ j' e
  24.         for (cnt = 0; ;cnt++)
    - I8 x* m3 X; v4 j, Q1 \
  25.         {( S' B& l" o. _% b' O$ J% @
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */
    # H& l+ ]5 m' G9 y
  27.                 if (result != FR_OK || FileInf.fname[0] == 0). s& a9 r1 |! Q  s, P& A1 v
  28.                 {
    $ V/ o! R, j/ r
  29.                         break;
    % X- Z4 M% o9 g' S
  30.                 }. h; H3 e( o0 T+ g# v% p
  31. * ?# q1 x, Q; X3 k
  32.                 if (FileInf.fname[0] == '.')
    ' w' F, I0 l; b$ d5 O. C
  33.                 {* _% ~! z% Y" a5 ^, }) q2 D* [, k& B
  34.                         continue;, z2 I. D& ^& F! a4 o. d
  35.                 }5 J: T% K" |- d8 o; p2 w2 ~& _
  36. - _% z, `; r5 d" t* N6 \
  37.                 /* 判断是文件还是子目录 */
    ! J! ^9 _% |/ a, A8 H: ^
  38.                 if (FileInf.fattrib & AM_DIR)
    / U, z" F* W! T) s' z. d+ L
  39.                 {) `$ p" _% R+ {1 E
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);
    : p# d1 g$ E7 h# y
  41.                 }
    - S$ V6 }  _5 O* S+ n0 \+ l5 C% K. [
  42.                 else, c, i9 W1 A% i$ f& G! f) V2 J
  43.                 {- H! m( o1 X: d; l! z1 f( D7 y8 J
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);
    - V5 H5 V3 P- x
  45.                 }. H5 q% T" ~/ `' k) @4 n

  46. % ^+ C0 Z4 l, b: B( @( l
  47.                 f_stat(FileInf.fname, &fno);
    ' H2 U, ^' ~( @7 A; {( g
  48. : R8 A; Q9 f+ D
  49.                 /* 打印文件大小, 最大4G */
    1 Z  W9 X4 a. v' D3 s$ d
  50.                 printf(" %10d", (int)fno.fsize);! |- g; Y4 Y( v, V: O4 K. K: X# O

  51. 9 e" t9 P" Z" v

  52. ' K2 J# K( Z2 K4 l( ^6 Z) B' M
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */
    ! a! p# n5 s) N0 X+ U, x
  54.         }
    ) b6 M  _3 A+ `4 z+ E

  55. ! b1 Q6 ^" C$ a  c' E
  56.     /* 打印卡速度信息 */+ `9 z- B8 t1 i! o8 N- }$ D
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED). |# r4 {3 E1 ]$ j- U* z
  58.     {9 K( x0 O* ?5 Q! }  J
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");+ o" z! w5 a. }, }! l2 g
  60.     }2 ~# M! u8 ~( @5 \( R' X' M
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)
    : Y  z5 Z# S% ^& V( [, Q
  62.     {
    , s5 e' R! D8 U; r- j8 W' D
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");
    * Z" H1 y( b3 P; i! H9 [" M
  64.     }" ?/ p- b3 E$ V* V8 t
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)
    : J7 G" }' ]; S& H
  66.     {
    : ^5 S* J2 e! a6 L
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");6 b3 L8 w6 i( i, p# n9 s) H
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");; u( H0 V0 u& a# t% Z7 y5 X
  69.     }! t8 c$ f; x( J7 Q! ^

  70. 1 F1 K0 |. ]& d7 ?6 e" R9 w

  71. 3 n" p- x7 r0 s, I6 P8 P
  72.         /* 卸载文件系统 */: K: J9 s1 v1 M  A/ c8 ?
  73.          f_mount(NULL, DiskPath, 0);8 g$ H- Y/ K* b/ a8 g- o4 y
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。- U+ S( |! k) u( N# F( V
      e.png 8 q" {7 o) l9 V7 ?+ m8 X
     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。
. I! U6 I7 D! E 添加的内容为 -fexec-charset=GBK,还是修改编码的意思。
( T! S; X; I" A9 H2 _( |      f.png ( _9 a% v% j5 s" `" @9 G) `" T1 E
     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了
, n- }# l, c8 ~9 l       g.png
$ Q0 Z/ p* n% m4 d      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
/ ~$ S% U+ g( ^9 t! F* B       h.png
2 Y( [6 H/ i; S) O  R; w, D# D4 M      料想这次应该没毛病了。结果,新的意外又出现了。
1 W. p1 Z3 N; Q! p9 a& D       i.png
2 r' S9 f! h% n) u' A& o       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。; T4 y$ Y. e9 m( B; v
      j.png k.png
# l: O* N) X' w* K1 W    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。
0 Q; J0 s& {; V* x: }$ S# N. v. G2 w" J+ J1 t1 W4 ~0 P6 x' W
      
3 P2 {% n; a6 W5 k0 q
. }- n) o7 I2 Q% K' y
  L: P! t& _5 C2 X2 V- }$ T+ m/ [) z3 B3 z
' u6 P* E7 [9 F# ?4 J
收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版