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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。& o% {7 R% g& z1 h, b+ G) S' E9 F
+ Z! w' H* f( a/ Y3 q
    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。6 v7 \3 Q2 N  t8 f6 A
    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号& j5 S4 v5 `- l9 ~9 F; _5 h" @1 h
      b.png 4 O+ J  {; Y4 K! C( z( _
     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下8 h7 |! ]7 v+ z0 V0 u
      
6 |5 F1 r" }2 N4 q; K/ Y6 z# m
  1. static void MX_UART4_Init(void)" F$ d" j+ g2 `
  2. {* S$ C" \; p; z7 D

  3. * o0 `2 M0 E$ @: p
  4.   /* USER CODE BEGIN UART4_Init 0 */( m, ^" c" j: ]5 j+ d  e8 ^: w
  5. ) c" n* c% W, |5 V
  6.   /* USER CODE END UART4_Init 0 */: {. h0 N: f* [8 Z

  7. & L3 d) T1 D' j" Y
  8.   /* USER CODE BEGIN UART4_Init 1 */1 Z8 x1 Y" x' a% n  v0 W: J
  9. 9 g+ }# y; E  C
  10.   /* USER CODE END UART4_Init 1 */! o1 R5 c0 ^8 v2 o
  11.   huart4.Instance = UART4;
    $ _4 J2 {% B1 {6 U5 M! c$ w" F) n$ ^
  12.   huart4.Init.BaudRate = 115200;8 [- r1 J# ]+ Q* J/ q! Q  }
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;, S! t6 S4 W3 v  [9 N) \, E, H! {
  14.   huart4.Init.StopBits = UART_STOPBITS_1;
    7 a8 ~7 U4 n' p: k, j  t' d
  15.   huart4.Init.Parity = UART_PARITY_NONE;
    " [, Z& Z2 @1 R( w
  16.   huart4.Init.Mode = UART_MODE_TX_RX;
    1 O9 ]9 _9 H( }7 m/ p$ \: n
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;+ x  p8 w" m$ ^& v
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;$ \7 v/ B: ?5 p$ X$ w7 f
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    , D% t  ?! `5 M& E/ u! M. H
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;; c; W2 _8 E! `
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;; m- i+ J: J/ Y  y! @; }
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)6 c& @; _% d; H9 ^0 ^3 Z; |( T2 y+ ^
  23.   {+ [6 ?! p) |  Z& C* ~
  24.     Error_Handler();
    + P( B% C5 i' k3 j' L
  25.   }
    ( ~+ U" U9 {8 W1 W5 u! \
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
    ' ~! V+ j* b0 b$ z% q  P3 c
  27.   {
    . _5 a) |* l9 u8 q2 o# L& C
  28.     Error_Handler();
    % U! [3 f+ t9 w. p1 m0 H
  29.   }" L- w$ ^! J  ]1 j( i; o% I
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
    0 ?* w: v2 ]; b' \
  31.   {5 u& V# X( t1 d, H5 y
  32.     Error_Handler();. Q% J0 Y4 R( z' j+ {
  33.   }7 T9 [  ]+ I# P( `' ?5 ?  u
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)' K7 V6 a5 O+ s7 x4 u
  35.   {+ T! b, u8 j) u" [1 p. \
  36.     Error_Handler();
    ) R8 U. |2 J9 |, F/ Z) b( m9 Y9 ]
  37.   }% d  D2 `$ b1 Z
  38.   /* USER CODE BEGIN UART4_Init 2 */+ k: d9 |( R, a  ?6 ~
  39. / L- J, E, T! G% t  G8 r9 }
  40.   /* USER CODE END UART4_Init 2 */
      p# `$ \- t4 Z
  41. " Q9 L% Y* f2 Z" R8 d: _4 @, C
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)  ]6 ~7 b$ g( `) H* I+ o$ [: {6 m
  2. {
    8 k# K8 z+ F  K1 w
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    / B0 g: b% ]" h
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    3 n6 ]) l* H6 g9 ]
  5.   if(huart->Instance==UART4)8 F( ~" I8 f& Q* U! u. _! b3 i
  6.   {
    8 v7 R. ]8 V6 Q& a0 g$ p0 L; P
  7.   /* USER CODE BEGIN UART4_MspInit 0 */8 ?% h6 s8 \  g

  8. ( K1 K# v+ t8 q0 ?1 b2 Z
  9.   /* USER CODE END UART4_MspInit 0 */
    4 a% N  d+ [5 }2 h
  10. * z  L) A* |2 X& F8 R5 t* W1 s( N
  11.   /** Initializes the peripherals clock
    7 e. u- Y5 V1 `
  12.   */5 T! k, |  w1 {1 ]$ ^
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;
    ( X4 @1 j+ n# T
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;
    / T5 k2 v8 r4 A+ `& q
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    * z, ?( `& I+ a' p: ?. h; y
  16.     {
    7 o; X: h; l/ m
  17.       Error_Handler();
    ! P  A" N. v$ J3 G+ r
  18.     }
    2 ]9 t0 c  `0 x) C0 K
  19. # A$ R9 t" W% }: U4 Z
  20.     /* Peripheral clock enable */
      w& S& y: e$ L& k5 U  u
  21.     __HAL_RCC_UART4_CLK_ENABLE();7 S  G; `/ `% J" f
  22. 6 ]. \# B4 v  U% B/ |5 g
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    1 d- H& N4 D4 c% W
  24.     /**UART4 GPIO Configuration
    4 E" T  q* g) d4 v- q
  25.     PD1     ------> UART4_TX- D. N" t  ~/ d8 w( x- F8 e4 z
  26.     PD0     ------> UART4_RX% I7 Y# t* i1 B1 n6 A$ C- X
  27.     */* W' v: ?% w; \+ e) L
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
    ; s# e4 H! w; i5 Y
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;: Y* d( i8 x% P' F3 }, a  D
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;9 b: K* b" n3 ^# Z- T
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;! i" C/ F: |& Q/ d+ R, w
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    ' z" \4 B" A1 N4 y+ L+ c9 L  [+ ~
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    ) e8 l/ j. }, C5 P7 ^6 Y4 }
  34. " T1 a2 `4 E) T- N0 |& A
  35.   /* USER CODE BEGIN UART4_MspInit 1 */& B" T) Q% A# `4 O

  36. 6 c" U! Q$ R" B" {. r) v/ b
  37.   /* USER CODE END UART4_MspInit 1 */
    3 F% @( Q) H! \9 U- m; s  i, P9 G

  38. 0 H% z0 s3 e. u# R, f) I
  39.   }
    4 u: B. z5 F- o, n# E% d
  40. 0 b6 ~9 v1 Q, p
  41. }
    4 K9 q9 J0 e9 A9 {, c2 b4 q
复制代码
  1. 使用cubeIDE7 B& s: I3 l6 p; _( O
  2. __io_putchar(int ch)7 P& @% n! f- }. m
  3. {
    & a" l, [' Q( Z9 T3 l3 f  A
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);
      i! C3 q% [, N6 A6 t* p' K
  5.   return ch;
    : r- {! d, n2 a, H# n) t+ c
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下
) p2 r8 l7 C- m2 c$ O+ k       c.png ! H0 G# ~1 M3 ~( G8 ~9 z+ B/ P
       添加输入输出头文件stdio后,就可以试试程序如何了。6 A4 W2 g7 m  T6 h, ~4 B! N# `6 Y! \
       d.png % W' M" |+ |! S* h& A' o' I) }! d
       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。* b; W# C. X- G# F0 E9 J
      + j' t! {0 D3 `9 P& z! T
  1. static void ViewRootDir(void), D0 n/ v; W' C9 e
  2. {
    , s3 M3 N* i- i" q1 M) g6 z/ p
  3.         FRESULT result;* E" \; Y* B# L
  4.         uint32_t cnt = 0;
    8 n5 j6 }: q7 b' p* x9 {  t
  5.         FILINFO fno;3 ]) [- h* }4 L% @$ b+ A5 k: g; }/ }
  6. # d6 u  {3 J3 Q3 ~. p

  7. # D# ~2 s7 n! A% o2 \
  8.         /* 挂载文件系统 */, {0 P$ V4 i3 `8 G) D+ r/ h. s" t
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */
    ! c4 P& |; o' j- x
  10.         if (result != FR_OK): f$ N( C9 }- v
  11.         {
    9 M0 J0 N+ `+ J
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);- ]) z- C, N/ ]1 Z  h
  13.         }# f- E6 o! l7 [

  14. * M9 j( c; j0 H$ E8 Q* F4 u
  15.         /* 打开根文件夹 */" \1 M" E; C2 z$ w
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */
    # ?3 w. F' `$ D3 f
  17.         if (result != FR_OK)
    ; s& x! c7 B& H6 ?
  18.         {
    / S) U1 V' P; j
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);
    6 ^& c+ E' N! A7 l% A: L2 g
  20.                 return;. Q, F4 F( [2 O
  21.         }
    1 B( Q0 [5 Q9 F8 D& y; ?& m
  22. 9 X! H! B9 X  _5 P
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");  q$ Y4 }6 A* ^+ ]0 P
  24.         for (cnt = 0; ;cnt++), ^  R+ ~% l5 r4 u% b
  25.         {
    ' a8 s7 V3 y/ K8 u+ p8 C: t/ v
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */* j+ i( j( ~7 ]
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)
    2 @* j$ `* T- r& a
  28.                 {( {. E# \) p1 w7 [1 x; }; @' d
  29.                         break;
    $ R# ~" b4 ]7 \7 Z
  30.                 }
    " {1 ?7 A6 h7 K# i8 _3 O
  31. ) ^7 m+ Q! _9 }6 h+ }$ @
  32.                 if (FileInf.fname[0] == '.')1 D, \; v, s  M1 t9 b
  33.                 {  \" m7 Q% s, g- F
  34.                         continue;
    2 M, Q( {7 W& X% B- \: D4 {3 `
  35.                 }
    ' U( t  P4 B/ Y$ `! e1 D( d0 w

  36. , G: U2 L, m0 x$ R" v4 b, f9 H' f$ r) e
  37.                 /* 判断是文件还是子目录 */( b0 q& v2 J8 ]7 f$ c0 y* J
  38.                 if (FileInf.fattrib & AM_DIR)
    % d2 |- w; T6 s/ ]
  39.                 {
    3 V) W( y) G$ V! m2 ~  R
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);
    " t9 |1 r4 e! ~# k
  41.                 }
    , d( M' \5 ]+ Z& e1 n9 k
  42.                 else1 w8 X" |( ^. j$ D) ], C! \- I. ~; x
  43.                 {' L4 M* T9 p# v7 \% M- W
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);0 a2 P4 {+ p' G& h, A
  45.                 }
    3 ~7 {7 R8 W9 f$ L

  46. - W, b' \# b5 k. s7 V
  47.                 f_stat(FileInf.fname, &fno);
    6 t1 q/ \9 p) z: ?1 u7 X1 `: F# O

  48. - @0 x1 A$ ]% t' g
  49.                 /* 打印文件大小, 最大4G */3 h1 V+ K( o# @, u
  50.                 printf(" %10d", (int)fno.fsize);
    & _: q5 K3 P2 o) z

  51. 6 X' j- i" |1 P+ n" k
  52. 2 ]8 l7 P+ v: I4 S
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */
    $ E+ [9 d% a, P0 N
  54.         }
    . L' X4 x5 b+ ~. m# O' c
  55. $ d( m1 @) e' o6 M
  56.     /* 打印卡速度信息 */
    - U, Y# h1 Q1 [5 h3 j  a
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)
    0 ?9 m% t6 p' p  i  e3 ]7 _5 h7 L
  58.     {0 r, x% U: Y% ^) L7 v
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");
    9 z! ?$ b+ [5 Z: c: U- t% ?: l
  60.     }
    9 E' g9 Z) H4 A7 ?6 x
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)8 T" ?" N/ J+ W1 J2 J8 C
  62.     {
    : C  [  j) q( \8 Y
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");
    7 w) W4 t) Z( s' ], I' N/ y, V
  64.     }
    4 K% `0 W" w# A' Q% P+ f: I
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)
    ! \+ \4 I( l6 z) P) s
  66.     {' N0 o1 u4 K1 `0 ]
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    & z- k* {, X! G; r
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");; X7 R1 A- z1 k( \; |$ ^) x
  69.     }
      C/ u. \$ ]: O
  70. $ [4 ]0 i+ G1 U0 j

  71. 2 V. p8 ~- G+ Y( C
  72.         /* 卸载文件系统 */
    % l* Z4 r, Q) J$ P3 Y
  73.          f_mount(NULL, DiskPath, 0);
    0 R1 R! p8 B# f6 U+ q2 x
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。+ Q) y7 `( z/ ~, E: p9 [4 O
      e.png 2 ~  A" S: p1 J" ^. r
     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。6 X. K$ V1 u- b3 I3 V$ s; \( G
添加的内容为 -fexec-charset=GBK,还是修改编码的意思。
4 U* V. `* x  j' V: {% R3 u      f.png
% ^0 ~# m$ l5 m& @! d) H8 C8 l     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了* i1 [; X  e+ W2 X
       g.png ! ^! K' f( e) S( L0 m! T/ `7 s* H6 E
      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可
" [- u& f& h. k# W       h.png . J- x* x. I# ^% B2 V4 C
      料想这次应该没毛病了。结果,新的意外又出现了。+ I; K/ c) D. o" f* }
       i.png   A; n: J* Z) h6 M/ |- F" J
       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。
1 x3 n8 T; K+ B6 C$ f      j.png k.png
9 D6 K9 J; x0 Z4 I) z: t    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。
8 S$ i" `+ Z3 j0 `6 E$ v- L) b  {; |+ r
      
; N. C1 l: v; i; [/ @9 l, n8 l: G7 \! X, K" \1 X8 r5 q
+ s) H  \/ |2 U3 A/ B8 {7 j$ S$ |

8 H! E0 N' i% ?5 `6 W6 b: ]. a& R5 f6 Y5 L- j0 @& W, Y+ L6 g
赞 收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

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