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

【经验分享】使用STM32Cube在STM32F7开发板上实现SD+Freertos+Fatfs

[复制链接]
STMCU小助手 发布时间:2021-12-16 21:00
简介- v3 f8 R1 H2 R* _
最近项目中可能需要使用到SD卡,所以需要对SD卡的配置和使用调研,在配置过程中遇到了一些问题,在此记录一下。
0 Y2 b* V0 y5 S
: H* j, d/ P- D8 h; qSTM32Cube配置0 J( t+ f7 {; W+ k" k" z( U- g, `
Pinout# a. J+ B( m) A. F" v: @6 x  [; S

  o: ?, N" T! a* M3 ^- M+ Z4 v
20180521180114826.png

: |4 g; F1 R/ y
  z) v, b8 t2 d
20180521180129690.png

# W: w# h4 l; |
* b+ q6 Q% \( x* N/ v) ^3 g: e只需要注意绿色部分的设定
3 T4 s+ e: n" @
$ X5 @- o1 D% g8 B- cClock配置
1 ?% Y& n/ ~! G( u& V* @
20180521180815759.png

% M4 U! N. t. x  r9 K4 C* t6 ~# N9 Q+ e2 V
这里使用了最大的Clock,SDMMC1的时钟是48MHz0 }( F& A. y) m; n1 _

; d$ |6 E6 ^, d4 c0 g( bFATFS配置
  Z8 r  k1 Q  _+ D9 I5 A7 Y# T; e. ^
20180521181353894.png

) C1 m9 t3 U( ~6 E( F. B4 y/ K. D# t, M
Freertos配置( _$ \3 I/ y7 x7 ?) T4 q4 M3 |7 S) R; f
7 i/ o9 p1 n7 E0 J  W* i
20180521183255134.png
( O, ^. F  S% p2 v  c5 {, R

2 Z8 P# w( v& `; m1 q' c! t* p这里增大了Heap size,使用了heap_4的内存管理方式。: G9 y* `  R1 t  T$ \' L3 T

0 d' `1 f. P. l! u- eSD卡配置
# h' }5 X9 r! f8 G5 ~6 H+ i9 V& h! t7 ?! v/ Y6 |7 `) L
20180521183527404.png
& P: \$ H3 Y7 \+ C

& C8 O  m4 m% H2 r8 t* v; ^  z+ s) K
2018052118353658.png
) |9 `4 ?" U  c% @; R; c8 e
& Q  B4 C9 u) j
在这里打开SD的全局中断,并使用DMA2的方式传输数据5 M7 u5 j5 m% ^; D% @8 {# O, u( P

/ z. @6 ]% ?/ {" _1 q5 \( p/ A7 }NVIC配置' v1 u5 h# ]: h( x( X+ s

$ e3 r  b/ G; q" D* G7 L# Y* u
20180521183735142.png

% n, l; v+ Q# w  I! h
. s1 p( e( N/ XSD的全局中断配置为5,DMA中断配置为6,5的优先级更高。, S; [- Z) Q9 E$ V) I$ A

" C4 r' C* t6 v: }* D工程配置; [9 r) I& H: x: h
; z8 Y' G+ x4 e' M* `; \
20180521184020944.png
7 j( W+ C; M# S0 Y1 d+ M. L

* P% q% B, Q; T2 l; S
20180521184028381.png

  Y8 {% c5 _+ K$ C) T' [8 ^' D! P& \1 Q3 u- t- j) _
以上就是所有的配置内容了,配置完成后,直接使用Code generate功能就能自动生成keil工程。
2 a& j, F0 h/ |  h! ]* t4 a- x$ E" p" }; g) D
代码修改
/ w% U8 ^9 M8 T$ H初始化SD卡
# b4 h! I9 T1 N3 W我生成的工程中需要手动添加BSP_SD_Init()函数,我是在MX_FATFS_Init()之前添加的。! A- W3 N' J. _4 Q5 U3 @6 t
  1. /* StartDefaultTask function */! Q' p1 m# u1 D
  2. void StartDefaultTask(void const * argument)
    ; d( k9 ]9 I& i' ]9 B' }
  3. {% n+ s& K3 }4 ~8 R" {  H
  4.   BSP_SD_Init();/ r5 {: m2 s6 U9 x% ?. \
  5.   /* init code for FATFS */% p8 G9 g( h, E* y
  6.   MX_FATFS_Init();
    - G5 `3 ?' E9 U6 Y3 Q6 Z% g
  7. + Q, f* C' y4 W4 [% M
  8.   /* USER CODE BEGIN StartDefaultTask */
    : @) K6 N+ u5 `1 ?8 q7 A
  9.   /* Infinite loop */: d4 f6 X& M2 i$ g. g
  10.   for(;;)
    ( d, O/ J# t$ k9 N+ W! L8 G2 f. q; [
  11.   {
    : }: W) i( d7 e  p7 N! Y% F
  12.     MX_FATFS_Run();
    ; p2 B9 m0 w& U9 r8 p
  13.     vTaskDelay( 5000 );
    ' \- Y  @! C- f1 p5 L
  14.   }
      O  v8 I$ i6 a  R
  15.   /* USER CODE END StartDefaultTask */% L2 D) P" {2 f9 y
  16. }
复制代码

9 v* }6 q1 U4 O% M* l添加DMA中断处理函数
. Y" [  b2 a- f+ Xstm32f7xx_it.c文件中,需要添加下面两个中断处理函数:
* a+ }' o2 L: U9 I' l: U& B
  1. void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
    * l3 m. I. W: }$ o. Z" _
  2. {
    . d! ^( b$ l0 h" ]+ D( u
  3.   BSP_SD_WriteCpltCallback();
    . |( N1 E+ V3 Q: l) y
  4. }
    + D" G, y) x2 ?8 o

  5. & N  a4 |( r4 Y" G
  6. void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)+ S, b4 G. L3 X9 F8 M4 O. J/ p- V
  7. {
    7 R+ X! N: w5 w1 Y
  8.   BSP_SD_ReadCpltCallback();
    + ^/ x' J+ |. w6 [! L# a8 F. L
  9. }
复制代码
0 `* t. \5 m$ I
创建Queue8 o, f, h1 q1 R
在自动生成的Demo中,使用了SDQueueID这个Queue,但并没有自动创建它,所以需要手动创建一下。我是在SD_initialize()这个函数中创建的,具体创建的地方可能需要再仔细考虑清楚。
8 x5 l& h9 V1 K
  1. DSTATUS SD_initialize(BYTE lun)
    ) g5 _! b' J5 y
  2. {  s/ j6 Y$ Y! g& z
  3.   osMessageQDef(myQueueSD, QUEUE_SIZE, uint8_t*);
    , v/ l% N& ~: o, L- J/ [5 s
  4.   SDQueueID = osMessageCreate(osMessageQ(myQueueSD), NULL);
      O4 V( k* [6 t  F3 b8 f; _
  5.   return SD_CheckStatus(lun);
    " N4 z% {4 u2 k3 @& M6 i: G8 s8 Z! v
  6. }
复制代码
$ A# d* R% p5 ^6 F3 m
将Pin的配置改为上拉5 h. f2 V8 W# x' x
在默认配置函数中HAL_SD_MspInit()对SDIO的Pin的默认配置是GPIO_NOPULL,但我在使用过程中发现,程序会卡死在SD_FindSCR()函数的以下这段代码中:0 g6 V+ j! |6 N% T: }3 ~$ N
  1.   /*卡在这个循环中出不去*/) G& K# i+ I/ V# c6 d
  2.   while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))
      z" ~0 E% \8 U
  3.   {
      O" P4 t% d2 G. J" O  @. |2 k
  4.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXDAVL))
      U6 T$ |" t7 u. b+ Y) h
  5.     {* a8 k$ F2 p- u$ S
  6.       *(tempscr + index) = SDMMC_ReadFIFO(hsd->Instance);% f! {3 g3 D; h% V* Z# ^! _: i
  7.       index++;
    ' Q" q% E- d, \/ g: Q, f
  8.     }! v( `# V+ l3 G7 I1 K

  9. " D: g$ n. O' c, P. c8 ^7 y+ u
  10.     if((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
      @7 S5 O' w7 m) O
  11.     {( {" r2 u2 D% D' O
  12.       return HAL_SD_ERROR_TIMEOUT;
    . o2 j+ D+ T, r/ Y) L
  13.     }
    + Z. G9 M; M! r. g
  14.   }
复制代码

: S0 B4 K/ h$ Z( J( \0 i" P% v后面我将GPIO改为GPIO_PULLUP后解决了这个问题,具体原因暂时还不清楚。
* t' Q2 a+ g/ O( ?; X, K0 o
  z, g" N4 b2 u4 h: X9 H" m- I
  1.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
    8 `& m0 S9 l. t3 \  G2 r. k& f
  2.                           |GPIO_PIN_12;3 x0 C0 Z, A) g% ?9 V3 Z1 S# I5 j5 A
  3.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    # M9 Y3 _. t# J; k
  4.     GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;
    2 R; V, Q- t; a( W5 ?+ V. d+ C
  5.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;" d, k8 n! I6 J# s0 K1 D( E/ L/ s
  6.     GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;- B+ t7 u3 u+ p! i
  7.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    1 b0 x3 J0 O/ m9 V. T/ ^: X4 W

  8. 9 c) @" ?( L- z5 V& ^7 ~& G
  9.     GPIO_InitStruct.Pin = GPIO_PIN_2;
    4 I' [& x5 o8 |
  10.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    7 P$ k/ B2 O0 s4 T0 ^: H: D
  11.     GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;: r! I' Z0 A: g/ H$ L+ c
  12.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    4 P9 R9 s- d9 S1 j* o
  13.     GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;+ _/ V4 }, Q- [5 `5 X) M
  14.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
复制代码
4 a# J' j/ \1 q# Z' y$ t% o/ T& C
简单Fatfs应用- v9 D1 w  H" `. x8 |
  1. void StartDefaultTask(void const * argument)
    7 h5 z$ W) r/ }% j# |) o0 N) X
  2. {1 h: P, @% ~; @" \+ B' ?$ ^
  3.     BSP_SD_Init();
    ( y' a; u0 I4 ]1 |. ^
  4.   /* init code for FATFS */
    $ c& ^/ [$ f' \# _" R8 b! j1 I
  5.   MX_FATFS_Init();4 Y$ C+ s( T( s
  6. & G+ W  x9 k  ~3 i( U
  7.   /* USER CODE BEGIN StartDefaultTask */3 d* \7 @, Z) ~) N, {4 w1 W2 e
  8.   /* Infinite loop */2 h9 ]6 ]( R- Z: O  V

  9. 5 L9 a& E/ o4 d4 q9 r; ?+ C
  10.   for(;;)( P9 u* q( O2 O/ F( T+ m
  11.   {
    4 u8 v( g! B0 g$ ~  r2 _/ K
  12.     /*自己实现一个Run方法,每隔5秒往SD卡中的文件写入数据*/
    ' i9 x1 u/ Y( K
  13.     MX_FATFS_Run();
    0 E6 _' m& F6 e; X% K; _6 W
  14.     vTaskDelay( 5000 );; E6 T: R9 h# A, A  F2 z- O+ c
  15.   }7 k9 {0 c! h9 h' @/ X
  16.   /* USER CODE END StartDefaultTask */
    * H) _9 ^3 h% }. e9 N5 G1 x
  17. }
      V2 c: A6 U2 P) ]! h0 E

  18. . D2 l1 ~8 C' |& l' e9 u
  19. void MX_FATFS_Init(void)
    ( z: G7 W% r( p6 A" t
  20. {
    " E4 y- K0 g. i2 [3 g0 {) n
  21.   /*## FatFS: Link the SD driver ###########################*/
    ; W/ O# ~% ?3 M  g
  22.   retSD = FATFS_LinkDriver(&SD_Driver, SDPath);3 k8 J7 s2 z" w' z- u/ ^

  23. 2 i' e! |) c" B
  24.   /* USER CODE BEGIN Init */
    ; j& _9 q  L" u& R  [, k, U
  25.   /* 在Init的时候挂载文件系统 */     
    ) G$ i. X7 c; `4 O5 k2 ^! j
  26.   if(f_mount(&SDFatFS, SDPath,0) != FR_OK)  9 H7 K: v8 u8 P) u6 u1 P1 b' M% k
  27.   {  
    2 {. B$ ~2 K- J$ d
  28.     while(1);
    ! j4 g' V) S8 ^4 [/ V
  29.   }   + G5 z! u4 H; n6 r' d/ z. [
  30.   /* USER CODE END Init */
    # n. [; h9 v" \. _
  31. }
    8 P2 D/ `1 {& U( {: H! E$ J
  32. $ Q4 |# [- L3 G  h
  33. void MX_FATFS_Run(void)
    5 H" p+ Y6 @/ ^1 J) j+ x
  34. {
    * b% J8 G, y# g! _* N9 S9 y7 f
  35.   UINT writeBytes;
    4 B; ~. V( S% y4 L
  36.   /*文件系统基本操作:打开文件,定位到文件结尾,写入内容,关闭文件*/$ S8 T( C6 g# i' W& N5 N
  37.   if(f_open(&SDFile, "SDTest.txt", FA_READ|FA_WRITE|FA_OPEN_ALWAYS) != FR_OK)# g' E; l. e  s, i
  38.   {
    ; x5 ~8 O: p. f3 w' V& a  [
  39.     while(1);, s7 N7 }" I& X) E- ]" F) F
  40.   }
    3 i9 }/ l) ?$ i+ {9 f
  41.   if(f_lseek(&SDFile, f_size(&SDFile)) != FR_OK)
    % H1 |6 G8 }$ F* U% `0 r) v) }
  42.   {( D3 r9 [( o2 T
  43.     while(1);' |" J# D  l( O4 Q% ^% L
  44.   }9 ~2 h; R! B, S3 S! b, l+ y
  45.   if(f_write(&SDFile, "sd Loop", sizeof("sd Loop"), &writeBytes) != FR_OK)
    8 ^% o  {; E% Z) l
  46.   {) T4 k$ `( L* V3 P0 d* M! P/ B% A
  47.     while(1);
    7 l* G7 B, t6 a* G, m2 [
  48.   }9 E4 X/ d- S7 d" }! G3 Y
  49.   if(f_close(&SDFile) != FR_OK)7 D( N" @( T9 t& n/ _. z
  50.   {: {. M& K: s" I8 Y
  51.     while(1);$ f. d6 Z- n$ e& C4 V% M
  52.   }
    ' z' o; r4 z; g2 z* T5 k  N) Y
  53. }
复制代码
! S7 r; P, J* e* y+ h
SD写入结果:8 Q$ L1 Z+ w$ c8 f  x
% \! o  J/ y) J5 R
20180521190454697.png

0 y; S# p+ K. S# L$ b) h; o6 _3 e; c( J7 L+ |+ ?
5 e$ G& t! A4 X$ v! v' U, Q
收藏 评论0 发布时间:2021-12-16 21:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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