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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。
3 X) }& v4 k$ K+ q
3 G' e- U' F( {' e    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。
1 X  ?" q" W# d3 ]0 C9 l) j    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号
0 J5 B' Q$ J$ l1 }+ |4 B      b.png
& F* X9 }0 T( h* B' d( O7 b     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下
/ q3 {0 r0 @2 C/ k* j# M      
8 m% Z) ?% C" j
  1. static void MX_UART4_Init(void)
    / @" F! E- A0 g* n+ ^  S% B+ V
  2. {
    ! o& A) `' r1 Z" s0 V
  3. 5 m$ A- V* A4 E
  4.   /* USER CODE BEGIN UART4_Init 0 */- S+ v. @2 I5 n4 A0 E% h6 J
  5. & g2 V9 e( K* Q+ \
  6.   /* USER CODE END UART4_Init 0 */
    7 _" g$ }3 L7 b" U1 k
  7. - T+ d; [5 E% u2 \" n# }
  8.   /* USER CODE BEGIN UART4_Init 1 */7 J' Q! ^( ]0 e
  9. 7 W8 c: l" G: P: E. A
  10.   /* USER CODE END UART4_Init 1 */: x+ T$ c: F+ {
  11.   huart4.Instance = UART4;
    ) b, Q+ {- d9 c9 P; V# L5 X. W
  12.   huart4.Init.BaudRate = 115200;
    / i  k3 o: j2 M& F
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    # T4 A0 r5 V& ?0 d- `
  14.   huart4.Init.StopBits = UART_STOPBITS_1;7 y2 U6 ~# h) J& J
  15.   huart4.Init.Parity = UART_PARITY_NONE;
    % P" O8 W9 ~. O; j  @% R5 ^
  16.   huart4.Init.Mode = UART_MODE_TX_RX;
    % E. L; S8 V+ g2 Z3 ?
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    0 v! {. m1 K  R- n2 {% s5 i
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    ( M# }. E/ M; j# a6 I, K
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    5 _3 I# C5 s% {8 d
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;" k+ ~% ^8 P! `( n
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    ; x0 T8 c5 l5 E/ J& Q
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)) [% |% I: ^, X5 B6 N2 G
  23.   {
    + X8 E' A5 ]6 x1 K6 N  B
  24.     Error_Handler();3 X* {0 V3 B- f
  25.   }" U" O. c8 e% b+ ^$ y1 {
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
    * D% e( ?- f3 o2 ]3 }" I
  27.   {
    9 n0 T% @7 I* S2 }% K  i$ V
  28.     Error_Handler();
    ' ]$ ]9 t4 f$ N1 ^* l& l" w9 s
  29.   }& a6 `) M& a: F! G, N5 t' e4 _
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
    ) T. k# L* O7 j
  31.   {' I! \) r, s# C  ]# a* r/ h
  32.     Error_Handler();
    ) s  q7 N$ ?6 f5 y
  33.   }( r) H  w0 G' L* C
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)6 L+ Q; P. l( I& w) x# R) U: }
  35.   {
    ; a* p' s) G% `0 p. _3 M$ f
  36.     Error_Handler();
    % a' ^% M1 K7 w) e& X5 e
  37.   }; o) r% ]! D# D6 K- D1 \: I
  38.   /* USER CODE BEGIN UART4_Init 2 */
    1 n3 G  T" J) Z: W# c/ I. T

  39. 8 \  I0 X% h( i. Z! y9 U1 j
  40.   /* USER CODE END UART4_Init 2 */4 T5 r& T" B# @/ ]! H
  41. " i3 ?* ?) i. H6 m9 _( x3 }/ K6 M( L
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)
    ! o% i- {4 T+ q' s8 n% N
  2. {5 X& D, @4 ]# o
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    # T" Q3 _' m# p/ H- F9 ]6 A( _
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};; W6 `1 T9 f' t
  5.   if(huart->Instance==UART4)
    $ g% r5 M) C# ]; x4 ?- A9 e! G# |
  6.   {; ~( Y4 v0 O1 D3 k0 {% G) i
  7.   /* USER CODE BEGIN UART4_MspInit 0 */8 {$ R* u& x7 ?+ f; \& T, `, r

  8. ! ]0 s5 O" q  D6 Q
  9.   /* USER CODE END UART4_MspInit 0 *// t2 ~% J% {8 c$ F3 f, L
  10. ' L# F* H7 Q/ `3 R: L
  11.   /** Initializes the peripherals clock+ p1 u% ]: D: `) z  D
  12.   */
    5 A+ \, f) {5 D; g% h7 v! F4 o
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;
    7 H( N9 X- y3 l7 L! g: ]* |
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;: H/ d4 P9 t% W
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)* r+ @* C4 Z' L5 {; R
  16.     {& n+ c3 n8 u6 Z- _& m
  17.       Error_Handler();
    ) z- X- K% B$ o' L& X7 \
  18.     }1 L& y5 E: F6 E
  19. 1 M. \1 _3 F. I
  20.     /* Peripheral clock enable *// c( E  o  E  h( b
  21.     __HAL_RCC_UART4_CLK_ENABLE();7 o6 _4 H+ B1 F9 H  O! y( m
  22. 3 E# |" K( w; u. j$ u, a
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();/ }# J4 p1 d/ F+ ]6 Y- E
  24.     /**UART4 GPIO Configuration& ~/ C, ?* S, q2 p4 V" D1 Q
  25.     PD1     ------> UART4_TX9 }+ O( q6 Y; B3 b+ W
  26.     PD0     ------> UART4_RX/ `) x' M" W9 k+ {" u9 Z
  27.     */
    ) |- ]& d1 X2 m4 l$ T: H4 V" l
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
    8 @9 D6 ~1 r7 F
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    ! a* `/ c+ x. J9 ?$ n1 L
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;  J3 ]6 i. T1 T( c4 j
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    , n" A5 B- ~5 q) G' i2 h
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    , F5 I4 r# w  D1 ^) I, W% [
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);8 j+ W5 H' O! J

  34. . N8 ^- o5 Y8 }: V9 r! W  m: k- _
  35.   /* USER CODE BEGIN UART4_MspInit 1 */" a2 q; q) L/ l! x

  36. " @, B. p8 q: {) c: \+ ]
  37.   /* USER CODE END UART4_MspInit 1 */, h5 K3 M2 V: y! A- s0 C3 m

  38. * M* b1 M" p4 W1 i& C" r; d) L; i
  39.   }
    ! w; i% U, Q$ o3 }0 A. I

  40. % L& m1 [7 ?/ o2 y" M  e9 h2 x
  41. }% E7 G- v, c. p$ r0 n
复制代码
  1. 使用cubeIDE% C; J! X" H) Q* W- [# i
  2. __io_putchar(int ch)
    ( d: ?& |5 x. V0 w' m( m
  3. {
    % o, h6 d# ?9 ?* S5 q! X, X6 I
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);
    6 _$ B# S4 R- _7 M
  5.   return ch;; J; L+ `" m' y  x1 P
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下
3 @: ^  y. S- `/ e+ p9 A1 n       c.png
3 `7 p9 H- R$ ^7 ~, X, f* P       添加输入输出头文件stdio后,就可以试试程序如何了。+ B# C. w  d! _* N4 G( x$ q: {6 N
       d.png 8 _" ~+ q1 E% N3 P" }3 \
       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。3 G3 Q# |- Y8 O. s! A! U, N. |
      9 h; y  R8 ]6 B: Z  s! ~1 R( k! b
  1. static void ViewRootDir(void)
    , p  V% B" m6 z0 J
  2. {% o3 z) O$ H+ t7 ^
  3.         FRESULT result;
    ! n/ P( w! k1 [& L; w4 g* j
  4.         uint32_t cnt = 0;
    % r/ v9 ?# h- ?2 \/ W
  5.         FILINFO fno;+ w" t: x. g. s: r% t, f& I' F
  6. 6 {  B5 |$ G! {2 i, ]$ z$ e) u, Y7 Z
  7. ' y! z% I/ i5 G
  8.         /* 挂载文件系统 */$ G( U3 f* `8 w1 w$ b" d, W) d0 l
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */- r% o2 D: E& x7 V5 t2 j; z0 F
  10.         if (result != FR_OK)1 }7 m" F7 R) W/ J: p9 |! x
  11.         {# L% F; G- P3 A0 G  A
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);. x! `+ \+ `4 A3 i* R
  13.         }
    0 s+ A# r2 a8 `2 _/ j( l
  14. ' ~4 a+ P$ t5 i& O( Y* B
  15.         /* 打开根文件夹 */: M! r# P* X( j& K3 s( _% @
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */
    1 M/ \( ?9 u" o* U. J3 q5 a
  17.         if (result != FR_OK)
    8 l+ \5 Q! \/ ?( @' i3 }7 @
  18.         {; V* w1 {* `- l( y
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);
    * }& |- I+ h0 q, \6 G: r
  20.                 return;
    - ^6 S+ V3 G& E9 k6 n  @' g3 t& s( Y; e
  21.         }
    , n1 G' ?0 n/ O, }5 N3 j
  22. # h3 a& O5 p# @( D% E  g( v, N
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");0 t0 A, _' e' Q. H
  24.         for (cnt = 0; ;cnt++)
    , S7 D) |* s+ |
  25.         {. F4 ~9 S$ O9 ]0 E1 I( t9 c! A. ?
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */
    1 U+ F# @' _" |. d1 K
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)
    / ~& F/ }2 P8 j, B* h$ k
  28.                 {
    & G6 v: w, ]- l
  29.                         break;4 A# Z9 d$ E/ r: z# p
  30.                 }
    2 j, \' H: I5 O- [
  31. $ {0 n; {  @/ i  @! w: b
  32.                 if (FileInf.fname[0] == '.')3 z9 _7 Q  `+ Z( r0 ~- G; K5 F
  33.                 {$ ^. M$ w1 [( h7 ]4 `( N, ^6 e
  34.                         continue;4 S! e! W: I' ~4 g0 T; Q3 _; g
  35.                 }
    & K* t& l* B. t1 E% N# X4 v

  36. $ u* C: H2 H8 @3 G  X
  37.                 /* 判断是文件还是子目录 */
    2 _3 }2 a6 [0 v+ h6 O" z
  38.                 if (FileInf.fattrib & AM_DIR)3 L( A" d, `& A& e' `/ J
  39.                 {
    4 R3 ?1 Q" M% g7 B# I  d8 l
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);
    ) r2 t! p6 e/ ]/ S# V. m7 ?
  41.                 }
    8 m  Q* \# f1 p2 J" h
  42.                 else3 b" l4 \! I8 i0 G, K
  43.                 {  _1 ~& [/ i- H. i; Q
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);0 c) D. u4 d' y3 I+ |5 F" O
  45.                 }
    * e# o5 X; n$ o. ~6 o
  46. $ K! P6 T( g6 U
  47.                 f_stat(FileInf.fname, &fno);) h# \5 W* z" K7 X9 I
  48. & c- w: X' w9 V  X& [- D
  49.                 /* 打印文件大小, 最大4G */
    + t6 W; `/ N; ?& l- N2 X! k
  50.                 printf(" %10d", (int)fno.fsize);4 u$ d- c% |  B% S/ ?! t
  51. 6 O  q" \. F5 i

  52. 9 r! m3 x+ H( X2 S
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */$ R% C5 R" h8 X( R' q
  54.         }
    / i2 Q7 r* o0 }7 v0 G0 C8 E  M2 S
  55. ( u# f7 x/ k; ~0 e  y% u8 m) }
  56.     /* 打印卡速度信息 */
    % U, W( C, E4 m6 }+ v+ p* l
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)( Y7 t. \' o7 K+ E. L! ]
  58.     {5 q" Z& E0 K+ O3 P$ @) z& I
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");
    : G1 D: e) S) ~
  60.     }
    - t6 X: f! f6 w( h$ a. T
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)
    : w: x' S/ ~, D$ F' f
  62.     {6 r0 S% }6 W! [+ h4 |& x
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");
    0 d( e8 @6 u2 |: n; s' K3 v
  64.     }( z' b+ M- \1 N9 X( a# ?. H
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)5 P( @7 p( \' t+ _
  66.     {
    " [/ D$ L+ U  O( A7 O
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    + t+ Z' z' q( D' S, r0 s
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");5 R6 e: S) g# V0 M! W  g" n
  69.     }
    7 ^$ c8 [1 u* M4 A( ~* I. N- h6 y
  70. 0 h. j9 w' h7 z+ H
  71. " {/ B0 s1 X2 Y8 f# u
  72.         /* 卸载文件系统 */' W' }& W* t7 l$ b' p  T, @5 h
  73.          f_mount(NULL, DiskPath, 0);
    ; W" \4 S+ f. T: n( l* O* T: _
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。
8 ^- I& b8 @9 Z( r2 Z+ F      e.png # E+ {2 ~* p! y* P: U8 e! m
     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。
& c8 Y2 ?4 \6 @  P 添加的内容为 -fexec-charset=GBK,还是修改编码的意思。: {. z7 W3 |6 Y; ]0 x: q7 g% p
      f.png ' s) P& K- `/ u: ?0 q- R$ m
     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了9 i8 P! N3 x( N! C- y$ t" R
       g.png
% \+ d! O/ z& u      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
3 j* X7 W. P# `& a1 {( A) u       h.png
  \+ D( Z+ b4 {1 ^1 m. o      料想这次应该没毛病了。结果,新的意外又出现了。, ]2 O/ @1 l0 a# w/ r! V7 {
       i.png ( M3 F! V* X$ B7 [# e+ u
       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。. v1 _/ x4 Y% D' W+ A/ T) u/ b
      j.png k.png
. p5 y4 M, L' C+ K    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。5 Y6 V" B. N$ \/ M9 X

8 X6 D; i- K/ J1 u/ @2 f      
9 I: q$ D4 E3 H# |9 V8 z9 G0 l0 U! y7 L7 l6 z) G8 t3 b" D
9 {: L$ z5 |4 E6 Q

9 I' @* ?: L# z2 A# k6 ?) d. e( C& f/ G& [
收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版