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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。
" M. k) }+ j9 O0 q' a2 x0 O1 r
! k4 R7 c  G7 N6 ~+ j9 v) a' M    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。
- o7 c; T: ~: a; S/ s    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号; u( e1 ]9 h7 \9 O* Y
      b.png 0 ]# b: P6 O2 \5 x- X$ W, P
     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下
6 x1 h( p: F6 I      - K  B3 P4 `1 X: J/ U4 Q6 T0 S  C
  1. static void MX_UART4_Init(void)
    , r! @: Z- b, q
  2. {) N3 y$ y% B" g! P* S
  3. ( p' B, p: T& u+ I- J* O
  4.   /* USER CODE BEGIN UART4_Init 0 */$ [" S: {. [1 h% N6 j; v9 S
  5. 7 |1 T. Y; l: `0 M
  6.   /* USER CODE END UART4_Init 0 */
    8 R% F! C9 Q; v. U  Y

  7. ( m; H" Q  f' f* A' u/ l/ l6 \4 @
  8.   /* USER CODE BEGIN UART4_Init 1 */3 c, W" j% Y; _6 ~4 C7 g" F
  9. ) \& s; P4 f- A- a# U6 Q3 ^# K
  10.   /* USER CODE END UART4_Init 1 */2 W* b4 c" h1 `( L
  11.   huart4.Instance = UART4;9 D. l( k) v: e7 C, I4 [
  12.   huart4.Init.BaudRate = 115200;
    7 u0 P+ C) t7 u) O6 s) R! s- S
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;/ j& {1 ~$ R. g8 I" i3 u
  14.   huart4.Init.StopBits = UART_STOPBITS_1;
    % f) i& h# @0 C* t8 ]& c, R
  15.   huart4.Init.Parity = UART_PARITY_NONE;, E& d8 O8 c3 t- c
  16.   huart4.Init.Mode = UART_MODE_TX_RX;' H' l' l  O6 J% b0 A0 U
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    8 A) Q* \) [- I, S, w0 O7 N/ y0 N
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    5 }. T" N/ r& P; z
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;$ H( q$ E9 v- y8 P0 S7 m$ l2 N
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;0 K+ _/ d2 ~, t- ?" l+ l: o7 s) p# j
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;' c+ Y2 s, ~3 c! C1 u$ Z3 p
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)
    - H3 f6 d$ l- \$ O/ g* a" X
  23.   {" n) ?  p: w* s' I- w& j7 c! _
  24.     Error_Handler();
    " P0 E' p8 I. l$ {1 b- G1 |
  25.   }) R3 q$ u  a  ?  m' z" F' r
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)$ h$ p9 m, C" n
  27.   {
    ) m$ V' w: G' |0 Q1 P2 C2 g
  28.     Error_Handler();
    . E3 g- V3 {5 u5 r, A
  29.   }4 @' c6 d* ^9 @$ R8 W0 o
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)2 A- m8 S" \1 Q5 T- ?  k" q
  31.   {
    ; Q  k4 g& p' |7 C% N. _. x
  32.     Error_Handler();
      K, |7 \# H( b. g
  33.   }
    ! K" y  s  s5 w
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)* I7 |) w3 _' x/ q
  35.   {
    + V" S1 @5 ^) `' r5 n  w
  36.     Error_Handler();0 n# I/ X, J& b/ \% O. x) e
  37.   }: ]  o* G/ u3 B5 E4 Y, ~" L
  38.   /* USER CODE BEGIN UART4_Init 2 */( T( Y7 ~$ N9 I! u( x

  39. 6 T* i0 q3 I3 u- U& j1 G
  40.   /* USER CODE END UART4_Init 2 */
    ( ]! _% b( y9 S6 p# q+ R8 R! Q" _
  41. 2 ]) ~3 q7 ~, n$ Z4 j
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)
    : |4 i. c; _) ?: g. M: a
  2. {; q; ?8 Z* N3 i1 r% c
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    . M$ l" {9 S. R* J0 e4 K' G
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    + r$ B' V4 Y* N% k6 W
  5.   if(huart->Instance==UART4)8 [9 O5 i+ u* |: ^/ O
  6.   {
    5 B6 U# L  A3 Y, F# \; Z# l
  7.   /* USER CODE BEGIN UART4_MspInit 0 */2 h5 Y) H& k( k7 M1 X7 [; F
  8. - {6 ?- U- y" C8 c- D
  9.   /* USER CODE END UART4_MspInit 0 */* @# c9 H1 w2 B0 E% K# v

  10. " U1 W. p+ x; k! X
  11.   /** Initializes the peripherals clock8 b9 W5 @/ {! L& P3 g& e. m
  12.   */
    1 ?3 i% k' `) X2 M
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;: R& o  h9 [3 f2 k. m6 \! I" g: G
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;
    & C# p; t, R+ a5 ^
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
      c7 H3 V9 w2 |* ~. F
  16.     {
    0 }% P! `  F8 I+ x6 P9 }5 m
  17.       Error_Handler();
    2 J% A- k4 f8 _: F7 h7 P! `
  18.     }
    ( p: L: c: m$ l( U3 s
  19. 0 W  Z: Z5 f; B3 j+ s1 z  i/ p
  20.     /* Peripheral clock enable *// E/ E+ d( Y5 x5 y
  21.     __HAL_RCC_UART4_CLK_ENABLE();
    . w$ B0 s4 Y) V3 I3 ?7 B) S/ w( b
  22. 7 j- R) y+ V+ j
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    4 v, K* e1 {* ^7 ?
  24.     /**UART4 GPIO Configuration
    . W7 e! J! `. F( I$ L4 A1 `1 o
  25.     PD1     ------> UART4_TX5 S7 M9 C* u# @6 l
  26.     PD0     ------> UART4_RX
    - Q1 ~* Q( A  U' w9 U& J
  27.     */* [; d9 d8 Q' l2 G
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;: A; a8 V/ j' @
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    - U) R% o( n/ ^2 L$ }3 k
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    6 u4 h5 y3 A7 m. L
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    0 Q% {1 M0 c7 z/ O. a, L
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;4 y* N# c& i  J1 Y4 r* H5 |' Z4 q
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    & }; F( k! B! C4 ~
  34. 4 Q$ {0 M8 e3 L
  35.   /* USER CODE BEGIN UART4_MspInit 1 */
    7 _! m& t, J/ E. T8 T

  36. + X( D# T& O7 w$ Y
  37.   /* USER CODE END UART4_MspInit 1 */3 W: i8 f' _( l
  38. $ ]6 ]" g5 s+ f
  39.   }  M, j+ S! N$ _7 d! k6 O
  40. / F  p% Z  |" e% n- L* Q
  41. }
    0 ?  n" W0 b7 N" o& H( S4 L
复制代码
  1. 使用cubeIDE
      s) f1 M: O/ W5 Y" H
  2. __io_putchar(int ch), k- Q% q6 q7 r
  3. {
    : r: z$ P" L. P5 ]  R" j) ]7 _
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);
    ; w' W0 X+ K7 @3 S& b
  5.   return ch;
    2 k$ B! L3 i% a0 |) f# b) Q" [! b# E
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下
9 K7 M* a: N& t( V4 F       c.png
3 t% T  U  z5 _2 d$ V, _0 ^+ L       添加输入输出头文件stdio后,就可以试试程序如何了。  F$ B( S9 d4 }! f, s9 V
       d.png ! R9 E0 v: i2 t% v1 S: n; x
       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。
, M" e3 S$ T: @; [% O' t8 k      
3 a! F8 I7 {& _3 Z: l
  1. static void ViewRootDir(void)  z# ~, P; w/ d7 M7 R# B8 _
  2. {
    6 ?6 d  k( t2 b1 k# d
  3.         FRESULT result;1 m  ~( l# H, Q: k$ K
  4.         uint32_t cnt = 0;
    ( Q% K) f, I7 Z
  5.         FILINFO fno;
    ( @/ L5 P2 L) [# X% p) B' e

  6. . V, c) v- o* _+ x5 O; b+ E

  7. ( V2 u" J3 Z0 ]! N3 b
  8.         /* 挂载文件系统 */
    . o$ f. s" |) m6 K1 ~4 E2 o
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */2 q* H  h1 t5 d' O
  10.         if (result != FR_OK)/ P0 i% A% F9 S) n9 C
  11.         {
      X2 U6 {( O" ]8 {/ x$ D. ^, Y
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);7 o. r! b4 p' i* Y- g1 V6 E, u
  13.         }% u1 m9 b( r  b  \2 C6 w% Z! o9 j
  14. 4 D5 p- D) R0 Q$ {( m. Q. d
  15.         /* 打开根文件夹 */
    & N. j& U+ f4 S' h  ]2 Q+ u
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */" B0 o2 t3 t) P
  17.         if (result != FR_OK)& E. G8 k9 d/ S3 T5 \* _! a
  18.         {
    5 R4 P( s& q. e  s9 W
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);
    . Y* E2 H" p( u
  20.                 return;+ q9 e" {4 s! K6 y4 W  Q# @
  21.         }" G# K- V( T. v% K1 a# v5 X
  22. 7 {; F5 }, a- y0 ?; b2 h. {
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");) W, {9 P7 q2 Q: M' G! n
  24.         for (cnt = 0; ;cnt++)
    1 Z" h; O, u2 J. @
  25.         {3 j3 Q6 V2 `9 _
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */% P2 O0 f3 W2 p& I( r; C5 F
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)
    ) u" Y+ ]" r1 k) D; u5 G2 i2 y
  28.                 {) ?  g  Q- o; Y1 E& K3 Y4 o' I
  29.                         break;% I) k9 [, R; B  H* ^
  30.                 }8 A0 o  \7 v, P2 J$ O" S
  31. 5 g; x( V8 O0 z% e
  32.                 if (FileInf.fname[0] == '.')
    1 L% g# B& T, V& _
  33.                 {
    - k% m; c. h5 K
  34.                         continue;
    8 W: o! r: ?# I) y( |
  35.                 }5 _, X% R* T8 |: y' _5 \6 }

  36. 4 |* @& l6 R6 O3 [' A! W+ d' V
  37.                 /* 判断是文件还是子目录 */  P* {. g8 F4 y1 u1 W/ |& x9 N
  38.                 if (FileInf.fattrib & AM_DIR)
    3 R6 V$ }; p8 y
  39.                 {
    ( Z; z; T* E* U" h+ W
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);5 m" U% `& p/ D' {# K/ W
  41.                 }
    ; W; A& n. c" y; m9 b9 E2 }/ l
  42.                 else
    & Z1 J5 P) [4 X
  43.                 {1 D( o3 ?) t5 L+ j+ y
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);
    " }4 ^9 A* A& F
  45.                 }
    , p5 t2 r6 S; s* i! t& {/ @4 F

  46. ' E8 n  s$ @* m0 l3 [, H; X& C
  47.                 f_stat(FileInf.fname, &fno);- r  w  L# K- [0 \
  48. + N( p/ E' W. ]
  49.                 /* 打印文件大小, 最大4G */
    - B/ J8 `/ \5 X/ j0 O5 A; y5 h
  50.                 printf(" %10d", (int)fno.fsize);5 n$ q" s* x4 F$ t' I8 t

  51. . x! ~. w9 z4 m! Y* I. m
  52. 1 k2 i: k" N0 L  ^7 y
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */$ G+ D  o2 n) A
  54.         }
    4 V, \8 v5 e8 t7 Z
  55. 3 {$ c4 z( J( k2 \
  56.     /* 打印卡速度信息 */
    ) ~& f' c& B/ b: T3 |
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)/ _4 B" D. q# n* g% Y: x
  58.     {
    * V8 u9 k% h! a# f* ?# m" [4 ~. Y' R
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");6 I2 h1 ]7 L* D7 T
  60.     }
    ) y* E" {$ q! Z3 m
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)
    % u: C8 E$ C- h, `6 Q+ B
  62.     {
    8 D% J2 O% u) q) l
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");4 K. h) N& j& w1 W
  64.     }
    ! a" k& _+ V2 a; ?% ~+ v/ o& n# p- N- ]
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)6 j# a! ^  Q8 U! T/ t$ B0 y
  66.     {
    * p; ]) @! `( E# L& v
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");$ y% N. ~+ `* w7 {
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");
    % @0 }$ S% A: D
  69.     }
    3 V& o' k) ~3 f) ]- S+ P  c8 a
  70. ) h* U; u( I* ~2 X& n8 D

  71. / f# Z3 N% ~. ?
  72.         /* 卸载文件系统 */" A+ Q& |$ h9 W" O1 s
  73.          f_mount(NULL, DiskPath, 0);
    , x# e2 q4 g/ p% w  W
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。
# Z8 T/ P5 S% B) ], E% H      e.png
" u) i% z8 W' F1 n     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。- e. c* W) o. T8 A
添加的内容为 -fexec-charset=GBK,还是修改编码的意思。- o0 h7 A$ z1 `. q  G  f
      f.png
+ ~4 F% g( @; Z% f$ E     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了
9 U( H( |; w0 G       g.png + `0 f1 ]/ ?( ^0 W( Z& k
      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
  W. q8 j2 V& A$ F+ z' }# B       h.png
/ Y# G$ R4 U  p' b, i" f/ t! a% H) x      料想这次应该没毛病了。结果,新的意外又出现了。8 d2 }. D) k' g# A) m* h2 B
       i.png ( A# s& y7 L8 p6 i! _; C
       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。
# U8 Z! U9 Q1 \1 I; o      j.png k.png ! Q7 E1 \3 z7 ~1 @/ `* ^
    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。. V4 y: y$ h0 z( a, P
* H; K$ S2 n. X; i5 c! S3 c) r
      
4 U* {' ~  }& y: X+ t
' }6 |7 n2 U  K6 W' ^
' X+ j1 M' `$ T3 H5 V' a
. {% W4 a3 h* V3 U* b$ U
# J, D$ P$ Y' A; E" c7 P
收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似分享

官网相关资源

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