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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。+ M& J6 z! q; P
3 ~' b9 S+ c' S; R# Q$ n3 b) _
    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。
) [) |. T, O4 `. I6 |$ a6 |    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号9 m. O' b4 c% V# H
      b.png / e7 A3 c- a+ g& f* M. ^
     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下1 [( }( Y/ e! ~3 j3 S) Y
      0 ]0 K% U9 E0 H3 B4 m
  1. static void MX_UART4_Init(void)
      W. ~1 f( H8 b! _/ U2 X
  2. {
    # r& F, f% @, J& ]% }' z9 Y

  3. # G; U, Z: a3 V8 m& E7 s
  4.   /* USER CODE BEGIN UART4_Init 0 */
    4 u5 w% k  B) t6 N
  5. % m4 m+ P' j" ?8 v
  6.   /* USER CODE END UART4_Init 0 */5 ^, ~( ?0 z+ G( b& E+ C
  7. - u' ]( B1 i+ i
  8.   /* USER CODE BEGIN UART4_Init 1 */
    7 k; q6 ^+ W; P/ B; G2 z2 b* s0 I( G

  9. $ G. a' a! q0 j# M' @8 f
  10.   /* USER CODE END UART4_Init 1 */" }. m0 y9 ^! R- d5 H6 V$ H
  11.   huart4.Instance = UART4;& D0 W- B/ D# Y6 r1 v% k
  12.   huart4.Init.BaudRate = 115200;
    , g8 G+ R. i, U$ Y: v! q! l8 m& ]
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    , j4 z$ z1 R+ ^
  14.   huart4.Init.StopBits = UART_STOPBITS_1;
    - [1 e$ p& e1 \4 V4 S7 e( C* p! P
  15.   huart4.Init.Parity = UART_PARITY_NONE;! T4 Z# H$ E6 |4 O  }
  16.   huart4.Init.Mode = UART_MODE_TX_RX;
    ! b) u/ L3 g! ^) v
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    3 Y; R7 ^# m2 {% C# N$ {
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    0 {/ n1 s+ }" a1 K5 l2 I
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;! A, r8 \$ T9 U( }5 M" _- P
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    + L. y$ X" D' A
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;8 P1 S$ e  P" N
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)
      q/ a$ U' @+ d: B4 k
  23.   {/ ?* k3 Q! S4 c4 O$ q# T+ g
  24.     Error_Handler();
    7 u4 K# P9 ?: M& Q% @9 L% r% h
  25.   }
    * l0 a4 Z! J7 \. o$ u
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
    + a- z: m3 j- _" D+ B5 n  K& [
  27.   {+ ]6 j; ?- o7 G7 i+ |7 |
  28.     Error_Handler();/ E$ s$ t; M3 @6 |$ C& Y4 u
  29.   }
      u& q0 L; \. _( x
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)$ p2 p! ~; l: C! p4 x5 f- O0 }
  31.   {
    ; l# b( S+ ]" z& R4 M
  32.     Error_Handler();
      x; W* I1 Q2 ~6 f# u
  33.   }7 k2 o/ S3 J+ b7 d. v  }/ o4 C
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)
    * A) ~- X6 c, Y( @
  35.   {
    2 W; D0 s0 m6 S$ l; o8 m
  36.     Error_Handler();$ J# X* @( H9 o4 N* \# [
  37.   }
    $ H6 b, z& C! l5 T2 ]
  38.   /* USER CODE BEGIN UART4_Init 2 */5 K* U- D. r8 }* t
  39. 2 |9 C+ H. _7 O8 C! N6 z7 y
  40.   /* USER CODE END UART4_Init 2 */5 {5 u2 l% m# @1 o

  41. * |- f. f7 B  k! E
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart); h; U. F: T% z7 E6 r2 ?' d
  2. {1 `3 g" M: I0 b/ W% V) c
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    # e- I2 q% ~" \' r8 b. v5 h
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};  z% q5 i# J0 Z, _( d5 R9 I
  5.   if(huart->Instance==UART4)
    ' V+ J$ |  c8 l& P, J
  6.   {" o2 S( R4 o* X3 Z) j
  7.   /* USER CODE BEGIN UART4_MspInit 0 */4 ~/ e5 d" W, ]$ Y6 l) e" N  ^4 J" n
  8. ( g# j) _; J, A1 Y7 J
  9.   /* USER CODE END UART4_MspInit 0 */
    ( Y. |+ \2 F/ O) F; o
  10. 9 `, P2 x1 [2 y5 w3 }
  11.   /** Initializes the peripherals clock
    5 A0 }, e5 R# f0 M) S$ w! [. Y4 C: t3 N
  12.   */
    * Y9 e, w3 G8 g3 Q2 R( o. R% z& o
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;1 A$ X4 \* {6 A  t
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;" u. t& L; n  g+ y4 Y
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)! ?8 w8 E% D& Q- X* H# @
  16.     {
    ! j3 E% h9 X. Q% j; a2 U4 s
  17.       Error_Handler();$ u+ S. L, G% V/ X4 v4 R3 p& G
  18.     }  V6 J2 `4 N8 u7 |6 R, s- Y

  19. 4 a# q2 m  |7 R! E
  20.     /* Peripheral clock enable */- s" J; b. p' o" N4 ~" T
  21.     __HAL_RCC_UART4_CLK_ENABLE();
    8 X$ P7 S0 M( M# J
  22. 8 X$ `2 M& {3 U, n/ e
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();: p: K7 |2 U! f& D# c- r9 w  g2 C
  24.     /**UART4 GPIO Configuration
    1 Q4 ~, Q( w% I' C" ^
  25.     PD1     ------> UART4_TX
    - I) P  s& o' a' u- s
  26.     PD0     ------> UART4_RX: _* v2 M# l+ [, m& C" [
  27.     */; @( n, a) `: U) V
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;2 ^5 W1 p9 U5 U0 c
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    $ X% ]; L$ ?" a  m) Y* J5 A3 z
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    & Z9 q% F2 S& w- y
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    $ |% t9 g) {- q$ I* \) M
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    ) B; C- R( Q! X* `+ J" s! U1 j# s
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);; M+ ^) ~2 v8 z! R* b
  34. * m5 y$ j! P) S3 G( J+ W
  35.   /* USER CODE BEGIN UART4_MspInit 1 */
      i9 r8 ?6 p: f5 P  d, Z
  36. 0 s3 c1 E- R2 }9 o
  37.   /* USER CODE END UART4_MspInit 1 */7 s5 u* b- C, I7 t& A  v1 r, ~' l
  38. $ S% V  Q9 v! W& r# d
  39.   }6 C! A) d# ^  D4 N2 @: F: m% r

  40. $ V, ?+ `: T' F7 j4 m3 c, p* I7 g
  41. }
    8 [* a. ?% u5 w8 C
复制代码
  1. 使用cubeIDE- c, O. \, n1 g, k( M
  2. __io_putchar(int ch)
    . H6 v( k3 k7 e) P( T: q. |
  3. {; e- U5 \9 u: `2 j1 J/ ?+ t
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);
    0 Q/ w/ p- ~  e) y! `& K
  5.   return ch;
    , v* U) _! a; `* M; t
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下
/ R% r2 |2 Y1 a! I+ g       c.png ) I0 V& l6 [+ z* }" d0 G; Q- f1 D  d
       添加输入输出头文件stdio后,就可以试试程序如何了。/ B$ z! ?2 i2 z) N4 z% v
       d.png
; |+ z  a  k. q5 e       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。
6 a  t! t' \' N/ b) c      4 \: a$ e4 J& Z' v# n5 x/ t
  1. static void ViewRootDir(void)
    - W1 I" I- U" i
  2. {. F- U$ a& D9 m2 U
  3.         FRESULT result;0 H+ [% t! k* x7 W, A0 R* P$ j/ B
  4.         uint32_t cnt = 0;) I# e& E  X  E. a& x
  5.         FILINFO fno;$ r7 |# `2 b( }) D

  6. 1 u; Y. m. t2 F4 v& c7 I
  7. % \% a$ F, ^, b2 L& o. S( H
  8.         /* 挂载文件系统 */
    1 m/ f. ~4 ^1 x9 T/ B
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */; S% s' E- |" w
  10.         if (result != FR_OK): h0 s; p1 u, ]: W3 r  w9 v
  11.         {
    0 f# U2 o( M2 x9 H
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);) ]# r- X" N; f- r! \7 h% z
  13.         }; P* M- H* c% K1 x/ r# O
  14. ) b0 k! {: g0 d4 z0 E
  15.         /* 打开根文件夹 */
    : O! q! R% m6 t* P# a& @" g
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */
    1 o3 `& s/ G" t4 D  I7 G5 h/ }/ |
  17.         if (result != FR_OK)0 n/ I1 }2 n1 C8 b
  18.         {# k: L- S' k% U& Y
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);5 g# z, r0 I8 x, _0 W. U
  20.                 return;' i+ k' ^/ L! a$ A! c
  21.         }
    2 ~: b* Y8 w0 }! B& T
  22. 1 a# E7 t: U+ S3 ^
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");7 O. n/ L3 w& H; s% W0 V; S3 `
  24.         for (cnt = 0; ;cnt++)4 I0 q, @" x% v) a) t9 n0 Q* T
  25.         {; Q. K# F, \  C) [9 r1 Y
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */
    4 L( _: ?/ {/ e" c6 f2 W) e
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)' M1 A! A% h# P
  28.                 {
    ) P, K4 r" G+ r* j
  29.                         break;- A" U6 q6 Z4 \
  30.                 }
    $ ?, y/ A' d# ^8 {7 v

  31. 1 P" o0 V  p9 n/ a0 g- _
  32.                 if (FileInf.fname[0] == '.')
    2 w9 J$ {* R4 F" W
  33.                 {
    9 E- P9 X! _. M% u, L
  34.                         continue;" L: W! P, |% Q. j8 t
  35.                 }- u$ ]: J4 u/ g1 R
  36. ; l( x+ [; |8 }6 w
  37.                 /* 判断是文件还是子目录 */. T  E( x% K! J( {: o# y+ T
  38.                 if (FileInf.fattrib & AM_DIR)
      Q. g% q7 i0 L& q+ ]
  39.                 {- R! m4 P" G, O$ F
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);
    $ X1 f2 Q2 i7 l3 f
  41.                 }
    ! [& A& M- g5 j; ?* N1 y, l3 C8 G
  42.                 else
    ( r% z5 [6 d9 m% X: U8 h
  43.                 {% \3 |+ E4 [# ?& R9 I, K( O
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);' C5 r+ S  q/ A1 z
  45.                 }# K/ D2 c9 c- p" O, R2 p; ]

  46. / R' \, t! Q* s* w! t* k; m
  47.                 f_stat(FileInf.fname, &fno);6 C2 k5 b; U, k, w: |
  48. 0 K! C; S, j5 R/ q/ v' o
  49.                 /* 打印文件大小, 最大4G */" Z6 w' u$ J; o$ l9 P; b
  50.                 printf(" %10d", (int)fno.fsize);
    * g  f, y+ }) ?( p3 ^- ~
  51. $ p$ o4 N/ y# o" F

  52. , d3 D5 I, W$ w9 P% z
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */
    3 Y7 o5 E2 M9 W% q! S5 c' T
  54.         }
    6 |+ [( c0 J: ?( ]* a
  55. / P* z8 X/ O/ m$ u) X
  56.     /* 打印卡速度信息 */
    , N0 S& B! U2 F' a, y8 J" _6 _/ r
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)( V8 T! b, M. L
  58.     {$ k; `; w! |" R1 u, ?3 D1 P  A
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");
    ; I1 `* n# _1 r$ |5 m
  60.     }
    ' I  z' ^4 `  H7 X! ^6 f
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)
    . ]; [$ {7 g. ]7 H! r; y/ o; Q
  62.     {
    $ H) t) o# _2 r; m
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");- t7 G# Z' y! q% I# s, e
  64.     }
    $ _( |" c+ A+ P! A$ k1 E* e- Y
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)
    4 Y% y( s5 c0 F
  66.     {; t& D3 G' n7 A& U8 g
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    6 y* F% K! k& {  v. P  b! u# w1 b7 p/ F
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");/ z" |( l. o) z6 |" m7 G: ?
  69.     }  X8 d4 w; _0 Y8 S+ @
  70. ' }2 Q. K4 E9 O( ]& {1 R

  71. $ b. p: G* N3 r3 E- e/ j
  72.         /* 卸载文件系统 *// A5 Q# x8 x5 s. _& J
  73.          f_mount(NULL, DiskPath, 0);
    7 U: D: |7 d' Y) T) E; l- v
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。* M( p% d$ O' a/ Q
      e.png
: @" j1 v3 U, e- a( T     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。
$ y; K, |5 c0 ?# Y) P" u 添加的内容为 -fexec-charset=GBK,还是修改编码的意思。9 K1 r6 ?- `5 j2 w2 q5 e5 z
      f.png , v3 |( l7 Y; o! S  ^. t5 i; Z9 F
     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了  x( W, ?5 n: m( T. u7 ]
       g.png . x5 n0 H1 ^8 a9 m' d/ `: @% e
      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
/ [( J3 P. O' `/ P/ F       h.png ; ]' k! U$ ^& g, @. O
      料想这次应该没毛病了。结果,新的意外又出现了。6 x" S) K$ z5 `0 G: E4 l! Z
       i.png " [  p2 T' }" W% g8 w. y5 v
       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。
# Q) V$ M& n* t. T6 g& f      j.png k.png   F/ \! \. H% R! Y% S0 p* Q  |# W
    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。1 d% @- o" |, j0 ]" B) E

* [( P  u4 R# O* L, Q) D& P7 L      
- A/ P: O# q7 w( s. _4 T3 O" f0 j$ x4 u
$ ?! C! q! Y* y( _4 x+ V& ^* S9 I* x# b
. E2 v5 [5 t1 s/ ?

7 f9 n/ ^- w8 a. @7 H
收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

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