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

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

[复制链接]
BinWin 发布时间:2024-8-19 23:43
    STM32H7S78-DK板载WM8904耳放,有SD卡槽有屏幕,合计着做个播放器。首先读一下SD卡。3 U7 w3 Q& C, b3 R; S- \

! [; f! ]9 M$ g+ D    鉴于该芯片从零配置较为复杂,第一步使用FatFs_uSD_RTOS例程进行修改做验证。导入工程后没有ioc文件,因此不能使用cubemx来编辑工程,遂手动添加。
; E& i& e9 O1 O5 H, b    增加串口打印,便于之后打印调试信息。从原理图找出调试器连接的串口号
: {& n: Q% F# _/ C5 p      b.png
8 A' Z; I4 O1 u+ i" `; }     手动添加,需要配置串口参数,GPIO参数,重定向函数。分别如下# q: M2 P' _& u6 F% ~
      
  E! r% X4 e$ M2 V
  1. static void MX_UART4_Init(void)! R# x. B& I& h' }
  2. {! J( ?! z& R& o. q) z

  3. . q" x% o5 L* W$ ~7 s' i5 O
  4.   /* USER CODE BEGIN UART4_Init 0 */# k' u( S4 O, H3 O& K

  5. 0 }1 @# y, h" p: R
  6.   /* USER CODE END UART4_Init 0 */7 A5 L  @% O" Z! V* }- u, `

  7. ( `5 e0 W4 j) u8 P2 D9 o! \! a4 H
  8.   /* USER CODE BEGIN UART4_Init 1 */
    # o6 y/ S7 T% _/ \

  9. & Q: t4 T4 t/ u! A; q/ y, ~. E- j
  10.   /* USER CODE END UART4_Init 1 */  W; j8 c8 K( W+ e# q' F9 B
  11.   huart4.Instance = UART4;
    $ B1 K$ v- ~# x" Y" R2 U
  12.   huart4.Init.BaudRate = 115200;
    / k' Z% J6 K4 O3 f. E( D9 c
  13.   huart4.Init.WordLength = UART_WORDLENGTH_8B;. a7 e. Q5 C7 A
  14.   huart4.Init.StopBits = UART_STOPBITS_1;; B' R! |# O2 {' V5 L3 s
  15.   huart4.Init.Parity = UART_PARITY_NONE;
    4 ^- r, [0 L# O& p  |+ x
  16.   huart4.Init.Mode = UART_MODE_TX_RX;
    6 B( v$ r" i$ ?* c3 O. A7 s2 y" r
  17.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    5 s, P; t/ t& ^* D: [
  18.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    & D* z6 d4 \0 h" ?/ |0 `4 A
  19.   huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;( |) ?* C$ ]/ l. c
  20.   huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;. z0 Y  s* v7 x* F
  21.   huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    : N2 a1 a* K: C' s& m2 N; F
  22.   if (HAL_UART_Init(&huart4) != HAL_OK)
    " O' x! f  `: T
  23.   {% L7 r' Z/ G0 V
  24.     Error_Handler();2 z; W' h: {' o% U! H& V  X
  25.   }
    3 ^5 Z4 I9 k- D
  26.   if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)( Q$ V" {% m8 k- j' O5 |
  27.   {* ^  A* X8 X! t
  28.     Error_Handler();
    9 I, G2 [, {/ X
  29.   }9 S6 p  ^* B* p9 f; @. u7 H0 p
  30.   if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK), o& @+ y" R- O: a% ?9 B4 X* Y% F
  31.   {
    / G0 }# N+ r" }: g" A) }/ }& |& b
  32.     Error_Handler();! u  W$ ]' S1 y- w( `/ X
  33.   }
    9 X4 Q9 G  ^6 L# ^
  34.   if (HAL_UARTEx_EnableFifoMode(&huart4) != HAL_OK)
    * B  K% m2 ]! q! |9 i! F
  35.   {( y' y( k4 T- F. M" J& X
  36.     Error_Handler();
    ( D2 z) o4 n5 L, \) h& O
  37.   }
    3 v9 ~% M. q7 R7 s, E6 c% ?6 ^4 B
  38.   /* USER CODE BEGIN UART4_Init 2 */6 {3 v4 \  G7 T) s" C4 ^

  39. 9 o2 P* w) W* A; e
  40.   /* USER CODE END UART4_Init 2 */9 J! ~3 _6 D4 x4 p

  41. " [2 `" }1 n8 c: Y) \! z
  42. }
复制代码
  1. void HAL_UART_MspInit(UART_HandleTypeDef* huart)3 u8 z0 g" l1 x  b5 @) \( Y) G+ M9 W
  2. {$ r  V& a0 b0 n/ P- W# x
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    8 F7 ]+ d% ^5 t. a  C
  4.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};7 `# e! k' ^, H
  5.   if(huart->Instance==UART4)
    ( `  G8 i' v# q) |# p$ i
  6.   {8 N% D3 u$ D8 o) B
  7.   /* USER CODE BEGIN UART4_MspInit 0 */! o3 J. a! m4 o! a4 c
  8. / N3 r# G: Y- y
  9.   /* USER CODE END UART4_MspInit 0 */% j( o" ~: B3 g! }0 _/ P! X
  10. " _) D6 r9 k* `/ |% q, p; M
  11.   /** Initializes the peripherals clock
    / J7 Z8 L+ k  ^  D
  12.   */
    8 N5 I: H9 ]8 H, i
  13.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578;; T4 u* S- O/ C) j: d( u
  14.     PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PCLK1;& A4 L  U- O1 Z. t$ T$ Y* N
  15.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    ) r! c7 A" j9 T4 A* K
  16.     {
    " k* T7 f+ _7 t- j
  17.       Error_Handler();
    % d  A- C8 B" R; y* f: M
  18.     }. l" z/ o' D% G4 U: _& _$ R1 P5 V
  19. ; `8 o' D" I+ Y5 `
  20.     /* Peripheral clock enable */
    1 ]+ x8 x! G& U
  21.     __HAL_RCC_UART4_CLK_ENABLE();0 P  q7 T1 d# ^
  22. " q' U. ]" {8 f
  23.     __HAL_RCC_GPIOD_CLK_ENABLE();
    , P: {) D: c* v+ }7 k3 H2 `* f! i
  24.     /**UART4 GPIO Configuration
    2 \: U6 }* d+ z7 v
  25.     PD1     ------> UART4_TX
    8 N( ]& o5 M! C
  26.     PD0     ------> UART4_RX' a: D3 [5 d% n6 p- }
  27.     */4 y8 C% g: s2 T% B8 Z+ u/ p
  28.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;8 l1 k7 S4 R+ c* H: `. D/ k+ D
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    + P2 W6 y4 P9 B1 Q
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;+ x, Z% {* `+ z0 U
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;2 H7 ]/ Q- Y  d- U2 j9 d; i3 r% _7 v9 N
  32.     GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    ' F% M! r$ b, ~) l2 s7 Z' i+ k" g$ l
  33.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);$ L( g3 h4 ^; F! z1 E3 V
  34. 0 |' ?# g: k  U! F- r
  35.   /* USER CODE BEGIN UART4_MspInit 1 */% F* s# L( }: p) U( G
  36. * L, P$ K3 V2 W
  37.   /* USER CODE END UART4_MspInit 1 */
      A8 e6 l" }' y+ U

  38. & ]$ E3 Y' S" i
  39.   }" i3 Y) b$ b- k3 k. O# |
  40.   b. T" [) }4 }9 F1 r, N
  41. }+ J+ x. A% x) q. k# p9 B$ e
复制代码
  1. 使用cubeIDE  i" z5 V8 \: \" e7 v+ R
  2. __io_putchar(int ch)) h$ C; t4 s  b5 c  R
  3. {% }) `* ?+ x9 a7 F$ ^, Z
  4.   HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xffff);' ~2 p( Z' s2 b1 e  z' B
  5.   return ch;# E8 z, F' z! ?
  6. }
复制代码
      代码修改完还是不能打印出信息的。需要IDE也作下配置,如下  D2 R' K1 N& Z) H% J
       c.png $ }3 b9 [1 T' E9 r. A
       添加输入输出头文件stdio后,就可以试试程序如何了。' E2 I% {' q! Q' t
       d.png 8 h# ]& w7 c4 l1 ?4 H+ q* S
       以上没有问题,接下来看文件系统。例程已经添加了FatFS,插入SD卡运行程序会在根目录创建STM32.TXT文件,并且写入一串字符。嗯,我已经测试,这是没有问题的。那要改成我需要的显示文件列表。SD卡我已经拷贝了一些歌曲文件,f_opendir(),f_mount(),f_readdir()等接口函数直接操作就行了。记得安富莱电子专门有做测试程序,拷贝过来适应下,对其开源表示感谢。) T8 x) R) k) V5 x( x
      + L4 V- q7 i, ?9 [9 s. Z  |
  1. static void ViewRootDir(void)" f" f. V; U! X8 N5 T% U
  2. {* u& Y$ ~4 T& h; V
  3.         FRESULT result;# `( A, k5 E0 N; q
  4.         uint32_t cnt = 0;
    ) H2 A+ W8 d6 p/ h& {1 \# B
  5.         FILINFO fno;9 }3 f$ t+ a5 |! K$ B8 ^

  6. 4 r* v0 O, O: @% x
  7. , {7 K, R% Y9 P0 {2 d" K
  8.         /* 挂载文件系统 */! ?1 C+ o2 L# q
  9.         result = f_mount(&fs, DiskPath, 0);        /* Mount a logical drive */
    1 i/ U, Z* |" X" O
  10.         if (result != FR_OK)" ~: `9 |7 l, A7 T* q0 q
  11.         {. M) U  m& ^# M9 I+ @3 E4 q6 c( K
  12.                 printf("挂载文件系统失败 (%s)\r\n", FR_Table[result]);% B- X3 L! i1 k) }% s3 }" U; Z
  13.         }% [- B# C2 m' t7 d* z
  14.   V" A! o3 Z: g3 o
  15.         /* 打开根文件夹 */
    / e2 c3 G' Q' a( i" j# n$ |9 `
  16.         result = f_opendir(&DirInf, DiskPath); /* 如果不带参数,则从当前目录开始 */! e5 o) w5 S& m' ]* G( }
  17.         if (result != FR_OK)
    2 K" z+ k% l% p% H( i, b* A; c! A, A
  18.         {
    + t! ?( v7 s' B9 V/ ~$ F
  19.                 printf("打开根目录失败  (%s)\r\n", FR_Table[result]);8 A1 D8 I3 D3 p+ J! y) Z; H
  20.                 return;$ p' b* ?9 ~3 O( K  [
  21.         }
    " J- Q/ L$ c$ c% Z" {7 d3 E* C

  22. . F" s" t5 x, N% i
  23.         printf("属性        |  文件大小 | 短文件名 | 长文件名\r\n");* R( ^7 S+ q9 y
  24.         for (cnt = 0; ;cnt++)
    3 W4 x! d: P: z  W& S
  25.         {6 l& H; W5 A: ^0 f% B- e" k
  26.                 result = f_readdir(&DirInf, &FileInf);                 /* 读取目录项,索引会自动下移 */1 d1 J* g4 d! V9 }
  27.                 if (result != FR_OK || FileInf.fname[0] == 0)
    7 E/ E" h# S" |5 H4 _% r
  28.                 {$ q: d* r' x# u4 y: D0 I4 L
  29.                         break;
    ) Y6 k! C; d4 X- d4 j; x- e
  30.                 }
    ; R6 {! a4 F% N% y; \

  31. 5 z7 T4 u. Y! U2 t' J
  32.                 if (FileInf.fname[0] == '.')1 k7 G- g- g; X* }0 N! ?7 C
  33.                 {6 z/ a; k1 M$ P
  34.                         continue;+ c- o( i* f6 }
  35.                 }  p  ^4 q2 o8 `( s( z4 p0 F

  36. * L% {" \: s! z% q7 V3 ~
  37.                 /* 判断是文件还是子目录 */
    4 h  ?1 _7 O, b# C" F5 X
  38.                 if (FileInf.fattrib & AM_DIR)
    , {0 o. E% h$ Q* G
  39.                 {
    % _0 v$ ?6 z0 n4 l9 R( T
  40.                         printf("(0x%02d)目录  ", FileInf.fattrib);2 M) a# ?- W/ j, `, @% `
  41.                 }6 I  R- Q: x$ s- @' U% \/ S, }
  42.                 else
    - U9 F& X  ?  \- W, x
  43.                 {7 x' e# O: `: u" _
  44.                         printf("(0x%02d)文件  ", FileInf.fattrib);
    6 f9 J6 {& @5 x) j# d
  45.                 }
    6 X7 c8 f" P- R  P' S( u" ?

  46. - ]! |" y/ H9 f* h5 A9 |1 R
  47.                 f_stat(FileInf.fname, &fno);$ W9 R/ b/ C" `! ^* b
  48. , y9 J' m+ f2 G0 F0 O3 _
  49.                 /* 打印文件大小, 最大4G */
    ; [  e3 z$ o% C! x/ v; v0 Q6 p0 U1 p4 C
  50.                 printf(" %10d", (int)fno.fsize);  C  F; s0 ]. S: {# M- Z

  51. , U# ]2 B: f+ m2 q2 i
  52. 5 \, S. |  F+ A: H
  53.                 printf("  %s\r\n", (char *)FileInf.fname);        /* 长文件名 */! \; a7 |/ k8 `/ W7 Y4 ]" ]- X; B
  54.         }
    8 B, }$ Z8 p. q

  55. - b2 h5 \5 O  N5 p9 @3 e! M# F* M
  56.     /* 打印卡速度信息 */' X8 D3 u: d3 y! I+ i
  57.     if(hsd1.SdCard.CardSpeed == CARD_NORMAL_SPEED)/ |9 _$ f# D$ y# u9 S
  58.     {
    , k; t! w5 S) n0 W5 h
  59.         printf("Normal Speed Card <12.5MB/S, MAX Clock < 25MHz, Spec Version 1.01\r\n");: v6 @( q' P* t) X, q: g
  60.     }
    # {$ e4 R9 c: i3 M- B
  61.     else if (hsd1.SdCard.CardSpeed == CARD_HIGH_SPEED)( i* d1 x3 u2 {) }$ i- z0 b* G
  62.     {( j* c0 X2 a! v& E$ \. P
  63.         printf("High Speed Card <25MB/s, MAX Clock < 50MHz, Spec Version 2.00\r\n");
    5 L. m' b1 S. o. M5 H8 v
  64.     }
    " V! }6 ]' J" ^2 ]$ ~8 G
  65.     else if (hsd1.SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)7 {5 o4 R( x% V+ c
  66.     {
    4 k5 m. z! Q3 N/ Y8 G. a, [( @
  67.         printf("UHS-I SD Card <50MB/S for SDR50, DDR50 Cards, MAX Clock < 50MHz OR 100MHz\r\n");
    ( R# u- H% X  G$ q  z% C
  68.         printf("UHS-I SD Card <104MB/S for SDR104, MAX Clock < 108MHz, Spec version 3.01\r\n");
    & E. L1 f1 }8 q0 n. e0 P' p
  69.     }
    . Q$ S1 U  U2 i3 P9 P8 L9 a
  70. . n: E# k7 C5 O# T. ~, p! G

  71. 4 d) Y6 U2 y, X. ~: d) q4 o
  72.         /* 卸载文件系统 */
    & d+ S. z* T; r/ i- I
  73.          f_mount(NULL, DiskPath, 0);( _! x# v8 c: t) H! o, o" r% T6 H- r1 q, ]+ B
  74. }
复制代码
     函数末尾还判断了SD卡的速度等级。我这个卡和厂家配送的一摸一样,看看如何。不出意外的话还是出意外了。5 g9 `# q. M' y  E  q+ U+ o
      e.png
( q4 a1 ^" a- m" U0 M7 Z% s     中文乱码了。这个应该能够通过修改文件编码格式来解决,不过网上看了下,可以添加编译参数代替修改编辑器。验证了下确实可以。$ D9 f; f/ v% [, d* U* p
添加的内容为 -fexec-charset=GBK,还是修改编码的意思。
4 h1 |6 |4 p- f3 U      f.png 2 {+ G, {4 {: w& s" c* ]
     接下来直接使用有歌曲列表的SD卡来测试,看看意外如何了
9 t* V: c  ^, k9 b       g.png
7 [4 {( V$ E1 `* O) c      很明显,还是意外了,不过问题我也看出来了。应该是长文件命名没有支持吧。然后紧急打开文件名支持,宏定义修改即可* }, {; ^2 J$ R; g7 p# x
       h.png
) K( B* q, \* H) m      料想这次应该没毛病了。结果,新的意外又出现了。2 T8 n4 j" {8 u- ^! B
       i.png
( V3 b2 |; f0 [+ w( q# j1 \& {       还好是我能hold住的问题,这文件看着也像是很接近了,看看ffconfig文件有啥没改好的。结果查看,发现code page指向了日文,难怪文字显示的内容参杂中文,这次总算没有意外了。
( ~& n& X( x  S8 R      j.png k.png 2 L' i0 \! }8 D
    满是意外的过程也说明尽管使用了例程还是有很多细节容易忽略,接下来计划添加解码器的驱动到工程里来。
! H" n( Q" G, w5 C2 h6 u& ?' G/ E+ J  a2 h. L
      8 e( h6 `  U- l
; ]! E9 `5 ~$ `0 O) Y8 Y' w5 u* G1 A

( S6 o+ r& W; g' U/ U* A8 Q2 B3 v$ {# i9 _3 ^' N+ M

6 k" W/ q3 q3 x; z6 ~. E6 \" X5 K  m
收藏 评论0 发布时间:2024-8-19 23:43

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版