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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。: M) s7 d1 @1 e( X" E4 a' Q
5 q. c+ p: a. G
    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。: R! t4 F' e& z; h* i
    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号
# x7 h) S) s* D" r; c* U9 t3 D      b.png " U* b8 e9 ]3 j- L& h
     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下
2 h# d7 t3 ~) [      : a" H( X6 T' \! P  R. [1 L
  1. static void MX_UART4_Init(void)7 \+ @# z3 ]/ G  m; |+ p3 M9 Q
  2. {
    4 n$ C0 y/ p9 S" `# y/ ~% K3 ~
  3. 8 _4 k- [$ s; N8 P6 m! n$ i7 h+ l, S
  4.   /* USER CODE BEGIN UART4_Init 0 */+ V: @: X  z5 H6 v9 g/ q
  5. " P" g1 a" ^& ^* u7 ^# E- z1 k5 d
  6.   /* USER CODE END UART4_Init 0 */% s& ^1 c0 D0 f( x; k2 P

  7. ) {  `9 D( {, v
  8.   /* USER CODE BEGIN UART4_Init 1 */
    / ^. Z% ?7 \! b- d0 _$ f# d

  9. $ T- G" S: `% r' j2 u, i
  10.   /* USER CODE END UART4_Init 1 */
    $ z/ O% S/ B) n- B% }
  11.   huart4.Instance = UART4;
    ' i* B  O$ q* y  k: j! q& V4 q( E% {% q
  12.   huart4.Init.BaudRate = 115200;9 }9 Y# q% Y7 R: \
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    2 Y# I% w, D, L8 U; v3 f, K
  14.   huart4.Init.StopBits = UART_STOPBITS_1;
    4 z0 f& v) I% y5 F# y' K( E
  15.   huart4.Init.Parity = UART_PARITY_NONE;
    - }: f9 o0 w. S9 S
  16.   huart4.Init.Mode = UART_MODE_TX_RX;
    + D' j+ s& j' Z8 C' A0 d" x
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;. i7 N7 y6 M8 w& N6 y
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    $ ~7 ]( j& V2 ]4 H
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;8 \/ m# {0 H# \0 a- p% z
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    - o+ Z/ H1 @. B6 f! E
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;  u1 Z6 s3 Z% ?' _" @
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)6 W6 I2 _7 A& v  B
  23.   {
    : P* r# {- ~. @/ R1 t
  24.     Error_Handler();9 w) }4 x# e0 I- H
  25.   }5 f. s" V5 _4 N/ O& P
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)) a( X- Z. t/ \4 P
  27.   {
      ~8 n4 ^; ^: h! I
  28.     Error_Handler();, Y7 @4 \5 l" p  W9 ?6 {! H9 ]! _* @
  29.   }
    ) ^! E6 U9 L! s7 v
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK); P4 S8 |- b- U
  31.   {
    8 j( A; v* `- o+ f) F, b
  32.     Error_Handler();
    # N. ?1 |4 _; X  i8 |
  33.   }
    6 T8 v4 d! w. [3 b% J
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)
    ! I4 n. _9 O' M
  35.   {1 j6 o8 i+ c# ~1 y; {1 I/ X; `; c
  36.     Error_Handler();
    0 r% c" a9 X% ~: @* g) D
  37.   }3 P6 E' n- x  ~
  38.   /* USER CODE BEGIN UART4_Init 2 */1 [6 G3 @6 B) C

  39. 1 W+ P! I4 E- `) A/ i& B' k- |
  40.   /* USER CODE END UART4_Init 2 */
    ; L  ]& {8 b: a( {" J! T8 C

  41. . [* ]* Q4 V+ v5 K$ |
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)
    : ?7 J: T! {6 L1 S
  2. {* ~7 }! U/ Y* u2 ]
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};. p4 W5 J2 l  m. z& C0 z6 \( t& J
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    & z# P1 V+ t4 l2 U
  5.   if(huart->Instance==UART4)8 d+ {8 y5 ]) j: x: C
  6.   {
    ) q& u! g8 `7 r9 H$ |' P7 a( {
  7.   /* USER CODE BEGIN UART4_MspInit 0 */4 n( O9 j1 ^9 H" ~& Q' a
  8. " O% ?( x9 F0 r; l6 E7 X* `
  9.   /* USER CODE END UART4_MspInit 0 */
    " f0 c0 P, ~- T
  10. ' N4 d. ~- `. T4 |6 c
  11.   /** Initializes the peripherals clock0 V: T6 o- N3 o; U$ G; Q: `
  12.   */0 F5 b$ o* f. y. _, X2 Z; Z' S
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;
    ' k  v# W1 C/ B) h; M* S- I& Y
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;0 w6 w& `2 W5 e, X& w
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    7 e+ V( \3 [/ A8 ?  S4 U* o, \$ n
  16.     {
    6 W$ R, U+ _) H( E; E
  17.       Error_Handler();
    % o1 R1 W% D0 u3 I' t# D( t
  18.     }
    ' B' }3 t: Q: M0 F+ d# K
  19. 1 z5 F7 M7 K, @, m, K2 P) _. K, U
  20.     /* Peripheral clock enable */2 L! @! E4 l! ~8 u
  21.     __HAL_RCC_UART4_CLK_ENABLE();7 `5 e0 E3 e. C
  22. 5 \  D, ~0 w/ P5 ^
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();8 _0 N0 o6 U/ p4 L8 \
  24.     /**UART4 GPIO Configuration
    ( P; b4 H) k4 H0 w7 ^
  25.     PD1     ------> UART4_TX
    9 [* l4 y" S/ a# D2 V3 b/ D
  26.     PD0     ------> UART4_RX
      q2 g  ~1 U/ B/ A5 R$ X% d
  27.     */
    0 W; M. \! R; Q6 s
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
    7 U1 ?  v4 d. K
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;6 `" C# \# ?& o+ D
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    . O) |, F* h7 H1 L* h+ C
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;9 p! ~" a) @4 O4 s/ ^
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;" `. w2 R! \" i/ o7 N
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);3 `2 h% }- K& _6 X- t$ E
  34. * f2 {/ m$ ]& S
  35.   /* USER CODE BEGIN UART4_MspInit 1 */9 F3 F7 m* T& i, A4 t- D# F
  36. , _+ ^6 u9 |; I3 E4 z( z
  37.   /* USER CODE END UART4_MspInit 1 */
    + u: a/ j+ h& z5 p/ H0 ]
  38. & \6 I5 L9 n9 ?" g2 |( Y" {( H% c
  39.   }
    6 Y6 r3 E+ ^5 }
  40. ( g2 V2 b* F; V6 I
  41. }
    ) k# y7 i2 S. ^6 B' T. m- z7 d* X6 f
复制代码
  1. 使用cubeIDE
    5 s8 Z: ]; g7 Z8 b$ n
  2. __io_putchar(int ch)
    0 r9 x, G9 f/ h  t$ r# d" L/ L& \
  3. {) Y1 N7 D+ I. F" ]5 K, p( L- O% Z
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);+ f; o9 i$ v4 n9 E2 m
  5.   return ch;; H$ G( N' \1 p
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下" o- e" w9 y' u4 t
       c.png
3 `4 l% o& p+ O1 g       添加输入输出头文件stdio后,就可以试试程序如何了。
+ [  r2 [, H0 g/ a% {       d.png
8 |5 i" @1 R9 u) o       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。( c4 u, b# ]2 P' u9 F  @( `* j6 ?
      ( T- d3 }4 E8 \! {$ T4 Q7 ~
  1. static void ViewRootDir(void)
    9 h2 t) o' ?* i' w! f
  2. {
    # c! B- q; Y$ G
  3.         FRESULT result;$ s$ d8 N5 P! p% P! [0 T0 O
  4.         uint32_t cnt = 0;
    3 T. I. q) c  v9 U6 j
  5.         FILINFO fno;8 X9 f- b# e5 k* p/ L0 r9 e

  6. * A8 k3 w4 E0 z9 ^& _

  7. 6 e% ?1 p( A6 |% x: O  y
  8.         /* 挂载文件系统 */
    ( }; l7 c3 }# U4 K1 _
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */0 b; u9 q& F4 n
  10.         if (result != FR_OK)4 Z$ D, `& U! C; \7 Z
  11.         {* L. V( u- |" K5 e
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
    ( z  H4 [3 V) t- e1 W5 v1 B* J1 A
  13.         }
    & S: H4 Q5 U9 {! @* d: ~

  14. 3 R0 k, Y& }% g) ?1 a7 Y; q% [
  15.         /* 打开根文件夹 */8 }8 N* _- H! W3 A2 F
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */  V7 l, A8 J# ?
  17.         if (result != FR_OK)
    4 |! H% F3 ]8 Q9 |5 ^; ^$ @# y
  18.         {  A% E: B3 M* i/ \
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);
    9 G  W* u0 G) {. b5 B2 \
  20.                 return;
    8 n# x& g1 B7 B$ y  V& t
  21.         }
    4 _% D# v9 R" d$ y9 Z
  22. 4 Z- R8 W( S) h6 b
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");8 T" |6 n) Z% s, v2 d% G
  24.         for (cnt = 0; ;cnt++)
    . ^' I: W) }, q; z8 |/ O% i7 K8 I2 n
  25.         {
    ' [; n" k- a" D* U' `8 c" c2 P# F
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */9 u! M* M9 p1 j8 l1 S( T) w
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)
    1 L$ n& d$ w: E7 C2 `4 k+ R
  28.                 {
    * r1 V! Q4 ?) h  N0 y/ }6 v  Y
  29.                         break;3 @$ h7 b! w  X- X- A: V
  30.                 }
    ; p" W1 _2 L1 \" e0 T9 ?

  31. 4 t: S# f9 S. A# d  g( J& y
  32.                 if (FileInf.fname[0] == '.')
    - O0 P* V# s3 L5 B9 y
  33.                 {
    - ?- L5 Z$ ?5 W
  34.                         continue;
    + D* g2 S6 x  N! Q1 Y1 B
  35.                 }/ E1 I( d% Y1 z" x3 B) \5 w

  36. $ ?9 Y6 V1 V- @3 P- J
  37.                 /* 判断是文件还是子目录 */
    ; O) Y. B) T! Z7 D! m0 r
  38.                 if (FileInf.fattrib & AM_DIR)% N( o9 Z! x* R% G3 W7 ]8 \
  39.                 {
    # G2 x5 P: X" X& u% v9 L1 C$ R! T
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);8 v! e0 p, v0 }+ S3 }
  41.                 }
    6 o5 k4 x0 T; H. S" Y. M1 e9 F
  42.                 else
    9 o. g9 Z+ N2 t2 j8 g
  43.                 {
    2 \( W* D1 j/ k5 b  m
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);
    / C0 F' W! B7 c) d. n0 i5 \
  45.                 }: c4 U. s( v- u0 _
  46. 4 v$ @- j, c: e2 N: e
  47.                 f_stat(FileInf.fname, &fno);
    6 N' M9 H# o( z, B  Z
  48. ' N% c. l1 U  R# q! v# P: t& x
  49.                 /* 打印文件大小, 最大4G */
    2 Y8 T. w4 u9 f' B# y9 C4 g
  50.                 printf(" %10d", (int)fno.fsize);2 f; y4 F6 w8 H" L' ~6 m
  51. ; {# P0 y9 I0 c; X" b2 P

  52. 3 ~( [" \* P2 P1 B
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */
    7 W0 g2 O' L0 Z( {
  54.         }  Q8 ?" g  K/ F1 v( p
  55. * w, N2 @9 A( }3 h1 }0 \
  56.     /* 打印卡速度信息 */
    " ~8 D* }6 A; }+ p& w2 A
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)
    . y# L5 v- C8 n, {* s" ]' c
  58.     {
    7 P( {" r. x: L; R
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");9 Q7 D" W& E; g0 f0 d
  60.     }+ t( W! b& X6 m$ [( o
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)
    ! c$ _8 R+ N4 G% @, Q% G
  62.     {- v* H8 w+ a" N9 \" Q
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");5 p% r/ U; z, Z& f" A) `6 [' T- n
  64.     }
    & V, @6 T1 d' v" h. m: w) H
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)" w% r. |  Q( |; \
  66.     {: m: W1 L% D' C' B$ q9 G
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    0 b2 g7 u; L7 A' @* r, p+ ~9 [0 c8 O
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");
    * J# x- b8 N0 G* Y2 }
  69.     }
    # j, R* p! J6 X
  70. " @. T$ m0 {- c
  71. , u7 S2 T; b: X3 ~" X+ u- \
  72.         /* 卸载文件系统 */4 n( E7 d+ b9 M
  73.          f_mount(NULL, DiskPath, 0);
    0 a0 r6 P$ B& N) @) N; e
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。
8 d4 x% D3 R: o- f0 ~+ Q      e.png
# S* L! ?+ z# e" _( `: M/ t     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。
& H# c6 k$ U# U# z! n  ]8 a 添加的内容为 -fexec-charset=GBK,还是修改编码的意思。
8 `  A0 u+ W2 }; ?6 C      f.png ' X9 m+ |) ]8 r4 M6 [
     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了5 A2 v% o/ i" X% X8 I5 S% f) `
       g.png
9 [9 v& u. D/ [1 |, S      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
( h: R0 ~1 ]+ {9 i7 R0 t9 \% |       h.png
" ?, b& ]1 R+ `8 k  C4 n; H      料想这次应该没毛病了。结果,新的意外又出现了。% o9 Y4 W) k- \. d  V
       i.png
! P# b$ X' W4 U       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。
2 v+ [8 D, v* O# G9 P0 |0 X6 F      j.png k.png 2 ~: W0 r1 G4 r. @
    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。
, Y% N4 M. v! t: e# M* ]
4 ]8 v5 J/ X1 e; e& j- C' Q7 U      5 X& A, C% A' e* \0 Y1 r5 W

$ Q$ Y( U( z. d2 D% N' }+ f- M& s2 D" D+ W9 r5 A+ _7 r' B

" P4 u- J) {: V9 a% M
$ X" e7 q' c6 B* O% l; z$ B
收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

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