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

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

[复制链接]
STMCU小助手 发布时间:2021-12-16 21:00
简介9 E% I# b% T" U+ j
最近项目中可能需要使用到SD卡,所以需要对SD卡的配置和使用调研,在配置过程中遇到了一些问题,在此记录一下。
5 H! U0 z6 D, s) ?, J/ ~) S% J& }4 i. W: ?  |& E& ~
STM32Cube配置
7 g* G( G$ `/ f$ LPinout
$ N5 x4 u5 r/ S: N/ X# N# c
7 f5 ~& A' @9 M. o9 o4 T( t
20180521180114826.png
2 e2 x7 o+ V. \
& c( G, K' B7 }: |
20180521180129690.png
3 H# ~4 {+ u6 H& `  }: l
! c7 H0 r5 W3 }9 \# |# f
只需要注意绿色部分的设定
2 i) R* v/ D7 R) c: z! D1 |0 M1 o* i! }+ R; j5 ?5 \. R
Clock配置' a1 }. j8 E5 L0 n. {/ o
20180521180815759.png
- O( a4 J% {1 U+ ^. ]

2 p" ]: G' k9 E" c, N- W1 G这里使用了最大的Clock,SDMMC1的时钟是48MHz: r# E' b& i& s! Y; c- X

8 w! _: J; p7 `! ]$ C: yFATFS配置( K& h- |$ Q7 v' S" f  Y- ^! a
% S6 x; C9 A  t
20180521181353894.png
' v; N6 R) A3 j2 U
7 e9 \8 K0 o3 K
Freertos配置
- U% _5 R# A) k6 q8 t9 f
: I3 l: Z8 v# k3 _  X' n, Z
20180521183255134.png

7 }9 S3 F# U* s' G( g3 w/ k7 g* ]
6 S1 p' W  o2 k8 z* d  _7 }4 l% @0 k这里增大了Heap size,使用了heap_4的内存管理方式。
# q& E  m  H3 d* B
% h  `. T$ e9 ]% W8 {SD卡配置
9 w- c6 x$ t' o3 g$ T% a+ |) V3 c* R# \. t
20180521183527404.png

$ R3 ^& Z7 i3 b( ?. w5 F
) P) F- V' g8 v7 ?  {* Q
2018052118353658.png
0 V# Q$ t9 P+ ~9 K
* D* D, J# ^! \7 e9 Y
在这里打开SD的全局中断,并使用DMA2的方式传输数据4 y5 w, j% v' _* k3 O4 v5 ^0 o# M& I

+ u4 q4 R  p# e4 H+ aNVIC配置
0 @7 \/ w5 ^7 U9 }, Q9 W- _8 x* Q1 D
20180521183735142.png

9 o: I3 k! t' M. ]5 r. I0 C
) F' ^! b: _" o1 xSD的全局中断配置为5,DMA中断配置为6,5的优先级更高。3 @/ h8 g6 J2 e- T- B. r8 S( W+ C
. |+ p/ i: t7 z+ O% i
工程配置
- j1 C$ U* ~7 n% g5 g: f4 |) f1 U+ J
20180521184020944.png

: i5 W- Q  ?# @; a* a) |! S0 H: N/ V4 p, V7 `. t
20180521184028381.png

- I9 S7 X1 h( d/ D. n! d3 E
' Z9 r/ X! L% g0 @( N! I以上就是所有的配置内容了,配置完成后,直接使用Code generate功能就能自动生成keil工程。
7 D  _$ E" }9 q* _
' P9 F( E6 }6 s! z& W- X& n! N代码修改2 \( n2 b/ i2 |" ]/ [3 S- ]
初始化SD卡
% m1 B1 T* A6 E; C# ]. ^4 |) E我生成的工程中需要手动添加BSP_SD_Init()函数,我是在MX_FATFS_Init()之前添加的。
/ r0 i8 J6 Z6 p. ]1 K4 |
  1. /* StartDefaultTask function */. R; g9 c4 w: y% H5 l! g
  2. void StartDefaultTask(void const * argument)
      ^& h4 Z( a& k  V: `! k* g( d
  3. {
    - K! Q9 ~/ E1 k6 M
  4.   BSP_SD_Init();9 Y+ F4 C9 m; o# u/ F) e
  5.   /* init code for FATFS */8 K9 f( b$ S8 `! K
  6.   MX_FATFS_Init();
    0 a( B& x$ y) s+ t6 d0 k  c9 K

  7. ( }9 s- i4 i& g- p2 v+ i! I
  8.   /* USER CODE BEGIN StartDefaultTask */
    0 f; P; B. F1 p8 Y: [8 C
  9.   /* Infinite loop */
    ) C  N9 H; c% k) [  [
  10.   for(;;)
    4 \* u+ v3 Z  f6 x$ H
  11.   {3 t) f; O* a$ `, x+ \# w' C+ P
  12.     MX_FATFS_Run();
    # r2 K$ S2 [9 T3 X' M# X2 Y
  13.     vTaskDelay( 5000 );9 X+ u# i$ n  [% r& y) m6 l
  14.   }
    2 h+ b2 b6 u0 A4 S. i+ W
  15.   /* USER CODE END StartDefaultTask */# T# @# s+ `% l1 N) U3 E
  16. }
复制代码

2 [" Y+ w" K; q1 Q4 l5 Y/ S添加DMA中断处理函数
' G( [+ I7 {3 [- |7 |5 vstm32f7xx_it.c文件中,需要添加下面两个中断处理函数:
8 i! C8 S! \9 G$ m" n9 K; \. e
  1. void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
    " l. z3 e# W: L, i
  2. {, O# Y; ~- Z* v7 x) k( X  L
  3.   BSP_SD_WriteCpltCallback();
    / z6 m2 l  S" _, u5 G
  4. }
    9 s5 H6 k3 t& o% A+ g2 g' {/ ~; F) N
  5. 9 k) r; j/ A' e6 j* ?
  6. void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
    & T0 i" E3 Y8 d2 ]$ A2 X: ~, e
  7. {
    % W2 R. E$ c# @
  8.   BSP_SD_ReadCpltCallback();
    5 c/ q7 I* F( Y) X0 X
  9. }
复制代码

, q! e# `2 R( d$ ^+ v0 T( S创建Queue6 E% M9 D( _% ~
在自动生成的Demo中,使用了SDQueueID这个Queue,但并没有自动创建它,所以需要手动创建一下。我是在SD_initialize()这个函数中创建的,具体创建的地方可能需要再仔细考虑清楚。. q8 z* a) Y* V9 C
  1. DSTATUS SD_initialize(BYTE lun)% z  F6 n8 x; a' H; d: s/ h
  2. {  \" }! ^7 ]# W& U; q
  3.   osMessageQDef(myQueueSD, QUEUE_SIZE, uint8_t*);
    ! @% b' \) e- c" K
  4.   SDQueueID = osMessageCreate(osMessageQ(myQueueSD), NULL);" O, U6 ?& O- i0 a- L& `
  5.   return SD_CheckStatus(lun);* j1 b, U/ h+ G: F
  6. }
复制代码
. }" G! m9 h3 i' D  S4 m: V
将Pin的配置改为上拉. G5 R' |) Y' o2 c- n4 S3 j8 q% h, U
在默认配置函数中HAL_SD_MspInit()对SDIO的Pin的默认配置是GPIO_NOPULL,但我在使用过程中发现,程序会卡死在SD_FindSCR()函数的以下这段代码中:' x6 Z( s6 H+ r+ {- x0 j# V
  1.   /*卡在这个循环中出不去*/2 s: x2 Y" ^/ }$ T7 J3 O$ }
  2.   while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))* N/ @% z6 `0 \
  3.   {
    8 `8 o2 _$ m) m& f# J/ X2 f
  4.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXDAVL))" \; Y/ R5 c' J  j$ K& l- C
  5.     {
    : e) d. |: j0 F- d8 [% e" O, ~
  6.       *(tempscr + index) = SDMMC_ReadFIFO(hsd->Instance);
      G* l: g, K8 U% ?8 ~1 \( e# X
  7.       index++;7 o( v2 K8 w! t- v# |
  8.     }
    ! P0 J. A4 j3 T! o
  9. 2 |& R" w$ I3 R+ c1 C9 i; k
  10.     if((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
    $ _' K8 T2 k7 p% ?2 X- }
  11.     {
    6 h3 u3 i# l' O; D
  12.       return HAL_SD_ERROR_TIMEOUT;
    : d1 L7 q1 e% n" y4 X& L
  13.     }0 `& y& J  ~& O& x+ W) H
  14.   }
复制代码
# x3 p8 `' l2 g
后面我将GPIO改为GPIO_PULLUP后解决了这个问题,具体原因暂时还不清楚。) c7 F" k9 Q. q' O. O' W- [5 `

; R7 X- s6 [% q
  1.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
    4 V+ ]2 W! O% ]: t+ U6 `/ \
  2.                           |GPIO_PIN_12;: \: G% u9 u, W7 Y
  3.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    - Z$ T7 s# o6 n, p- J/ ^
  4.     GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;
    $ D0 q% x  B% f1 W8 I/ g+ m
  5.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    + _: `4 z7 f8 t! p3 A* V3 p: e
  6.     GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    6 b  B. w' J% ~0 V3 M" O4 j
  7.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);+ N/ L7 S) `$ i) B" |

  8. 3 _* N' G; k& p1 [' {* }$ g( l
  9.     GPIO_InitStruct.Pin = GPIO_PIN_2;
    " A7 U1 v6 D: u
  10.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    , l/ S2 ]3 Y% p
  11.     GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;
    - Y+ \  M5 r1 O' |$ C; C
  12.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;7 r/ F1 J9 l. y5 O0 R$ C
  13.     GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;1 U/ w9 h7 ~! o( p; L* N# Q  R
  14.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
复制代码
) M$ ?0 t+ L0 F
简单Fatfs应用- Y; `& J1 M# N" q
  1. void StartDefaultTask(void const * argument)
    ' Z6 d. I2 [9 q3 _0 v% A
  2. {
    ( }7 x8 w* L! n
  3.     BSP_SD_Init();
    : {% E' _' O7 S; a
  4.   /* init code for FATFS */
    ! _1 w% a& B9 y# k) ?& F0 e( P
  5.   MX_FATFS_Init();
    4 R' u7 A+ T; K
  6. ( W9 D& K  v( h0 B* Q
  7.   /* USER CODE BEGIN StartDefaultTask */8 i. ^# H  B1 v
  8.   /* Infinite loop */5 H% `# A, Y5 C. ?8 g  [

  9. , S4 v" f- m% I- _5 H: [- K5 |4 A
  10.   for(;;)
    9 z, H1 a( `) q$ x/ z- R/ Z( f
  11.   {* j- q4 n- r" n* X( Q
  12.     /*自己实现一个Run方法,每隔5秒往SD卡中的文件写入数据*/! Q2 u! p6 }6 v1 x. ~- v
  13.     MX_FATFS_Run();8 n9 X' Y" E8 Z6 r. Q; ~/ J7 v( W7 h
  14.     vTaskDelay( 5000 );
    * O$ T, N4 z* E& D  m/ H: V
  15.   }
    & z9 C# f3 I9 C3 }6 e
  16.   /* USER CODE END StartDefaultTask */
    ) [# e, s6 ], H6 H5 r1 h/ S* L1 n
  17. }& _  |! C& @1 H7 K  C: X

  18. + {* e; T1 G  S' b8 Q
  19. void MX_FATFS_Init(void)
    5 i' {: O, p/ b( y4 J6 P4 o
  20. {( f- [. C& Z( _! e$ o
  21.   /*## FatFS: Link the SD driver ###########################*/
    ( F2 Z& m/ d( u! J5 z
  22.   retSD = FATFS_LinkDriver(&SD_Driver, SDPath);( J% Y& W9 Y) w1 U: f
  23. . Y  `. R1 S6 ]1 I) b
  24.   /* USER CODE BEGIN Init */) T' v* J" s  g, q# y% A2 h
  25.   /* 在Init的时候挂载文件系统 */     , Y4 s5 _! z+ z$ S+ p( P4 [
  26.   if(f_mount(&SDFatFS, SDPath,0) != FR_OK)  
    0 d$ L$ }7 ^* D6 u( ]
  27.   {  
    - Y) p0 u+ e8 G/ m& y/ U
  28.     while(1);# p, v, r8 L$ A
  29.   }   
    2 r4 f' S9 P4 c2 o+ R" ~
  30.   /* USER CODE END Init */
    0 n8 P$ L. Q  Z' |  L# o2 d
  31. }) V2 x2 ^8 Y$ i9 x3 h0 Q
  32. - E8 Y. N+ Q" k& t* R8 c" N% ?
  33. void MX_FATFS_Run(void)# D8 K  y8 V( R  h
  34. {0 s5 X- U% `* P) p6 X% W
  35.   UINT writeBytes;
    7 \1 |5 \3 K: H6 O
  36.   /*文件系统基本操作:打开文件,定位到文件结尾,写入内容,关闭文件*/
    4 z) {6 s. G  V6 o' C
  37.   if(f_open(&SDFile, "SDTest.txt", FA_READ|FA_WRITE|FA_OPEN_ALWAYS) != FR_OK)
    - v% i7 H6 R: Z0 S# Z
  38.   {! j7 h. C. V) A9 y0 @
  39.     while(1);
    ; `/ B% f. y1 }9 k
  40.   }
    . x0 A' ]# @, H1 G+ T
  41.   if(f_lseek(&SDFile, f_size(&SDFile)) != FR_OK)# W7 X7 R5 P3 b& U7 L- V( H' d
  42.   {
      L8 a  V9 Q1 l" \! }
  43.     while(1);6 R* e% j" b& ]8 w, U# ^! x! s
  44.   }: `1 F2 R4 K9 ~2 ]: h
  45.   if(f_write(&SDFile, "sd Loop", sizeof("sd Loop"), &writeBytes) != FR_OK)$ @6 r! i8 n' k' u0 s7 e. x1 v
  46.   {
    , g6 F4 y& t6 \
  47.     while(1);
    0 p0 f3 A+ Z" u$ L8 Z  q
  48.   }& W5 U  d. A3 }7 w7 ]" o
  49.   if(f_close(&SDFile) != FR_OK)
    % I* w/ ^' `8 l% i" n
  50.   {% S# F0 ]) ?! T7 p- E$ C3 \
  51.     while(1);
    8 I+ u5 _9 A4 [/ `
  52.   } * E6 M4 v  ]7 ?: v1 F& `3 Z+ e; _8 z
  53. }
复制代码

0 Z! I' y" V. A* L5 F9 Z/ `SD写入结果:  t$ D+ \1 V3 }7 I3 T
1 ^  U" _; m) [' E1 A# T2 H
20180521190454697.png

9 O$ P: o4 `- g. R, Y1 N% |& ^) y0 q

% @! N2 ~+ Q$ O, F' j7 g
收藏 评论0 发布时间:2021-12-16 21:00

举报

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