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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    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
      b.png
4 ~3 Q. T1 Q$ j. e3 J     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下; H6 |/ t7 _* B
      5 n- ^# Q8 @+ @3 O  v. B6 j$ D
  1. static void MX_UART4_Init(void)" @3 h- P' N: ?+ v
  2. {+ D+ k- }8 m4 S$ I
  3. " f1 d# L- G& P1 G4 K; N
  4.   /* USER CODE BEGIN UART4_Init 0 */
    6 u( b! ~$ M* W& X5 U

  5. % I: h. ~7 k  `8 o6 T: a
  6.   /* USER CODE END UART4_Init 0 */
      g# F! ?9 I* P' }+ k4 Y
  7. % Y8 y, @7 U7 G& Z
  8.   /* USER CODE BEGIN UART4_Init 1 */4 p/ v9 Y8 T' n. ]

  9. & d0 ^9 f9 e4 u* i) b
  10.   /* USER CODE END UART4_Init 1 */
    . t) W- X( s; \* a1 ]+ }! {: }2 d
  11.   huart4.Instance = UART4;% i5 F) [( u. I# t6 Q2 k5 g( H
  12.   huart4.Init.BaudRate = 115200;
    $ c; U0 I! U) e
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    5 Q& k6 K% b! W$ Z$ A3 l  q. Y
  14.   huart4.Init.StopBits = UART_STOPBITS_1;1 c2 j) w% M) z! N3 }6 d& |
  15.   huart4.Init.Parity = UART_PARITY_NONE;! q) r3 ?" g7 B% @
  16.   huart4.Init.Mode = UART_MODE_TX_RX;/ b. @4 b  A( E9 I* Z
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
      x/ z3 u8 h/ D# \5 o( q
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    ; R8 f( j; _) G1 c- ]; ~, F6 e
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;6 ]" N9 N0 g5 K+ G% F7 Z
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    7 d% K+ u# n, x6 D. V" T
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;/ r/ N* V, W, g  {# s
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)1 }4 u9 z" E& m+ t) S8 u
  23.   {
    # o2 b0 w8 F. [1 ?9 y
  24.     Error_Handler();* j/ J# d; t7 O% _! {" _& o
  25.   }
    4 T0 C2 @9 A2 P$ _
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
    4 A! j. D9 w2 L$ |3 y
  27.   {/ N" W' N4 @' j* ?/ d) n9 K
  28.     Error_Handler();
    % e* [8 I: h& r- p
  29.   }
    - |7 \$ _! ~  V' k/ q  L
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
    8 r) w3 d* v% Q; d
  31.   {- B" Z0 s- G; R$ V0 C) p9 s
  32.     Error_Handler();
    , l, K& h( H- @1 X
  33.   }! @( u) m8 `0 D" U8 U
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)6 z8 I4 O& |. z' B) L/ Q
  35.   {+ E+ r5 ]# a; j: ]) j6 l; F- U
  36.     Error_Handler();& y2 E9 i7 h# `1 t( R! r
  37.   }% a$ o! a& y: G, c( b* A$ g
  38.   /* USER CODE BEGIN UART4_Init 2 */4 [; j( `8 \# g6 K+ j8 C

  39. " K! O1 [/ s1 w) e( ?
  40.   /* USER CODE END UART4_Init 2 */& f. T- A$ f2 n* y$ B

  41. ( F% ]* E$ E3 u+ _. N9 o
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)' z/ b2 E( A5 ^! A( R
  2. {
    3 N3 ]. W9 `+ ^0 g
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    3 N+ K! s1 ]% j9 w- z
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    / t& m) \# {+ x0 ?8 u( s- B
  5.   if(huart->Instance==UART4)" L1 |# R9 U- x; D/ H
  6.   {
    ) j  |# x  M; c1 _: o5 K& U0 r
  7.   /* USER CODE BEGIN UART4_MspInit 0 */- e- d5 }% h7 s1 s& ~

  8. . Z7 F/ f. B6 _
  9.   /* USER CODE END UART4_MspInit 0 */. m. [, L/ z' P: F
  10. ; {/ L8 z: }' V4 f
  11.   /** Initializes the peripherals clock' K5 [% A9 `( s5 P
  12.   */% g$ ]) v+ N9 `9 {
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;
    6 _3 B1 T% i$ t) {2 e3 x, N
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;
    1 `, x; @& \2 j
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)9 S( H  s: ~/ ?9 D2 J1 N+ i. [6 K) G
  16.     {
    & V6 g: x1 e( f" L1 u1 |7 _
  17.       Error_Handler();
    ; {' U0 N5 b) U! _. z
  18.     }6 s; M0 e7 w% O6 U5 ]

  19. : y: x8 r# d6 f$ {8 j4 h2 F
  20.     /* Peripheral clock enable */( a- d" N8 j3 E3 c
  21.     __HAL_RCC_UART4_CLK_ENABLE();" g4 f; ?/ _! `% B, w  [5 d# W

  22. & p+ f# Z% P2 A( X. M+ W$ _
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    ' q( Y4 B4 M) L' S( H4 F1 k
  24.     /**UART4 GPIO Configuration
    + @! P% J8 L8 L" k* \/ d
  25.     PD1     ------> UART4_TX6 k0 D" {! b3 W. v
  26.     PD0     ------> UART4_RX
    " h& r8 o  C) l$ v- m' ]
  27.     */: U. k1 ?  r' L2 l2 D
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
    # v+ }( f6 k! v4 w  l, f/ S
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    # w/ u( A2 D" F# y, \1 q6 R' A
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    2 p* u) O; n8 G1 s3 |) \  F: y8 m" i
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;) z/ G. }! u# @4 q, j) b  }' `
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    : y1 T5 e0 A, ]- N4 r  C
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);5 f9 @6 p3 t. K! g/ d

  34. 8 m6 Y; v) \8 a+ Z* M
  35.   /* USER CODE BEGIN UART4_MspInit 1 */' _& O  c8 g8 m% P) R) K/ O1 J9 W8 A
  36. ' G2 |8 S) O: C8 g1 y4 n+ U
  37.   /* USER CODE END UART4_MspInit 1 */1 J( m( ]: g* Y9 u$ o% l! m

  38. 0 s! F5 ?- g' h
  39.   }, p; V& K" [; I8 i8 R
  40. 0 j$ ]! P# ~8 ]" `- `* K5 Z
  41. }* y, ^( I" t' ]- y& a
复制代码
  1. 使用cubeIDE- [9 ?6 G* f5 c
  2. __io_putchar(int ch)& i6 V- s' i! x! N8 O  Z* G+ O* b+ Y
  3. {
    9 |" z! k4 E$ G1 f+ P3 o' u
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);* N1 ]9 ^5 t; D* o
  5.   return ch;
    * }* p' ~: D: r) S: ~
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下6 R- R2 V7 I1 X) V: o8 Q3 g3 ?' q
       c.png - y& i3 I, g" R) W# i( x4 M
       添加输入输出头文件stdio后,就可以试试程序如何了。
8 d3 F( }4 U1 J' J       d.png
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
  1. static void ViewRootDir(void). v' O+ y& m/ v  S7 \% L
  2. {
    , A7 j7 k9 N: x* }5 W3 f  u+ ~' f9 O
  3.         FRESULT result;5 d* x/ v, |7 u+ J: G* ^
  4.         uint32_t cnt = 0;
    3 a. c5 b4 w9 z0 C
  5.         FILINFO fno;' C) B! [# S7 A6 {" E
  6. 6 N1 V  A9 `  r5 @$ g* s

  7. 2 t$ \- |, l& k
  8.         /* 挂载文件系统 */6 A  v8 G6 x2 j% p& c+ ?6 }
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */
    # v. d' P; f2 O
  10.         if (result != FR_OK). m0 n1 _+ c+ u2 V2 l0 s' M8 B/ i1 n5 t) H8 V
  11.         {
      B. s: X) b$ K, ]
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
    / V4 ^2 R) l( k/ D8 `5 y1 b
  13.         }
    0 ]- Q' O3 V* _: O8 ]4 q7 s2 {
  14. - f( ^/ ^7 ]8 S1 ~7 s/ R. Q3 `
  15.         /* 打开根文件夹 */
    3 v- n; M0 P/ Q; J6 k2 f& D
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */
    8 g" ?  e2 @! `; Q9 f
  17.         if (result != FR_OK)/ P) l' L7 V1 h2 V6 L' J1 c! g
  18.         {
    + y! t7 P" E( c: g
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);; F" [8 A4 `$ M# a
  20.                 return;) r  M3 s' U5 H! a4 Z& X
  21.         }0 y, E! N) l5 D+ ]% }: d
  22. ' u  T+ |/ O# ?1 [$ f# R
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");  g0 [6 x) z: ^( I+ E$ @
  24.         for (cnt = 0; ;cnt++)
    1 H! N  a  z8 J# d8 a+ z- R
  25.         {
    5 Z5 u* J6 J* {4 l
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */
    * S9 c/ I* C- K+ s. w4 S- }0 b
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)3 u) }$ K  i2 F4 j* b1 w  R$ S: \
  28.                 {: W' T* H2 o- C$ o7 {
  29.                         break;2 Q* ~  `% r: ?+ F7 M
  30.                 }* ^6 v7 m7 @' U1 p; j% ~; c5 o

  31. 4 i  t) G! \$ G# X5 k0 f
  32.                 if (FileInf.fname[0] == '.')
    2 {4 z$ s  X: v% o: Q
  33.                 {
    4 E" F8 w' M6 S: S4 ?, T
  34.                         continue;
    9 S4 a, u, @8 J9 m8 p/ J: S
  35.                 }
    4 G0 R, y4 E# u# Q- j1 J0 S
  36. & [% e6 j0 s  C- ^3 r2 ]/ R( I
  37.                 /* 判断是文件还是子目录 */
    % E; N2 {$ f. {9 X9 C+ [2 n' t+ p7 X2 Z
  38.                 if (FileInf.fattrib & AM_DIR): \0 f' Z3 E% u) C3 W4 j8 J
  39.                 {7 ~0 R* X8 y& m( I, h; w! N! g
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);  p$ N& y( C8 b* y9 w) [% D! J
  41.                 }4 D* }: f3 O& d: w) W0 Z' y
  42.                 else
    7 X+ M/ o. f* J, N0 L
  43.                 {
    7 e$ J) D5 ]5 k* w0 r2 e
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);* W1 B$ P  {( M2 l) a8 Q6 _; G5 c
  45.                 }' i) E6 @& t/ g& x% h6 I; F" E
  46.   x+ F" }6 h5 _# N
  47.                 f_stat(FileInf.fname, &fno);! k2 i1 F% @8 h" @
  48. & n4 J+ f8 d# ^- r+ Z0 M
  49.                 /* 打印文件大小, 最大4G */
    + E! N$ |4 m6 ]
  50.                 printf(" %10d", (int)fno.fsize);
    7 c. G$ \9 H' f# v- o! x# [0 l
  51. / C$ P! L& C8 T7 A2 M
  52. ( j( x4 o! J- ?$ L: w
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */
    * h0 T4 E) ~( Q$ N! u
  54.         }
    * I( F3 l2 b/ ?4 v+ b5 \" v( B
  55. 9 B; @0 E3 h% ?9 ~3 `: \6 I& P
  56.     /* 打印卡速度信息 */8 U6 F8 l' m( @
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED); N" a9 i" q! \; ~& M0 |# [
  58.     {( t  T3 E2 t; l) M% p5 T: ~: q
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");
    ! r3 D2 V9 ]. W" L: m1 z
  60.     }
    1 B4 v' X# ~& ~3 g4 r
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED); B0 Y8 W. P( ~- ]& R4 @
  62.     {
    - j4 _; K; N7 x: R6 |4 a
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");5 A0 W& ?) G$ q2 q% O/ ^, Y6 T
  64.     }7 j$ e6 Y. [$ ?( H
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)4 f9 ?/ h. j% O3 i
  66.     {* k" Q& B/ g; i8 }) e
  67.         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
  68.         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 ?
  69.     }/ M' P( a+ `. P$ u9 @( v

  70. ; J9 d3 {0 S5 a- ~' ^% H# y* Q
  71. ; D) b& n+ a/ i$ u
  72.         /* 卸载文件系统 */
    2 T6 |( E* T" {
  73.          f_mount(NULL, DiskPath, 0);! N5 b  }  B6 u( e5 |  A) `& r- ~
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。
9 E1 h+ {3 G# ]- t5 t      e.png
+ 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
      f.png
* ^2 y4 b: [9 ?# d4 q2 ?     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了
1 h, |" }: F/ h6 [5 U       g.png * u5 d3 t# f. Z
      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
! C7 x. v9 ^) d+ H, M0 P* Z% f9 u       h.png 3 h! [; v& `* |6 S6 R
      料想这次应该没毛病了。结果,新的意外又出现了。
- ^2 a5 P+ g8 B: @7 `       i.png
0 E) e+ z  a0 t       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。9 `& x- R4 A$ a5 x" J& h
      j.png k.png
  ?; 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
赞 收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版