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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。
) w+ m2 B( ?2 a6 s- D' u. t
' X) p# ]( k8 ?+ B    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。$ W/ t, D+ k- A- x
    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号; I  \" g% q1 Y# {9 `
      b.png + R) c1 @/ ?2 Y% s! H
     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下
- R' I5 t1 i2 B$ c# n; ^1 x      6 X2 P, y1 j0 g! `) G! t
  1. static void MX_UART4_Init(void)
    ! S& E# }; `/ X' C0 R% e
  2. {
    $ _& Z4 w3 Z: V* X6 X
  3. * p7 |/ e  @: q3 F
  4.   /* USER CODE BEGIN UART4_Init 0 */( g8 a$ N5 n. r2 T
  5. & P/ e9 v0 r, M  G% x. k: k0 c, N+ U
  6.   /* USER CODE END UART4_Init 0 */- @, m6 `$ |( q3 P6 ?
  7. 8 u4 P5 p) D- ]( I' Q
  8.   /* USER CODE BEGIN UART4_Init 1 */4 O1 ?5 d( j" P! A
  9. % b& \  \% X# Y* V( s, K* s
  10.   /* USER CODE END UART4_Init 1 */
    ) }# G9 h$ U9 [; D3 G, B+ g. {
  11.   huart4.Instance = UART4;
    * D9 L9 s) \. g" x: w
  12.   huart4.Init.BaudRate = 115200;
    # O! T0 M. H0 T! u6 e% V
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    2 p$ d9 N- o% ]: g4 ?
  14.   huart4.Init.StopBits = UART_STOPBITS_1;
    1 F7 L# M: D; s6 v" \! u! Q6 Z
  15.   huart4.Init.Parity = UART_PARITY_NONE;
    7 P) z2 c6 @- \$ b
  16.   huart4.Init.Mode = UART_MODE_TX_RX;
    5 T: X/ S9 s+ P) m( M8 R( g
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;! N" l! A9 c" P7 J* R7 q
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;6 i4 ?+ C+ ?& x6 t# n9 y5 {# L
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    4 W( m3 _( m$ p! |8 z
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    - U/ v) [3 M) p
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    9 q6 E3 _3 z5 g; ]+ O
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)
    " D$ d2 Y6 Q, {2 n
  23.   {
    ! p! m* c) w% y: a/ a8 G; r* j0 N
  24.     Error_Handler();
    ' j0 _( G2 h( Y3 U$ _) l4 K
  25.   }
    9 y* H: e' f* Y9 F* \
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)& N5 m6 e  J5 s# Y
  27.   {
    6 D1 x! f, q& }
  28.     Error_Handler();2 |, w6 S; A6 e  m$ u+ p
  29.   }, m- D; L: O. O. L$ c# T
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)& }3 t: Y: ~& u# i
  31.   {* T& A2 l. H' U8 J
  32.     Error_Handler();/ _! Z) W4 x8 @0 u+ y1 H1 a$ N" y
  33.   }
    * g+ D* C4 j/ T7 e$ g
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)# ^2 M2 K9 _* \) H* I7 g& h/ h
  35.   {7 ]- N/ b8 K7 X& Z
  36.     Error_Handler();
    0 ^9 P1 N$ R( U5 D( o% r
  37.   }
    " M) }  [4 {, f0 }: t* p
  38.   /* USER CODE BEGIN UART4_Init 2 */
    . U8 h) y* U, \3 v

  39.   s! G, M5 Q) L3 d# y3 V" {! }
  40.   /* USER CODE END UART4_Init 2 */0 h8 o, [4 c2 c- ~/ T
  41. 1 F$ r: t* m+ R, {
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)8 _, ^' e. D! Q) J: w* T( s. p
  2. {6 V1 ]! h' O3 f
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};! [, \- l. n; E4 r+ b" o8 ~
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};' V" x2 W& {2 r! h
  5.   if(huart->Instance==UART4)+ h) |. z: ~  l5 _* E! g. E! D/ P
  6.   {
    ) |: v" K! k& E
  7.   /* USER CODE BEGIN UART4_MspInit 0 */  f- [& y9 T0 L$ K8 y) b4 i. n
  8. 2 O$ C8 I' Q6 V. L
  9.   /* USER CODE END UART4_MspInit 0 */
    1 C1 s; p/ c6 ]9 c  w: O( _
  10. * k+ a; {, V- |+ @% G: \) U
  11.   /** Initializes the peripherals clock
    % j+ a/ ?: w2 i. [( O7 W/ z4 ]8 F
  12.   */8 M- {7 K4 x  k
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;4 E1 ^" D' w5 N5 s9 I6 {1 v  ]
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;
    . s2 D8 {4 T, v& V8 h+ P' P: z
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    5 u* v$ ?4 ]2 W5 T: j
  16.     {
    - {( B* Q; m" e
  17.       Error_Handler();
    # A( K3 N! d" p" H" A  F/ P
  18.     }
    : z2 y  _' G, O) e8 G" W

  19. ' e0 }' j( s& t: T
  20.     /* Peripheral clock enable */
    8 t1 M5 Z' W6 l1 `. y
  21.     __HAL_RCC_UART4_CLK_ENABLE();
    * s0 U" u1 Z& l1 V

  22. 7 x5 _- Q( ?- z# ~6 h9 I! F
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    " x7 D9 i2 `* y1 T% F
  24.     /**UART4 GPIO Configuration
    & Y; X& M, l) v5 a5 e* W% B
  25.     PD1     ------> UART4_TX
    % }7 y$ I. ]( ]( p3 u' H
  26.     PD0     ------> UART4_RX
    6 e- k& h5 \$ E4 p/ H1 Z8 g; h' H
  27.     */
    . M2 P/ l; P" Y1 Q7 w' ?; D) M1 E
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
    " |: S8 b" {' d2 O9 w4 v1 \
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;" S# K  N3 @+ [: d- X
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    ! z9 v, \( ]  O3 E
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;; r: d* b7 m' n, r0 i
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    ) e) }7 m- f0 M
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);. U  L7 i9 l  ]: N
  34. 0 q3 r. U! Z  T' w( k, _
  35.   /* USER CODE BEGIN UART4_MspInit 1 */# X6 Y9 b' J+ y, a9 t3 j
  36. % Q& W! f# W! x) G! V, N
  37.   /* USER CODE END UART4_MspInit 1 */
    & c5 k. Y% p( W1 l1 D
  38. . I' T" d- m- p/ X# A( \8 p
  39.   }
    , ^& w$ H1 D# e9 [# K. I7 S

  40. ( n+ |' @1 p  I6 l3 t
  41. }! y" Y% g# P) D0 U" ]: f- g1 k
复制代码
  1. 使用cubeIDE+ r2 ^$ a/ E3 s$ y& Z
  2. __io_putchar(int ch)9 f  F- z: `1 b0 N( t/ a, s4 a
  3. {* p& I, K- P7 m: z: z5 i/ @8 d
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);8 J: `; F% |: S2 Z! o! C
  5.   return ch;
    0 x: Q: y" R; f& T, D
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下
/ {! q  p$ ^& M3 z6 A" P! T" D       c.png 5 a1 o! d5 `& S- M% k2 m6 P
       添加输入输出头文件stdio后,就可以试试程序如何了。
2 `& w1 L3 e0 M& U8 z( G! n: f       d.png
- D$ z; @7 w; t; `" N1 X. x       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。
$ D+ y3 b; Q7 ?1 y" y      ) q/ ?* Z0 i( e  w4 f0 ^5 c
  1. static void ViewRootDir(void)
    ) w; T; a3 @7 n5 r0 L2 n1 M
  2. {0 s, `9 ~- y9 [  f
  3.         FRESULT result;6 U( S: ?# `& V" a6 u( f5 S
  4.         uint32_t cnt = 0;
    0 B" V8 ?4 G' h9 J
  5.         FILINFO fno;
    1 l) Y* z) t- n$ u: }

  6. ! A& q7 |8 ~0 b$ o3 i6 U9 E% }8 x; h& o
  7. 1 I, {  s0 U5 H! n
  8.         /* 挂载文件系统 */. _, P- M/ \- y% k* f
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */! [9 v+ X" d/ z* Q( v3 Q% I
  10.         if (result != FR_OK): i7 g" k3 g2 n5 n1 R& M& x
  11.         {9 b' u& ^* b3 S9 S, R! D
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
    0 f: z8 s* o! E1 l1 j( U9 r. o
  13.         }% E. d3 R) h8 w  y

  14. 2 }" I$ D; O. ?3 ]4 R
  15.         /* 打开根文件夹 */
    $ U( v& q: }8 W1 w4 b* l& t
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */- ~" H) d& Y6 c- H$ |: U
  17.         if (result != FR_OK), K, [$ L2 R, i5 }
  18.         {
    6 Q, L& a9 _. h1 @* e% d( n9 t5 L
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);& r# F2 f- N0 E6 x- E
  20.                 return;
    8 n: S% l0 A8 G' x& g1 t
  21.         }
    ' v) z5 {7 K  ]7 |

  22. 4 _" p4 i  S! O% E7 ?
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");
    0 \7 z& X7 W1 T% k2 P$ R
  24.         for (cnt = 0; ;cnt++)
    ' G% c8 J0 C: t: }6 w  R7 E
  25.         {
    . a* g! n5 ?9 r& h% \
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */: A: `" w0 O1 d: z
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)2 V; U9 \' f. V' o+ U4 H
  28.                 {
    5 q  B6 J4 g' T, q
  29.                         break;5 A% I$ A5 V* |# u" y: `4 X
  30.                 }5 T# [% H* p$ ^8 A: [# m( ]" S
  31. # a! m9 B1 L6 [
  32.                 if (FileInf.fname[0] == '.')/ h7 H/ `5 H* T8 H3 E% g& F
  33.                 {2 E/ f5 }$ U. X( n
  34.                         continue;- i6 l0 Q7 ~% ?0 T) @
  35.                 }$ W, G$ u6 M6 T, {% ?3 q1 x

  36. ' |1 W% S6 f0 |) G  }
  37.                 /* 判断是文件还是子目录 */
    7 i7 ~3 t: _6 t/ u/ H5 C3 i6 z
  38.                 if (FileInf.fattrib & AM_DIR)$ c1 [) t. T5 P( h: m+ T; f$ V, K' U" y" ]
  39.                 {2 b5 T" d. v4 Z% w9 B# }' D, V2 u
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);
    3 W- ~) j9 e( Q* U
  41.                 }
    ) @1 ]; s0 c$ W: L0 M
  42.                 else' B# n! |" k0 ~2 C$ I, q
  43.                 {9 D) m) r4 L/ Y0 O5 a
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);5 s9 ^" s, s  c
  45.                 }% S9 l( v& V) g  o6 e" `2 u

  46.   J' ^# @. z# e; f1 M4 t
  47.                 f_stat(FileInf.fname, &fno);2 i* M7 s# m) t3 _: b

  48. ) ?' e/ A- H1 q: o/ W
  49.                 /* 打印文件大小, 最大4G */
      P2 K& m( ^  C0 G2 t# e
  50.                 printf(" %10d", (int)fno.fsize);
    + |8 Z& [% [: m/ I

  51. 3 R: M( k5 Z5 k& k& \2 r

  52. * \1 v6 b6 |; ]8 j6 {
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */' ?  B/ E1 ^' o
  54.         }
    3 x! |! q) {7 n" P& T% Q

  55. " K+ o7 q! m* c& R9 n9 Q
  56.     /* 打印卡速度信息 */
    " n7 P5 X- c. S' T0 I
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)- L+ T5 `! f/ X. u! E
  58.     {+ Z( i, u5 t) h) @
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");
    ) y. ^1 R( T6 U( ^
  60.     }' v$ w" H7 L* ~6 P$ e
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)
    " H8 Y7 j/ w2 Q' @* s# p. r+ T
  62.     {. \  M: A: z& u8 U5 f! y- T" ]
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");
    / x, l; A4 i% H0 D. g; @& k, P
  64.     }
    ; u6 ^% f3 v( _+ ~+ S8 S) w
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)
    6 t$ e% u6 T* [. s
  66.     {
    ! ~# [. x0 H# Z- i, q# L; `; @
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    + C2 y. K$ O4 q- ^
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");
    ) ?0 L4 R" B. L* ~
  69.     }0 Z; B7 y$ V5 D5 _

  70. % }. y1 m7 x0 d- P
  71. ( C8 Q; q6 y8 d+ }, m9 e  |$ B
  72.         /* 卸载文件系统 */' Z; b( i: f' T; a8 Z  g* d$ w) p
  73.          f_mount(NULL, DiskPath, 0);) I* D" I" V# D. m) G
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。
/ \4 _. s' m0 x# U      e.png   k3 S% k7 u7 g$ _2 o3 \) B& ~% m
     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。3 o* x  n$ I, O, @+ {# ~. g
添加的内容为 -fexec-charset=GBK,还是修改编码的意思。  b  I- F4 I+ S3 r; W
      f.png
" [$ g. ~) g/ P  s" z' T     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了
# O: W8 p+ s/ f: B' Z6 n       g.png & p/ N! X) B2 {$ ^" ^
      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可  f) D7 d; E0 X
       h.png / \& `% t4 k+ Y
      料想这次应该没毛病了。结果,新的意外又出现了。" [# n- H9 a" G  G
       i.png
% L( r2 p  R+ @- E9 o* u       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。
( G2 H' G4 T8 \1 ^* g      j.png k.png
  T) V% J+ v" P  N' x    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。
8 [% U% [& ]7 W, S$ x- {2 I" S0 w5 E' z# d  P6 ?* S
      / L+ @5 z4 [5 x- r$ u. N

1 R- E: h8 d% U" G9 o2 \+ k9 a( |6 b' J- W! j$ h

$ K8 b# a. v5 }5 ~8 R: z' d1 Z, F2 x
! |5 E; }& f: v/ J  \, G
赞 收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

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