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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。& P+ Z' A8 O! z8 o4 u
' H- J  M0 s; l+ x& B5 p+ e
    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。9 \* n% [4 e& l" `
    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号
% k3 Z6 [, V* }  f$ \      b.png
) k: E# [. H% F' C     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下
4 b+ I4 K; C9 j2 V      
* P4 w* J7 N( d1 K2 J1 t/ S
  1. static void MX_UART4_Init(void)
    1 |$ H8 {4 {7 L; w
  2. {! F8 z, }/ Q# r8 L

  3. / Y3 q2 Z. ^* x, W1 o) T
  4.   /* USER CODE BEGIN UART4_Init 0 */
    ! y- X' X7 H( r- A

  5. % ~, U+ h1 P6 ~$ _4 q
  6.   /* USER CODE END UART4_Init 0 */
    - }- ]# J% C7 Q$ q

  7. , _5 s$ e8 {7 x# ~9 T2 V
  8.   /* USER CODE BEGIN UART4_Init 1 */
    ) Y- y- l2 E8 ~

  9. ! w2 R. a& R# ?1 ~7 }
  10.   /* USER CODE END UART4_Init 1 */0 n& \9 ], u- N/ S3 G3 V' a+ f
  11.   huart4.Instance = UART4;8 x& w7 _- a1 [
  12.   huart4.Init.BaudRate = 115200;; S5 B8 i3 u% W
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    - R3 Y4 u4 _: f3 Z* o$ |9 O4 \
  14.   huart4.Init.StopBits = UART_STOPBITS_1;$ ^) a, }! j# ]" ~! \, A0 {
  15.   huart4.Init.Parity = UART_PARITY_NONE;/ d8 q- e4 J" Z1 I  b9 k% R
  16.   huart4.Init.Mode = UART_MODE_TX_RX;4 B8 i8 h8 s& {) i6 F1 y" _' L$ y
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;/ V" b+ i) `3 z( H' R' P
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    ) w% Y6 v' u( O. \
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;( u. i1 n4 ~) C5 N
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;" y4 s, R  h! z7 [, A8 e7 }
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    & w% r% _5 L3 K+ o, ]; M
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)
    ) g2 v" g  h8 Y4 w: t( a9 s& A
  23.   {
    0 m1 n& V: z& O
  24.     Error_Handler();3 f6 q) S: F9 T$ X
  25.   }
    ! F! d, ]0 m! L9 w. X5 G
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
    . j, B7 B7 `. B( c+ q% S
  27.   {. q1 j& u  f3 K2 u3 b6 o( M+ D( W; ~
  28.     Error_Handler();
    0 l; @% {8 J% t3 @6 }& F
  29.   }
    - `& o- A! {, x
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
    0 T# z! A6 U+ f- w4 K
  31.   {; D) i8 D3 k* J; |- k
  32.     Error_Handler();
    6 v6 Y4 K  W7 L
  33.   }
    ( H( J3 a; `& a$ s6 s9 c
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)( N3 b  B6 W5 S2 z2 Z$ N
  35.   {
    : c& [) B# w4 J+ D
  36.     Error_Handler();
    % q( Q! C3 A! y# o
  37.   }) t) X7 H4 @1 W9 S0 M
  38.   /* USER CODE BEGIN UART4_Init 2 */
    * D/ M  e9 L5 B' q& ?
  39. , B; S! k1 B% p' i' j$ }  e
  40.   /* USER CODE END UART4_Init 2 */
    5 E) j- p1 g) x+ G
  41. 8 i( R& I2 c) {
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)+ i5 }! G3 n9 `
  2. {* k: L* f! ]' \: z
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};: [0 r3 @. D( P' V+ y& R' k7 K, z
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};: q; z4 E0 }9 p1 C: f% D# w
  5.   if(huart->Instance==UART4)5 A  l+ t6 h1 u+ M
  6.   {
    3 ~% U2 ?( z' W2 s* L% y2 c
  7.   /* USER CODE BEGIN UART4_MspInit 0 */2 P3 j8 ]9 d" Y# v
  8. / \1 g& y( C* e0 X( ^  {+ ^( G
  9.   /* USER CODE END UART4_MspInit 0 */, A7 w( D' k! I& s2 j
  10. , M( X* ^1 ~6 u" Z" g, L. ^
  11.   /** Initializes the peripherals clock
    % S6 c7 k, _( d% ?9 v- v
  12.   */
    9 M' r$ s5 a9 Z; [" Z" N
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;( t7 x8 [! x) O* f" q: E! A
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;! C: Z  w9 O& G+ V+ V3 c1 Z! c! a
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    6 V5 n. O5 ]8 ]: s7 {
  16.     {
    8 N7 n4 D8 l$ p6 H! T
  17.       Error_Handler();1 a: l% j  m( ^% L- i# \* E% E8 S
  18.     }1 Q* D- s) L& H

  19. 3 h2 g/ J( H% F& R
  20.     /* Peripheral clock enable */
    6 F. m2 M, j$ R- d0 Z1 P
  21.     __HAL_RCC_UART4_CLK_ENABLE();; Z, d5 H$ ^3 N# @$ [

  22. ) z% ~( m4 N+ p6 I
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    1 B7 P( K2 l+ q+ ?
  24.     /**UART4 GPIO Configuration. w% t* t* z2 l
  25.     PD1     ------> UART4_TX
    & c) h- F, W( Y5 u  F
  26.     PD0     ------> UART4_RX" v, h4 E7 j7 N( N/ z) @6 Y
  27.     */
    / r9 R( U6 {  {. \$ B
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;" o1 M2 y% U- V) {" @( T
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;& e& d1 b# `9 r
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    ( t( ]- g/ d( N  p! Q5 S) g
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    7 D( m( q0 ]3 n/ i
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    6 {  O- O0 ]' u. i. R3 P7 V; B
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);% m, |6 q0 M+ {" a5 M

  34. " B0 v1 ~+ s1 p1 K) B- M7 L
  35.   /* USER CODE BEGIN UART4_MspInit 1 */
    7 u- E" t% @* K# @/ w

  36. . R# T7 X' M4 ]& ^
  37.   /* USER CODE END UART4_MspInit 1 */1 w* T: c& |$ V8 g; M  Z/ O. l- k

  38. 8 ^! X. U7 h3 F6 o2 L4 g
  39.   }4 o  ^5 J8 r/ n6 O

  40. 4 P8 y1 d3 Y# P  I, j6 [
  41. }
    ; s. j* o# @( K- z- m2 y
复制代码
  1. 使用cubeIDE
    7 O2 U7 {) O, Y9 S+ E+ ~* @
  2. __io_putchar(int ch)
    $ W7 H* ^- [, g# c  f, c8 A( J
  3. {
    . V/ _2 K$ {6 e' T
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);
    . |6 g2 b9 [! |3 K8 y( X
  5.   return ch;
    0 c6 |( ~4 s7 ?- }8 f
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下1 _' m! z% V& O# N
       c.png 8 n3 ~' s+ W4 M0 Q
       添加输入输出头文件stdio后,就可以试试程序如何了。9 h6 X5 t" h! z: g( B7 i
       d.png 1 H, n! k$ D2 ?) i
       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。
6 a, T7 Z" X3 Z6 y      : K4 V/ M) U& p$ g8 S& _" Z  E
  1. static void ViewRootDir(void): b) Y- H0 {" S' g# m
  2. {0 t) D) ^7 \5 v% w. {
  3.         FRESULT result;3 l$ E; u' j) t* K2 Q1 C7 Z
  4.         uint32_t cnt = 0;
    # S" B7 E  z* j- W# }
  5.         FILINFO fno;
    2 h( _+ ~# q; i4 I; y( _6 Z3 l
  6. 2 V& Q# s0 s# H/ I8 p9 k
  7. - _- h# A7 n3 [
  8.         /* 挂载文件系统 */& j, \  L$ o/ H* ]# _
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */* V- r( v' V, x0 U
  10.         if (result != FR_OK)
    ' ?! g1 p8 l1 b9 h
  11.         {
    5 G& U1 }; d$ R, v, K$ j6 j
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
    # t6 a! y; U3 h# ]9 i
  13.         }. n# R1 x: x2 b. N" G5 Z" Q

  14. " \0 W7 D; `2 H, x. W' P
  15.         /* 打开根文件夹 */
    " E5 q0 T1 |7 m; j
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */6 P/ N+ n' u3 |3 c$ Q
  17.         if (result != FR_OK)
    1 J- D& Q3 S+ C7 \$ c- [7 T& B
  18.         {
    . g; ]  f& `/ N) p7 ~9 r6 k7 P) B
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);
    , x3 G4 j' f' W7 d
  20.                 return;) V- G! l( \1 U6 [
  21.         }
    - d" B- g# V/ D4 N' y7 |. L
  22. 9 |$ W# O& ?& @4 m1 e7 h, ~7 q
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");
    1 W- J! x; d# V* e! C
  24.         for (cnt = 0; ;cnt++)+ x% A% Z3 o1 s6 @$ o' N; V
  25.         {: Y1 h& F. f7 I* l
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */8 ~/ r/ _( F# g$ \) B
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)
    3 A8 @% i  j' e9 `! |& q4 r: ~
  28.                 {
      q& h- a, n7 a1 W  k
  29.                         break;
    * w7 j6 K, c+ R' R
  30.                 }
    9 ~" J! c/ l) I+ J- A1 V2 Z% c
  31. / S1 Z3 B! a* u. }* X% n2 R+ m
  32.                 if (FileInf.fname[0] == '.')) T% ?" Q: h# f, X. G
  33.                 {
    2 ~& x2 A% ^& T, T5 a( N
  34.                         continue;/ N% r" r0 B/ m1 l2 X. t5 ~. |
  35.                 }
    7 J( W; }' {4 _4 Y) ^& U
  36. : q* N# I. S" f' |* `7 ?$ E
  37.                 /* 判断是文件还是子目录 */+ t( [8 q0 x% P
  38.                 if (FileInf.fattrib & AM_DIR)
    % r4 B9 k; Y. v# E3 r
  39.                 {
    ; W: l: Z! D( j) ?5 g# U/ p+ g
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);
    * X( F( n, M3 J* V/ ^% e* {' |
  41.                 }
    , ?% i" f& \- w. f# V' n
  42.                 else
    0 S4 W7 _$ M' S' C2 Y5 B/ }
  43.                 {
    $ J" y9 i( V& n
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);2 k: R2 A8 G/ i) @9 H
  45.                 }
    8 B1 H! t8 w9 W. ^
  46. ) M1 H: Z3 h7 R7 ~$ u4 _
  47.                 f_stat(FileInf.fname, &fno);
    0 b- O  s( [+ h. ]' G
  48. ( J/ Y) ^3 U! u. i- m% w( I8 `% x
  49.                 /* 打印文件大小, 最大4G */4 ?& T" s5 w' M- x# e" G  ?
  50.                 printf(" %10d", (int)fno.fsize);$ ?2 s; |; Q4 H% M1 j$ N0 a' t- r- s

  51. 2 B" w# s; y6 P* M9 |7 d" m
  52. ) R, b- y! j7 G$ e! G
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */
    1 q& y# l4 Z% ?  Z1 p% e2 r' ?
  54.         }; `$ r4 D# M+ o
  55. ( G5 ~; L' [$ E( D
  56.     /* 打印卡速度信息 */" p2 n  T/ S# q# k. R- r
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)) Y  @8 {  ~+ ]
  58.     {, T3 l6 O+ e9 k/ H3 x% Y
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");
    : Y2 c5 ~9 p  |5 ^! Z' O" J
  60.     }
    6 j. X! s' U. Q7 [. c
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)+ E! H5 N. ]( H3 ~* w4 A
  62.     {  Y) L% b" T, u0 R: H: Q$ K
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");' Y) N) n1 B& B1 g7 p* L& A- q
  64.     }
    8 M5 }5 I! n0 F4 {  M
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED): d: P2 G  t1 X
  66.     {8 r& p% Q  \2 l" f
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    8 }( T/ Q' W; {* ?' ]5 |+ t
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");
    & O4 G; [( _6 ~2 y/ g% P
  69.     }
    3 [! j" G/ }- `) f' ]0 `5 ]
  70. + f, s; z; B4 p7 Z- ~: @, M5 Y

  71. ( g9 t% x  Z) x
  72.         /* 卸载文件系统 */
    ; q7 @9 n. S; v! X2 k6 i; U, V
  73.          f_mount(NULL, DiskPath, 0);
    5 m2 M, v5 w# D# b# b
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。& G; Z$ k% z+ h. Y4 l9 J
      e.png + k4 F$ O! {, v  Z# ?9 e
     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。! H. N/ P0 m) I
添加的内容为 -fexec-charset=GBK,还是修改编码的意思。3 A3 p2 G  k4 C+ }" M: N
      f.png   ^' i9 s9 H7 h2 Y) W! W) a
     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了4 e% T/ I) r9 T- K4 Z
       g.png
& p7 [) x  R  s7 `) M      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
* F, a3 K( Y) H2 [# u1 h       h.png   N6 U; x* a5 ~5 L( }: k' F
      料想这次应该没毛病了。结果,新的意外又出现了。
6 g, c' i3 q- G5 ?: j: J/ C       i.png   Y# V2 }+ L9 D/ p. r" `
       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。
8 D! [; y( R2 l9 ^" q      j.png k.png
  F: L1 S0 _" n! [4 ]    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。+ P9 Z8 ^% J1 L+ t$ p

4 E8 F; c- n% D) i% z5 j  x      6 X4 M- P7 I$ F; \
- T8 n; C7 a3 N/ a: V
. E* Y2 E$ }. \6 G9 g

- _5 [" s  W' h" C* ]5 u
  ]8 G& T# b4 K
收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似分享

官网相关资源

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