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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。  r# e2 M, ^; c  c+ R
7 v1 T0 Q& l5 v) {
    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。
3 {% f) \1 q% K0 L9 p9 J* w    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号3 D. ~6 j. P0 R" A7 N
      b.png 8 N$ c- e, r" n  @9 `
     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下1 L1 w7 ^9 n) `. V9 f, M; c5 q
      ! B1 Q( d3 t) y6 Z
  1. static void MX_UART4_Init(void)
    1 b" j. w* R/ _2 K# F
  2. {1 N+ j& W: K2 X3 K3 o  @

  3. % r* T9 f7 O6 A8 N1 d
  4.   /* USER CODE BEGIN UART4_Init 0 */
    - m* S4 z6 y) C# I$ x

  5. 2 u% [! F8 s; W: M5 W7 h6 O7 }3 B
  6.   /* USER CODE END UART4_Init 0 */$ |6 d+ H# Y# Y8 d+ Q6 F- f% R
  7. % M* Y& x+ Y; ?! j- J! V
  8.   /* USER CODE BEGIN UART4_Init 1 */* w. Z( `8 x' R

  9. # h- C7 d; _% ?4 |3 |0 p, \) H
  10.   /* USER CODE END UART4_Init 1 *// G+ v! \4 `- H/ p4 t
  11.   huart4.Instance = UART4;* t- J# j% n/ Y
  12.   huart4.Init.BaudRate = 115200;/ H4 T& q1 m* F, F( ~7 e# }/ w4 U
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    ! @. `7 p5 t, r1 \- n5 F
  14.   huart4.Init.StopBits = UART_STOPBITS_1;
    8 R- u0 j4 x* H5 `3 i7 a
  15.   huart4.Init.Parity = UART_PARITY_NONE;0 P" U, i6 H! m, a
  16.   huart4.Init.Mode = UART_MODE_TX_RX;, [6 \$ {) r! U+ M9 p" u# D
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;, `  \3 t7 v9 {* V* n8 o( O# @/ w
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;7 q+ d! L, S) y( E% M+ l8 {
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    ) \2 S' j# j; `% o$ ^3 G: G5 U3 U
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;3 X5 }. Q% G& C% @# I' H( r9 p
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;; _' G& T' `4 v" h
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)
    ) h* n$ p# s: c8 z7 O
  23.   {
    ( x8 ]3 c7 g: x
  24.     Error_Handler();
    2 m, S7 O; B6 c+ i; O! j
  25.   }
    " T, U( Y8 J0 n* z1 n
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)" e" `" T: p, M8 ~9 o2 ^
  27.   {: L% @1 S( y) W* o
  28.     Error_Handler();+ i- j) x3 P6 V3 E+ R/ V
  29.   }
    ) a' p. x! C# i/ h
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
    ( ]1 {& N( o) \
  31.   {/ P1 j$ }$ e# q: ?
  32.     Error_Handler();. J5 J" R% `$ ]3 j- h1 b) L
  33.   }
    4 A' i. R1 F+ i7 C8 H- h% X- D
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)
    6 G+ ]4 [- p3 ^3 m$ Q+ W( Z
  35.   {
    2 T! @7 z4 G) |9 h" |
  36.     Error_Handler();
    & S. Q0 I* e+ E. S# _9 W
  37.   }
    7 ~0 |  o* |) R# L+ R9 T, y
  38.   /* USER CODE BEGIN UART4_Init 2 */. Y. j4 _; n$ X' t( ?* i  o: g

  39. ; T7 n/ H; v: ~8 n
  40.   /* USER CODE END UART4_Init 2 */
    " s5 @- M9 a, H; k+ k5 D+ D0 l

  41. % U! U' N& L; R( Q
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)4 [8 ]: b$ Z# p* m/ ~
  2. {
    3 O0 o: \. Y7 w
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    - O' S- j1 i- C$ `1 h
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};) T2 i( Z) H( E9 l+ w# M' e
  5.   if(huart->Instance==UART4)
    9 [5 Z& R0 k4 C( x! ~$ J
  6.   {! F8 V9 J( r2 d6 L: G7 O: z2 |
  7.   /* USER CODE BEGIN UART4_MspInit 0 */, @& h3 y( N6 C
  8. # S2 R0 b: g) S. x3 W
  9.   /* USER CODE END UART4_MspInit 0 */
    , P) @( G; w1 d  G( Q7 p* U
  10. 8 t" }  v7 s1 U. s
  11.   /** Initializes the peripherals clock
    . r4 }1 G' n) T* O, w! o4 r
  12.   */
    & K$ D. L2 }8 k6 `3 E
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;) F7 S5 d5 p- A  X
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;
    # u5 S; T: E$ M, k: ]# B: n
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
      z. V9 p# {5 m
  16.     {
    / Z& m& x9 a6 S" _
  17.       Error_Handler();
    / Z" k6 K4 p8 D1 C% A6 v' N' ]
  18.     }/ t( t: j" y) P/ \9 `( t. l

  19. 5 E6 w' ^0 i9 L
  20.     /* Peripheral clock enable */
    , d+ @' Z* U; f, K, w
  21.     __HAL_RCC_UART4_CLK_ENABLE();
    9 @# L7 }: E( [& i. {3 k- u

  22. $ i" {+ Q5 e. D3 y. X2 f4 v7 f
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    ; o; s5 b$ w* ~: ]
  24.     /**UART4 GPIO Configuration
    3 l+ S' _1 Y2 p; f
  25.     PD1     ------> UART4_TX/ l+ G& n* p4 n5 v! k  j
  26.     PD0     ------> UART4_RX# U+ o4 r  I- a
  27.     */! l: o7 R4 ^4 }9 n. ?9 h
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
    ( X0 f' k$ @+ W
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;; J8 \. J0 M8 _6 Q1 B8 ^! f
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    * f# T9 J! `/ s9 W) m
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;& C; R' L7 ^) H8 V9 [/ t
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;8 }  R$ e' q0 [* `3 `
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    - d4 N1 g$ @& o( R  \! s+ f1 c

  34. $ C8 W8 m7 c6 G% I+ l1 c! W$ g1 D
  35.   /* USER CODE BEGIN UART4_MspInit 1 */
    ) g& h( Z8 F3 b$ H. s
  36. % C0 y$ d( ?$ l  E. Z* W
  37.   /* USER CODE END UART4_MspInit 1 */
    & G9 {# Z' ^) a) U+ W, G: w
  38. / {5 b* j) K. K0 p! c- `- S/ T
  39.   }
    1 Q3 _! x% H: i( |
  40. ' A  o9 m! u7 K( L
  41. }
    2 V1 H! P5 d. s' x) g
复制代码
  1. 使用cubeIDE
    ; C# f' b  j$ x( l
  2. __io_putchar(int ch)8 e8 N9 c$ y) \
  3. {5 ?" \  \: U" Z) n; z0 h% X- m+ h8 ?
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);. q/ y3 @3 u. P# S8 X7 _1 W: v0 n% M
  5.   return ch;+ b: \! B; N4 u' Z1 ^2 v
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下1 {1 _* R# @3 s9 m! @
       c.png   m; V  e6 \7 J4 V/ s6 m
       添加输入输出头文件stdio后,就可以试试程序如何了。6 x7 s/ }' P' D& T2 N, f7 X+ Z
       d.png " H; B( p- A/ d$ [
       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。
- m9 I* F; P2 y% W1 ~3 t3 W      : U0 A7 u6 o5 H  p
  1. static void ViewRootDir(void)7 J' Z8 O* d; U
  2. {* A% C: i" y6 Q
  3.         FRESULT result;
    % U8 F7 f2 }8 ~* N2 ^( x
  4.         uint32_t cnt = 0;, A8 C1 U6 r, Y- W& _: e" j1 F
  5.         FILINFO fno;
    - C$ e, Q5 ^* y. r% a, P5 c1 k

  6. 1 S' i. w1 j+ G8 Q
  7. & o/ Y+ @$ ^) f" z8 }" \
  8.         /* 挂载文件系统 */; ~0 E6 D& o( D( b
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */% T# F4 N$ G* m4 ]0 j! O9 M
  10.         if (result != FR_OK)
    ( Y5 o; Z2 t6 K; d- k
  11.         {, ?1 C  d' \% m- i9 w: b4 p7 v
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
    * D% v4 R* d* p6 P# [; ^
  13.         }; C* ?. W" ^, Y) X
  14. . ^9 `8 r; }) g$ i2 O
  15.         /* 打开根文件夹 */
    8 H; Q  c  h7 U) k: C4 S$ m
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */
    7 G0 s& P* F, X' ?  m7 Z
  17.         if (result != FR_OK)
    7 A& P9 o; ^/ j7 h( L5 Y$ y
  18.         {
    7 L3 `  ~- j- _+ C2 ]5 e
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);8 _$ `  K) g+ D# j) J1 F7 u4 t
  20.                 return;
    7 y$ {% D' O& t! T+ z4 v) |
  21.         }
    4 |; r2 {! {% d& x! r
  22.   p* e2 \0 v8 o
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");$ n9 s- R$ f* m+ k! @; r
  24.         for (cnt = 0; ;cnt++)
    9 p3 x+ r' J, L! z" I9 l7 X+ k
  25.         {$ x5 }3 w4 Y: N/ B
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */
    : L' R  s# P' {' Z. j
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)
    3 z$ L7 W7 M5 ~1 ~# b% Y
  28.                 {
    1 O$ n' A8 x3 ^7 v
  29.                         break;& ]. b6 k+ h9 I& i- k: D9 j; n
  30.                 }
    * d6 r+ k3 m7 F

  31. , C/ i! u& f9 P, O/ }. S7 S. k
  32.                 if (FileInf.fname[0] == '.')
    , u: q& m6 g9 Y5 K( ]
  33.                 {7 H( {  `4 i  {4 ?7 s
  34.                         continue;
    " I( C% ?; x4 m
  35.                 }
    5 w3 c  Z/ e& i, h% X

  36. ! ^1 F- {0 X3 F5 U! [" L
  37.                 /* 判断是文件还是子目录 */
    ! c9 U* ^/ V) x  a0 q$ V
  38.                 if (FileInf.fattrib & AM_DIR)( W  ]% l3 r' b, |; V* w
  39.                 {
    4 i; @5 B# k3 j, c/ j2 Y# G
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);9 E6 V8 m7 `. Z$ ~1 O
  41.                 }
    / s" n# ?' l. \  u5 r
  42.                 else& x% V& S7 K5 n
  43.                 {& `7 ]& k0 z/ k- _3 m! A
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);
    # ?; Y: v+ c! {. z/ ~
  45.                 }1 \; i8 t- H4 O# S4 l
  46. 8 [' s$ `/ [5 W2 o7 u7 k! M
  47.                 f_stat(FileInf.fname, &fno);
    / f) V, [2 H4 |( W, q: |: B

  48. 3 M3 L; r9 z- p1 X( O
  49.                 /* 打印文件大小, 最大4G */" U2 A# @4 V2 j" k
  50.                 printf(" %10d", (int)fno.fsize);
    . A3 s7 p2 s1 w; Q" }$ j$ `

  51. ' \1 q% l4 H% C! c2 R8 P
  52. % S$ H) H3 F* Q- X7 d# K! o+ \% F
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */
    , \1 n5 d+ b0 \5 Z/ _
  54.         }
    . K8 ~7 ]  B  `4 K* K

  55. - F* [. V' s- l$ m( F" r+ m
  56.     /* 打印卡速度信息 */8 H  D/ J7 I# _+ M$ {
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED), }% ~3 @( h% P$ l' z2 E
  58.     {
    - g6 o  C3 x1 [9 j4 M4 t. R1 C
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");' v0 j/ w4 Q3 K. E
  60.     }7 a4 q1 h, x0 t4 w9 R- Y
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)* U: W1 u' e. K" G( V7 \
  62.     {
    * }0 W2 p7 d# Z% z
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");( E" c& S$ t3 U0 `$ @2 ]- L0 s: t  i
  64.     }
    ( D: N. e& e) W, Y0 F3 C4 R: [1 @
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)
    ) f7 N, c) F5 i, `* w+ [' N
  66.     {
    ; K7 l; r) f5 j; y3 ]! C
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    ; m5 c: b" ~% e* q; a$ X* o: f
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");
    4 o, b. r* O& T
  69.     }
    0 i: h4 r0 @5 J0 e& K1 }5 c) n

  70. - H2 Y6 F5 g" A9 p( u" G& L: O, R
  71. & v$ t: l$ k; A0 P
  72.         /* 卸载文件系统 */
    7 s( ^: V8 x& s: G- D- S
  73.          f_mount(NULL, DiskPath, 0);- `, }& c: n) z* ?7 Y' a$ ~) j4 J
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。
. G3 a; _' I- ?; [6 K5 W! Q; r# u      e.png
- u6 u) |  z" d* c. h     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。
1 n7 ^- O2 ^' e" Y 添加的内容为 -fexec-charset=GBK,还是修改编码的意思。
: A7 n6 g' L5 g: [      f.png
+ {( K  @/ h0 |# |2 e     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了
, t3 M! A$ o" p8 S5 {  y7 _; m5 U       g.png * t' }! }, F9 o+ O$ D
      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
) l6 H- e* X. ~# F2 I       h.png
8 {2 D* X8 L0 X      料想这次应该没毛病了。结果,新的意外又出现了。, j  h: [. n; `4 X
       i.png ) N5 \; r# e( a8 E. p% g
       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。& q$ X! w. ?  L; c
      j.png k.png
9 o- N  N: l$ q9 Z    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。8 ?3 b& @; B2 p. a9 Q' q/ A5 x" P

) T9 Q+ W9 A$ m      / k1 D, k: R$ K/ g; Z$ }4 p. r2 w
/ {8 |! s4 S( L' P: N4 ]0 O& z
+ A4 r0 [( Z5 h  Z

4 D2 n, S+ _8 p/ a/ @; _: e9 |/ K+ i+ t. r# M4 t  V% Z
赞 收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版