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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。
9 E4 a, X0 }' w  d+ g# C( d( B7 ]+ l- k5 x' W" R
    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。
0 X" q" _; c# u    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号& @0 H6 d# ~! K; E  k6 n3 g
      b.png   F) `  m2 ]( D0 b" K4 X
     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下) n, w" _. ~& V
      
, d- _( q2 H( G
  1. static void MX_UART4_Init(void)
    6 J8 N) W- A6 A
  2. {" ^- Z. q' \: V& q. ?% P3 n

  3. + h. t* S) r( X5 S6 Z$ _
  4.   /* USER CODE BEGIN UART4_Init 0 */
    ; \9 D' B0 [; ~9 p, |. X

  5. . w7 _0 D0 ]2 O& ^+ S
  6.   /* USER CODE END UART4_Init 0 */
    ( H4 j, l$ [3 }: @& |: A$ G

  7. $ S1 o2 K5 V: z  f
  8.   /* USER CODE BEGIN UART4_Init 1 */
    4 ]) b1 _5 n: {# f/ a' Y7 S( [& }
  9. 0 U8 y; I3 m2 z1 X9 a% }
  10.   /* USER CODE END UART4_Init 1 */' J# C& F7 N! I/ s- e" S1 v
  11.   huart4.Instance = UART4;
    % a; m/ ]$ V( {' P5 R1 l% T
  12.   huart4.Init.BaudRate = 115200;
    8 x' u  ^) c8 K$ J
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    - U/ a. g0 g; Z: b( b
  14.   huart4.Init.StopBits = UART_STOPBITS_1;/ c! f/ N5 B3 P1 W
  15.   huart4.Init.Parity = UART_PARITY_NONE;
    ) L+ |9 U" L  T: t$ v, g, F
  16.   huart4.Init.Mode = UART_MODE_TX_RX;
    # u; N$ @2 c6 }+ K5 q$ u! v$ R
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    ) |' W+ W) J4 y: A4 }
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    ; W4 u4 W& y% g6 ^8 G/ E
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    ! Y6 s& I2 b2 R
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    * s7 _" w8 ]+ U/ l
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    ! c- W) N; i1 l; H' H0 D4 j, M4 S
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)& k! D3 t3 Y2 X, ^; J: }
  23.   {
    " F, H1 J/ j! o/ Q
  24.     Error_Handler();
      m! B4 e  F5 g9 m
  25.   }% X! K5 m& r3 r- w* c1 e& [
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
    ) a- d& C" U8 [3 L6 y/ K
  27.   {' C4 C/ o' ^) g! L3 O. L: {
  28.     Error_Handler();
    : @. s- e& B6 T3 c$ {
  29.   }
    3 F% O' F6 M. W. l( b
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK); C, n( f: F' x6 }. d3 {2 ~( U
  31.   {. s, \+ ?7 o  v5 a0 J' T
  32.     Error_Handler();
    ) w8 L: Q- `1 ^2 l
  33.   }5 n0 E1 a, L( O/ ^% {
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK); i! @' O- y+ S4 H: a& r, l
  35.   {
    - Y1 X6 \' e7 ?$ A3 I1 o
  36.     Error_Handler();) `' Z+ I  m+ A6 N( z5 a, X
  37.   }
    / q/ B6 H6 p, g  H/ D
  38.   /* USER CODE BEGIN UART4_Init 2 */% _$ j" W; a1 O7 t) }% h" y
  39. , @( l4 }, y7 e: P) f
  40.   /* USER CODE END UART4_Init 2 */* k8 {" u9 X1 z1 \; `: f

  41. 7 p2 Y" N, Y$ t0 S: u/ a
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)0 d. j6 u9 w* z
  2. {
    3 `; z  V: X3 u& H0 ]; U9 W
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};2 C0 u% p% ]3 ~
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};6 r4 f+ r8 i& G" q3 _" a
  5.   if(huart->Instance==UART4)4 Q  x8 |9 I$ U- \. E8 r/ ~$ f
  6.   {* ~" D$ M2 q  D" [
  7.   /* USER CODE BEGIN UART4_MspInit 0 */
    % u% ^! C3 e- R# B$ \

  8. 8 J/ u7 r( q  X
  9.   /* USER CODE END UART4_MspInit 0 */
    : |. n) ]4 M$ Y& D

  10. 4 K, y% K; p+ \; a& B: {! r
  11.   /** Initializes the peripherals clock
    ( r6 S! H  `/ ?# S# w7 }0 \
  12.   */
    - m( `" e/ Y* [
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;
    + R7 P5 b7 R7 e( U0 v# }8 F
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;! }/ X+ ?0 O1 m( ^
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)6 n1 e/ m2 T' }# x
  16.     {
    ' i) F6 h1 R: }% \( k# J. b$ e
  17.       Error_Handler();- D9 n+ q1 x5 s4 U
  18.     }
    : Y1 b0 r% j% W- m: [3 y; S8 g6 A" I

  19. 4 d3 R: E: P! K. V/ U  b
  20.     /* Peripheral clock enable */
    1 H1 Z  g  E$ R, M. W
  21.     __HAL_RCC_UART4_CLK_ENABLE();* Z# J- S+ t8 a8 n+ h, H8 [

  22. / b/ q: h' P1 U9 k
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();0 z. @# y* X+ I0 |  j6 [- `0 M7 I
  24.     /**UART4 GPIO Configuration2 Q/ M, P0 V; s3 _/ B. C+ b
  25.     PD1     ------> UART4_TX  K! i/ I$ [( m( L- ]
  26.     PD0     ------> UART4_RX; V! |) `1 }! h5 J0 ]6 Z' a
  27.     */$ l: I# B0 d8 E) L1 j8 F( D9 E3 F
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
    : i* O& S% S1 R9 _$ G7 s, ^
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;; [) N% r+ A3 E  p+ t: i- @& F
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;, A: Y, k) C! f2 t% Y1 J
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;1 J: y( V; }$ j8 k, t- X* X' h
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    $ V" f" I( J9 V+ @+ `$ |: l5 I2 X
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);" Y- E& T% k5 n' o

  34. 2 E! D3 J% C0 @
  35.   /* USER CODE BEGIN UART4_MspInit 1 */
      e8 ~7 Y2 R1 w3 h7 V
  36. , y5 y* X: q; d/ P1 U* p4 W
  37.   /* USER CODE END UART4_MspInit 1 */
    5 ~  J8 q4 x) S4 W/ E8 C
  38. 4 b3 n/ M) ~& c0 R; d  ^0 d
  39.   }: T( X" m4 q5 P* M2 Y1 ?( ?
  40. % T6 I1 V9 x4 }6 D" L% G
  41. }# F' s9 V0 L2 p
复制代码
  1. 使用cubeIDE
    + |  Q/ I6 W, n+ q4 T+ |! V: z. h1 s; w
  2. __io_putchar(int ch)
    . H1 ^7 |% D7 W- c' |8 F) ^. c# {
  3. {
    # T* d+ I' p6 F2 m* L
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);
    ; |5 h9 _# F: P# s! x5 j, i3 P
  5.   return ch;
    ! w  z- A: v8 d) \8 T
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下
% C6 z3 F& m/ m       c.png
5 b1 B. \4 f, F' m5 Y+ Z* |) i4 T, C       添加输入输出头文件stdio后,就可以试试程序如何了。
( Y6 m4 M/ ?5 L. w% i       d.png
8 E  Z3 E3 M# k7 f4 r2 P       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。, Z! T! }  F" u
      
: [1 R8 F: C3 a+ X' p9 e+ u6 t
  1. static void ViewRootDir(void). h2 w% \4 a% @0 o
  2. {; \4 U7 h0 A& z/ }
  3.         FRESULT result;; z  n" [0 ^- O2 H: I
  4.         uint32_t cnt = 0;/ U9 l2 @; s. r/ p( }/ [
  5.         FILINFO fno;  [+ S& b% f3 ~1 C, e

  6. ! e& _. A9 H6 G3 C, i! G0 o$ D5 R. |" k

  7. ) g  ^  T  \# J
  8.         /* 挂载文件系统 */$ {) y/ e! g- N; r
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */
    % G( `6 W4 k/ _! q, c
  10.         if (result != FR_OK)# l+ L3 X4 i3 o) d& Y! W2 u
  11.         {- U. H' l, U. S7 B# [& c( U( n. S
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);8 R+ ]+ \1 `# B' u: R
  13.         }
    * c+ T2 r! p, R. U$ k8 `

  14. $ w! I1 d% Y' {  T2 @7 M$ v! r
  15.         /* 打开根文件夹 */* v: W! h4 t- {, l
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */
    8 N0 j6 t& V" B# c' |! C4 u
  17.         if (result != FR_OK)3 ~) @- K8 b$ H/ L( S6 {
  18.         {
    % X3 M+ p' t5 s# D0 D. u0 X
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);# ^+ [5 m) @, U$ t! O
  20.                 return;/ Y: g* A% i( s, b& t1 r
  21.         }* M8 ]* I% z: b$ l8 R" E& i/ q

  22. . Q/ m+ T8 n% I1 q+ j3 a6 N, i
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");: I2 ?% D: p' x, E6 x
  24.         for (cnt = 0; ;cnt++)- {2 N4 R4 M; ~: ], t9 S* h
  25.         {
    4 F1 z( d- O6 r
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */' Z* y$ U! p5 B' V+ y, Z% y0 w
  27.                 if (result != FR_OK || FileInf.fname[0] == 0). @- T. f3 i9 b! @
  28.                 {* W# |6 w6 N2 p( f
  29.                         break;4 T  A# H/ k. c
  30.                 }
    ( F) N8 {0 T8 ^7 t
  31. 6 f# I% k1 v+ b& r' T
  32.                 if (FileInf.fname[0] == '.')
    7 h: S: r) ?3 V; c) M
  33.                 {- x2 j5 B+ ]( y! ^2 }
  34.                         continue;
    ) N. R! y1 b) X- ^; M# _7 b
  35.                 }, x4 X0 s( a- D4 U1 v) H0 Q9 N

  36. ' x8 |8 c: J; z
  37.                 /* 判断是文件还是子目录 */
    , u3 S3 h  x& w' Y3 i
  38.                 if (FileInf.fattrib & AM_DIR). |8 @* c$ x1 w
  39.                 {3 O2 `  b6 |6 ]! F! ?6 i- C4 m
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);. p  r& w6 j% Y3 l  R
  41.                 }
    2 E# J- S# F4 Z6 |( i
  42.                 else( L  D& q  i( Z$ M. B: ?
  43.                 {. ~5 G! ^; d# k: V
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);
    ) G+ p. O/ l% g8 n+ I! g; h
  45.                 }
    1 B2 b- I6 N, h7 O/ N, s3 a
  46. * N) M$ p, h; B& H
  47.                 f_stat(FileInf.fname, &fno);
    . [1 I0 E& Y" }& c7 I

  48. , D; }' P- o: r, @1 b, ]# g8 E
  49.                 /* 打印文件大小, 最大4G */* w7 I3 c5 C; v! x
  50.                 printf(" %10d", (int)fno.fsize);
    7 b! j* l  @9 K/ p$ |

  51. * |$ H; u$ ^6 t- K
  52. 8 m4 q. s1 n: ~
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */$ O6 V2 X( o0 C# U- ]
  54.         }2 m5 P4 {, F/ e
  55. & u2 ~/ j' z& B' d1 q9 j, [- x5 Z
  56.     /* 打印卡速度信息 */
    % {9 z7 c- h% n4 K3 L' `# Q- W& e8 m
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)0 @! G5 V; m- |" o0 L
  58.     {
    $ O5 r+ K0 Y$ V
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");3 r( p2 {. @3 {- }7 V  x4 r
  60.     }
    # g3 o8 }/ {( q& G  c7 y$ O
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)
    4 {, u. b0 T; ]5 p4 x2 ~6 l* j
  62.     {8 b* X! Y5 }( I. H6 G- E2 H# N+ g2 f, _
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");
    ( m) B  M; ^! g. n
  64.     }
    7 ~9 ~* |; U3 D! m
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)
    1 w+ I$ Y# h0 k* p, G4 D
  66.     {
    . ]7 `" t/ ^* a. w. o; W0 A, x4 v
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    : q* L. R( Q" _2 ?$ l
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");
    1 }3 {8 F: n! x  e% T: x( e
  69.     }# ~% l9 ]) z' S# }% \

  70. 9 P/ W8 k! A) l' ^

  71. - J" l3 s: o  @, r9 L, j- `: k
  72.         /* 卸载文件系统 */7 R; Y' j. K1 D6 k" W7 M
  73.          f_mount(NULL, DiskPath, 0);0 v6 y. j9 @/ ?, T" D
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。9 G& e9 h# l/ `6 Y
      e.png
, M. p. t/ U: G) d: w& C     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。$ f6 |+ ~* A6 A  }
添加的内容为 -fexec-charset=GBK,还是修改编码的意思。; T! \" r2 h- Y& w, _2 D
      f.png   Z  g, H" g" M3 v0 A# N
     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了
5 G# D5 h- Y% G1 l/ B       g.png
/ [+ A$ L# U9 a0 e$ d      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
. Q/ t; i" K! J9 v" N       h.png / k6 p' o0 r4 {0 K
      料想这次应该没毛病了。结果,新的意外又出现了。6 S7 `! e' v8 B# m( a3 g
       i.png
# v  r. @8 R1 b       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。
2 p; o6 Q! x8 i  r& u4 n. b      j.png k.png
& ^, T; O' o; e    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。% q+ T: K  w6 t4 S0 o
" O: I" n1 S+ E; T+ M  p
      
3 I  F$ L) O" A2 ?6 Y- L0 E/ H" t9 W0 J8 S" v7 S- @

3 g& }" D- `+ `* D6 E
$ Q( v$ x  i$ `0 k6 q
7 @2 K7 `8 @/ f, K0 g4 ]
收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似分享

官网相关资源

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