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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。
! Q" V+ X" [( [9 a9 }
6 q& O1 L7 L# B! @. _    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。. |% L; t- C" l. E* n
    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号
4 l5 S* x3 S6 R7 _) q& G7 @* Y# r1 d      b.png
% h0 E6 `7 |/ t) ]0 t$ N     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下. h3 q, C& J+ K
      8 S* l. S: H- p1 ~( ]5 A0 N. C
  1. static void MX_UART4_Init(void)5 Z4 F6 M. {1 H* B* b2 w
  2. {
    8 g* X5 R% ^' c
  3. 1 a' i; E' Z. _( E5 o5 I
  4.   /* USER CODE BEGIN UART4_Init 0 */
    ( v$ y2 t* k' _* B2 z

  5. + y) B4 Y" ?0 [0 I4 N9 M
  6.   /* USER CODE END UART4_Init 0 */
    9 u; Z3 d3 Y9 B1 P8 C! `) M6 H
  7. ! a: u9 I. k  \- s* i+ w% N& Z
  8.   /* USER CODE BEGIN UART4_Init 1 */
    : r: ]2 J; o' a, a1 t$ a

  9. 2 {0 ?& B+ t6 ~' F
  10.   /* USER CODE END UART4_Init 1 */
    & O5 u" J/ }  j
  11.   huart4.Instance = UART4;. }* K$ ?/ r- G% ~( r
  12.   huart4.Init.BaudRate = 115200;
    1 Y$ p3 v$ a2 l: ^& K4 Q( L5 y* r: c
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
    2 g8 x, A+ Y( j2 |( k" O+ B
  14.   huart4.Init.StopBits = UART_STOPBITS_1;8 [' m$ B8 W3 i% H; J
  15.   huart4.Init.Parity = UART_PARITY_NONE;
    . v( D) ^+ P1 S9 p* o0 g
  16.   huart4.Init.Mode = UART_MODE_TX_RX;
    0 l* D" z  H6 K/ _5 F
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;  S' _& _! _% y) ~& o# @& q
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;! C2 i3 t- h2 B- v  j9 J% W
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;& d9 ^* ?! [5 P2 J4 O$ k
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    6 d$ h+ u3 Z' e7 b, v& A$ h
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;5 ], S; l' O8 O& g3 a6 `/ }
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)" }- \7 }8 f1 `6 C' `& c" u
  23.   {+ j5 i6 F& {& X3 i, A1 P
  24.     Error_Handler();
    . U1 v- `, U6 u/ R4 o7 N# a" I
  25.   }2 H, v& N. ^- f9 S$ E3 @
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
    " w( R- [+ D( i6 V4 _( m
  27.   {3 a5 _0 J% h/ x; l1 k: k8 X4 r
  28.     Error_Handler();2 {- Y6 H, H" f- C" z0 h
  29.   }
    2 R! z6 b6 `4 _) v: X
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)0 s' T2 o8 K! k. q4 E1 s
  31.   {
    # _& x+ T; S, y+ R
  32.     Error_Handler();
    * H2 s  t' l" r/ }; g( U' }
  33.   }* L7 v# n; o7 g0 K0 t9 I" @8 z9 A
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)) g! m/ A2 O5 x- C& I5 Z- B  a
  35.   {
    # T! `' M- e- e$ L5 G
  36.     Error_Handler();  ?4 N8 J& g% c# D$ N; p3 C4 I' ~
  37.   }' ~" u7 f+ b% |, @& H0 _
  38.   /* USER CODE BEGIN UART4_Init 2 */! r+ j3 _* W3 }" S" L  E

  39.   n/ e% _1 j' ?7 u8 K. c: O
  40.   /* USER CODE END UART4_Init 2 */& W- I& f+ F- q, {7 h
  41. % g- K0 ^8 r5 z  t3 R+ m4 z
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)
    % N6 t# K+ J. r* X
  2. {8 M8 q) l! z: h) u! p+ Q2 u
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};: |4 [; F8 T* v
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};& X7 S" g( @+ z, p: }) O& K
  5.   if(huart->Instance==UART4)0 X/ K( W0 i: V! o% a# u0 ^3 v! L
  6.   {. T6 K( j8 b6 x, f5 K) P( s
  7.   /* USER CODE BEGIN UART4_MspInit 0 */
    + o6 _, _5 F: C, P4 ?  \
  8.   A- y* ~" x. g$ V9 m4 i
  9.   /* USER CODE END UART4_MspInit 0 */. O2 F$ }- E) g; S

  10. , S1 x/ f5 Q! N0 U4 k+ Q2 C2 [
  11.   /** Initializes the peripherals clock
    1 ~; @# T* k. z- C" E* K  _; s. k
  12.   */5 e9 c6 S! m+ n3 O( z
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;; M3 x; E6 S, P, c' i' g
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;
    # \$ y4 ?0 D2 p8 s  M. l
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)0 W+ A+ e& x: ]  m
  16.     {: o! \8 c, K. q
  17.       Error_Handler();
    8 x" Q, {' Z1 x! o9 }; T
  18.     }
    5 ^$ i( C; _+ G0 V/ @
  19. 8 F0 i% B9 C6 w+ i. d
  20.     /* Peripheral clock enable */8 Z, j+ }$ G  m
  21.     __HAL_RCC_UART4_CLK_ENABLE();
    ; K5 g+ e5 V) T' H1 \" u6 ^

  22. 9 @: L- T* `2 g+ p% Q4 H
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    4 r' R* O9 b7 t" E# u  ^. g
  24.     /**UART4 GPIO Configuration
    & T- n' {+ t& V. ~
  25.     PD1     ------> UART4_TX
    ; l8 S( D8 }* T7 k  u4 R& g
  26.     PD0     ------> UART4_RX" I% X, d- c% b6 j- k; ]7 ]; H
  27.     */
    * Z  p& ?8 \# l  F( G' `1 E
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
    + K3 R; X' z' F( u3 j
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;/ a# D/ Z6 n+ ]( y/ [: V4 {, Y
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;& O7 Q/ a# [" s4 G( g( b
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;8 }5 E/ a( Q2 _# M4 x  m+ w
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;& o4 x$ V$ H9 U* D7 f5 k7 y& ]
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    2 I* ?7 J9 i. P% h$ A
  34. $ g# h- ?7 N# v3 h
  35.   /* USER CODE BEGIN UART4_MspInit 1 */  C( |, D( W6 _1 I' m/ u2 a
  36. 6 Q3 l! O/ F2 b2 ~1 s$ k
  37.   /* USER CODE END UART4_MspInit 1 */
    - r: @$ ?6 K* K8 ^% x

  38. 6 |7 o- _) w: D& H5 a" h# f( E3 R  l% J
  39.   }
    5 P* H& M9 {2 Z* z9 q
  40. & c: c! h4 C' j2 s# l
  41. }
    6 |) B* A. I4 N) N0 O
复制代码
  1. 使用cubeIDE
    5 Z! K, V7 B2 P3 d* b; {7 @9 T0 o
  2. __io_putchar(int ch)! k8 _7 K" b# F0 v4 l9 X* ~7 h: n
  3. {2 T. }$ X  X3 y* R( L: u( ^8 U
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);) }4 w) f$ {) ^7 t' i3 k
  5.   return ch;
    8 x: U2 S( s  D) X  ?; ^8 h
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下2 u/ _" I3 \7 t3 }: ^, Z
       c.png 2 V! ], i8 I1 S
       添加输入输出头文件stdio后,就可以试试程序如何了。! z) b1 k4 ~" V' v: j
       d.png
- P0 c6 a, b( n- l9 o       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。
9 [* V) {, G# a0 r. Y2 d+ e# E+ G, w3 U      
' k. g$ B  x  f$ }7 h" V
  1. static void ViewRootDir(void)0 P" c3 f& ~7 ~& ]* y: r
  2. {9 h. I* i, V& h9 ~
  3.         FRESULT result;- C# v/ _- H& [
  4.         uint32_t cnt = 0;" |( v! J: ~$ ~) S/ U# p/ i" E$ d
  5.         FILINFO fno;
    & Z$ G$ J2 r* Z  y7 T
  6. ; q7 a7 `  @9 C: y0 R
  7. ' P1 v0 k8 N9 R( D3 d# F
  8.         /* 挂载文件系统 */9 T' c1 W. b% I6 \% V
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */
    8 x0 C/ B  v( U5 J
  10.         if (result != FR_OK)
    : k* q# k# L0 G0 g' k, _" @
  11.         {
    + u& C2 ?  ?- E% [! p
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);
    & P7 i2 ?% L' Z$ E% I
  13.         }
    : ~" A/ l' `: k7 _7 |% B
  14. 0 n- ]& u4 B3 _: e' s5 L
  15.         /* 打开根文件夹 */
    ) q/ I! D+ @& p& m( e9 F
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */- H" C( h+ [* p# Z5 h
  17.         if (result != FR_OK)
    + s3 I5 ^/ [) _) ~% B5 ~+ C
  18.         {: H, a, I1 U+ o5 T9 W. y# C6 c
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);
    , Y1 I+ V4 [# f- I9 ]. g$ j
  20.                 return;) w! |3 z# L  Q
  21.         }, |2 H; A+ V% N
  22. 8 r4 _0 o: [3 a+ }; d$ d
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");8 x/ n9 T2 [! z! L) |) p
  24.         for (cnt = 0; ;cnt++)  ?% P- v, k* W( W: i0 j0 ?
  25.         {+ W7 s, D+ T$ x: @  n( L
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */
      s5 D  T+ a/ g3 F! k2 o
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)) ]) m* z' I- `+ c5 C
  28.                 {
    : j) E! m' _2 ]/ `7 t& d
  29.                         break;
    3 \- v. f3 o3 d. m# ~, ?* E
  30.                 }
    / M( J( Z$ Q: O/ H1 {  D" Y0 a. b; X

  31. # t9 i, h: F0 A  ?* T
  32.                 if (FileInf.fname[0] == '.')( h8 ^) K  s' U
  33.                 {
    / W/ g# u" j8 n( u( P
  34.                         continue;* t2 s9 x, n6 d! J3 u! s( c
  35.                 }2 b* X3 k5 `: {* [

  36. $ I: Y3 Y9 h- k' v
  37.                 /* 判断是文件还是子目录 */& G- E6 o5 @  D# u+ q- P. @
  38.                 if (FileInf.fattrib & AM_DIR)
    5 a# L1 l! h7 t! p
  39.                 {
      `  P9 e% x. [
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);
    7 Z6 _' `) [/ ~9 K8 I0 v
  41.                 }  q1 q* ]" D% Q) R( d: o
  42.                 else+ Y" ]5 X- p6 U; x6 |% M( H/ k) d
  43.                 {
    : y# Y2 Q/ H7 N: P
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);
    + K8 J, g( H, k% V! @) |& h8 h2 P
  45.                 }( x9 c1 Z4 T5 r% q! u4 N. _

  46. + r" {& H- \8 y! {5 z/ h
  47.                 f_stat(FileInf.fname, &fno);' [* ^! _+ k9 E2 s& v, u: L
  48. $ ?1 ~1 n/ c3 A, \; \8 J  O! i
  49.                 /* 打印文件大小, 最大4G */
    ; M# M( V8 h, Q# S/ O* Q3 ^
  50.                 printf(" %10d", (int)fno.fsize);
    ! @% G( T1 K; t% j9 A: e6 X, a
  51. ' r# x' m5 T8 x4 S% D( e' f7 L+ ?

  52. 1 J& w% I6 Y" M
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */3 T( [. v: b* T. B
  54.         }$ o  X" c" O% p5 i6 s6 S- n
  55. 5 @+ Q' T( L3 @6 l5 Z- M4 M
  56.     /* 打印卡速度信息 */
    2 s6 w  g) H1 b. p: z
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)) P3 q, s% U4 g9 D% O# X1 K
  58.     {
    8 ]0 R! r. u, t
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");2 A: m% t! ?) y% I- E  f
  60.     }) H" o6 g; a6 a7 M7 M/ b5 r
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)$ g5 u  Q' K5 l' G
  62.     {
    8 M+ E6 ^1 M( }+ N- d$ b$ |
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");+ L& E* u2 N2 Z3 I* O1 N' N3 O
  64.     }6 `; C6 w0 A# U* W& W+ ?: z& s/ m
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)1 z$ x' u  H" Z% r8 t- j& e5 [
  66.     {9 ~  o$ h/ l$ h
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    7 m9 G, o$ u) X# P) V( g' o, c/ P
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");5 q3 {' j' y+ u2 y& R: K
  69.     }; H" r. [1 n( n! J  a

  70. 1 v% ^% z9 \# T, i. e9 ]0 v

  71. 2 Y2 U( f" d6 l2 [4 P! o0 p
  72.         /* 卸载文件系统 */
      r* `9 [) z, O' e/ u) _' L. T
  73.          f_mount(NULL, DiskPath, 0);
    . z" R6 Z0 B7 [4 O: L4 D3 A3 Y3 v
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。/ e( Q6 j: q: b
      e.png
7 l/ i  T( M: o5 j) f& |     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。
7 u0 i, ]% C5 u/ u2 C$ _$ T; J 添加的内容为 -fexec-charset=GBK,还是修改编码的意思。
6 d0 ^0 b' z4 A& e% \9 _. F" l! \      f.png 7 p1 F$ e# W4 j+ b
     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了/ n) ]6 H) A. \. M# c
       g.png
* s, N+ \# {) o5 K! k6 Y; G      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可7 ?: t& J3 S# s: C+ P
       h.png $ a: \; F4 l6 M0 `6 E6 N
      料想这次应该没毛病了。结果,新的意外又出现了。
& G) H& m3 o, P% P( P  z       i.png
, J0 k- C1 s8 @' ?6 R       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。+ n+ ]7 Y9 E9 C( i1 T
      j.png k.png * ~- x$ }& h% f9 x' _+ F8 n
    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。! }+ p" q2 Y/ D3 c/ i1 [

" ^9 E& \7 z7 G2 |      9 s* N1 M1 ]2 j7 E

# u. ]+ F# Y1 |3 ?5 @+ {$ i3 y
" @; z& b/ c# v2 _4 F5 }0 m7 L# r6 s% }' t/ G
5 \; t7 v# Q$ D9 r" O- ^& `6 {
赞 收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似技术帖

官网相关资源

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