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

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

[复制链接]
STMCU小助手 发布时间:2021-12-16 21:00
简介3 E" X  @) B2 i/ M) R6 \- q& i% K
最近项目中可能需要使用到SD卡,所以需要对SD卡的配置和使用调研,在配置过程中遇到了一些问题,在此记录一下。
/ Z  }& z# g5 U  {5 I1 J0 L* \: d- P$ s' j
STM32Cube配置; D/ m3 c' ]. r" W
Pinout
: o. V* d$ E" E% B$ H
5 c5 O- G7 o. V3 N& T
20180521180114826.png
' i- B1 Y- m7 b0 L% l+ u* B: N) @

. V) s5 w% M2 R+ V, f
20180521180129690.png

* H# c2 T& ], c1 C$ j6 h
+ f& f" m; A# c2 G9 o" c( T只需要注意绿色部分的设定
' M* M% G% m/ Y( X
* d8 @7 C) Z7 M) U1 _0 oClock配置) A1 d( x& d$ {6 s
20180521180815759.png
: G. S% H/ L# u5 z) {/ n

/ p  Q) U) x! M7 n这里使用了最大的Clock,SDMMC1的时钟是48MHz, x+ A; K5 o6 U5 b% g
# N* q1 ^& K: ?9 y6 ^% k
FATFS配置/ U: L" U5 i: H' m  ]% A
  d, ?) E2 ~* c; k) s
20180521181353894.png
5 C3 P9 ?6 r( r- T+ Y
% K1 f+ ?1 R9 `& h
Freertos配置
5 l$ C3 t0 u7 O4 X
& r4 F( M, ?3 a' @) u3 D& ?/ T
20180521183255134.png

# l9 t$ O. X( k' G  z
2 K/ K4 c; F* U这里增大了Heap size,使用了heap_4的内存管理方式。2 `: W' W# E9 d. Q& }

) U9 B- p/ f" ^4 y7 k$ \- w: CSD卡配置
" D7 g5 o9 j, R$ B* i) M, \+ z1 z& G! E; R! a
20180521183527404.png

3 W* x, `- d% t- L9 O
( d9 S  e' d" A( U, h$ h
2018052118353658.png
1 R; r1 m+ Q0 }- S+ [+ a0 w

( g9 t. Y% o! T! B7 R在这里打开SD的全局中断,并使用DMA2的方式传输数据5 y0 h1 \5 {  H( e3 F8 P4 e- [/ b
0 F) k0 Q! i- x8 V8 R
NVIC配置
9 A6 h8 }4 e" i2 h2 h- ]# E6 Y/ ~$ H$ j, r) S; ?
20180521183735142.png
9 q; ]0 o4 F) A" `

2 m: A3 a( S; p$ H% _  c7 h3 oSD的全局中断配置为5,DMA中断配置为6,5的优先级更高。( R' C/ K5 L  |* z  s3 n( u1 d8 _

$ ?7 B$ U" q7 j5 i工程配置, S; |8 A" U1 Y1 |3 \. V
2 ]! v. X6 L. f- W( U; j. n5 C
20180521184020944.png

% P1 l4 x( k5 n8 Q+ e) \3 p: t; a+ ^! g# {+ d' g0 f
20180521184028381.png
. u) }. z. {9 O  z' T
; P0 k4 J& A( {" t
以上就是所有的配置内容了,配置完成后,直接使用Code generate功能就能自动生成keil工程。( ~4 x/ I# K3 ]% X

6 z) S6 B. ]/ c: ?6 l  M& [) E# z代码修改3 {( P8 J" e% q' I0 [
初始化SD卡' x, e/ q* U0 p- N! N" r
我生成的工程中需要手动添加BSP_SD_Init()函数,我是在MX_FATFS_Init()之前添加的。4 |1 v+ D' W+ L: J" C8 i8 Q6 a8 U
  1. /* StartDefaultTask function */0 X8 W! Y$ z- a6 g
  2. void StartDefaultTask(void const * argument)- P+ v, p' }+ w' C6 u( w
  3. {! V5 g& j0 h1 m; }1 R
  4.   BSP_SD_Init();
    3 o5 D  @" C5 K( S5 Q1 N
  5.   /* init code for FATFS */
    . G( G( W( _* S6 F  r6 L6 H# _
  6.   MX_FATFS_Init();
    " R9 R3 }. R8 R2 s* z& H( D* K

  7. % m4 e+ M4 F, E$ o
  8.   /* USER CODE BEGIN StartDefaultTask */8 r/ `- F. }0 \% a
  9.   /* Infinite loop */
    % A- x1 ]9 r  s# c/ R8 i
  10.   for(;;)* X* [, g, n5 x' a5 H2 [. v
  11.   {
    7 [  ]* i& T/ ]' P( T1 p
  12.     MX_FATFS_Run();
    . N# R! \0 m9 l8 S8 t1 l. \
  13.     vTaskDelay( 5000 );
    4 O1 i2 y; N. B) }9 O1 L
  14.   }( r. d- A- H5 N! i) X/ s2 S5 ?0 Z5 v
  15.   /* USER CODE END StartDefaultTask */3 u) L, W, o- x  A0 O& q. i
  16. }
复制代码
- p7 Q, [7 `  S: P4 |
添加DMA中断处理函数
2 `# |0 \9 s7 ?+ a& p/ |stm32f7xx_it.c文件中,需要添加下面两个中断处理函数:) R& _/ ^* A; Y, g
  1. void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
    ) F$ L8 p1 }. i* `7 _
  2. {
    ! p* M* F" R2 m
  3.   BSP_SD_WriteCpltCallback();
    / D+ r7 x, L8 I( |, O
  4. }
    ( G. v) `" }: L7 N) N! B; m

  5. 4 i' a3 O& _$ _9 F$ D
  6. void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)" n0 Y. O2 a( I; b  y9 Q& _
  7. {) [  o; u5 ~( G  H# s* Q. B  j2 F. |
  8.   BSP_SD_ReadCpltCallback();# ~9 y$ ~* J7 ^  g) \0 H
  9. }
复制代码

; t+ z) A. W4 S2 ]. X9 H% }1 @) O$ v创建Queue! z0 o0 C+ ^4 G/ ?3 U8 G" L, ^
在自动生成的Demo中,使用了SDQueueID这个Queue,但并没有自动创建它,所以需要手动创建一下。我是在SD_initialize()这个函数中创建的,具体创建的地方可能需要再仔细考虑清楚。- t) |7 K3 S0 L' x: D
  1. DSTATUS SD_initialize(BYTE lun)- n0 \  W: p7 \# K( }
  2. {
    1 g. A* i8 C# o' P; H% U& q8 P( r
  3.   osMessageQDef(myQueueSD, QUEUE_SIZE, uint8_t*);
    / {. r' c1 D! i8 T
  4.   SDQueueID = osMessageCreate(osMessageQ(myQueueSD), NULL);
    ( l6 s' w: u0 J/ A  j/ B
  5.   return SD_CheckStatus(lun);+ ~! @, i  D1 ?
  6. }
复制代码
9 }( r$ W1 }# A6 D
将Pin的配置改为上拉" n; _2 l" P- h, b0 x1 {9 r
在默认配置函数中HAL_SD_MspInit()对SDIO的Pin的默认配置是GPIO_NOPULL,但我在使用过程中发现,程序会卡死在SD_FindSCR()函数的以下这段代码中:, M; {+ j# [0 A  U- S
  1.   /*卡在这个循环中出不去*/
    - T0 _: N0 g7 d/ x
  2.   while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))
    9 T4 ~7 }. |, P" ~
  3.   {
    4 O* A, L7 ?7 a3 \9 I6 f7 D
  4.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXDAVL))
    0 l. X6 T# q5 D% m" w% ^( j
  5.     {
    0 M0 u$ W' ~0 |4 j. g
  6.       *(tempscr + index) = SDMMC_ReadFIFO(hsd->Instance);6 f7 x- ~4 A' E; y6 K+ v* y( V
  7.       index++;8 }$ I: }) @# K" z0 ?+ {1 X! ]
  8.     }! C& O0 w* H- p  ~9 [3 |
  9. : h; }0 P8 S6 R7 L  Y: n
  10.     if((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
    . h0 \4 v" J( l
  11.     {) a0 D  F9 r6 z8 `
  12.       return HAL_SD_ERROR_TIMEOUT;8 B6 ~. F2 t" S! p6 Y/ ^0 L
  13.     }
    8 ~. F1 f: |$ `3 n2 I( i) l
  14.   }
复制代码

: t) m' c7 S0 {4 i/ z后面我将GPIO改为GPIO_PULLUP后解决了这个问题,具体原因暂时还不清楚。
. g7 ?/ k  S2 ~
5 M' M- o: a0 {: U7 k
  1.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
    & n7 K8 B. k$ R" n" }1 Q
  2.                           |GPIO_PIN_12;: J3 v/ g0 E( h* \7 g
  3.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    5 L; E) v* m9 D# C; x: x, x
  4.     GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;& ?' r5 _$ d) ?' Q: ~# w
  5.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    5 z  q. f; I1 d9 x( t5 p5 P" `
  6.     GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    & s' O; W+ \6 Y9 e
  7.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);+ r9 m5 o5 |! v( y0 M8 _3 B; d, F

  8. : b! \# |% B; X
  9.     GPIO_InitStruct.Pin = GPIO_PIN_2;$ E  }8 g# W4 {$ p
  10.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      x) Y! S6 {; F- r8 S( j
  11.     GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;
    / R' @; h* E1 ?9 W
  12.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;3 x7 I% |5 m! [* [
  13.     GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    ( G3 L, |( F: N, T- M! E
  14.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
复制代码
+ e6 b1 t! v2 d; B' V/ o% `
简单Fatfs应用( m! A  \" g- U5 B9 C
  1. void StartDefaultTask(void const * argument)
    , w& y  S; L9 {* H+ o0 ~
  2. {: I1 c( k" U6 D& G) o
  3.     BSP_SD_Init();
    ! @8 d# y; E; O9 t1 ~/ k# D
  4.   /* init code for FATFS */
    1 |2 v$ F; z0 V" P( p7 t& p
  5.   MX_FATFS_Init();9 V8 {  }% x  W* n; O

  6. 4 M& N5 G0 W1 \+ \/ V
  7.   /* USER CODE BEGIN StartDefaultTask */
    7 v5 F* F7 t# b/ h
  8.   /* Infinite loop */8 N! E4 _1 t* f4 h

  9. : k1 M" |% w& A' O8 a" ~
  10.   for(;;)
    . n9 v" X1 F! u3 I
  11.   {: a% t( ]6 F9 i& p. d0 Y; |
  12.     /*自己实现一个Run方法,每隔5秒往SD卡中的文件写入数据*/
    & h4 ?/ v" C( |
  13.     MX_FATFS_Run();+ j4 A0 U& a; W6 \! S: x
  14.     vTaskDelay( 5000 );# \9 m- }1 p, ^" f, g' o) ~% p/ g
  15.   }
    1 A+ i8 O7 ~! B9 U
  16.   /* USER CODE END StartDefaultTask *// \% M- {/ t6 N
  17. }
    ' v+ y7 c% {; l
  18. - z) m) N; T( N& b" Q
  19. void MX_FATFS_Init(void) 0 C' m% l$ w/ _. R3 b* {2 W
  20. {! t' Y$ H( i/ _6 q4 ^( @% B
  21.   /*## FatFS: Link the SD driver ###########################*/
    7 j5 K7 d) ^7 g3 J" p$ o3 i
  22.   retSD = FATFS_LinkDriver(&SD_Driver, SDPath);0 D7 h4 h3 k" K5 S5 w

  23. 0 \8 O' v1 A& m$ f5 L
  24.   /* USER CODE BEGIN Init */- s# T3 t1 S3 e( l
  25.   /* 在Init的时候挂载文件系统 */     # q' z  }3 a& u4 u' c) u; g+ m
  26.   if(f_mount(&SDFatFS, SDPath,0) != FR_OK)  
    ( T) p- n% P5 c& y0 I$ O, j
  27.   {  / L7 O  A( R+ D
  28.     while(1);7 z6 X2 F3 g  O% f3 U- e
  29.   }   - P9 v* s! `- b4 `% W
  30.   /* USER CODE END Init */+ S+ |2 B9 l$ l' D/ n, u
  31. }
    . g1 D$ ]+ ~1 A3 m0 T) S

  32. ' X+ l  o1 k( d% Z4 q: g2 P
  33. void MX_FATFS_Run(void)/ Y& s  g# p! ?4 `& l5 X
  34. {
    " K! d1 a: _$ j$ f' u" J
  35.   UINT writeBytes;
    ( P" h  u( Q) d/ D, B% p
  36.   /*文件系统基本操作:打开文件,定位到文件结尾,写入内容,关闭文件*/
    $ o! ~" I! b. F
  37.   if(f_open(&SDFile, "SDTest.txt", FA_READ|FA_WRITE|FA_OPEN_ALWAYS) != FR_OK)
    0 g. }. M" ^- O
  38.   {6 K8 e3 X7 H5 B7 A; c$ a7 n
  39.     while(1);
    7 P' o/ |/ O" D
  40.   }
    3 {2 S" `$ y* a. Y; \& R7 Z
  41.   if(f_lseek(&SDFile, f_size(&SDFile)) != FR_OK)5 M5 |# W+ w( u# s
  42.   {
    & P4 E+ A7 m& D/ Y' O4 j! z0 X2 C
  43.     while(1);
    , Z4 D7 c- g2 z+ _5 o6 z
  44.   }$ C/ D) u8 b: e4 `
  45.   if(f_write(&SDFile, "sd Loop", sizeof("sd Loop"), &writeBytes) != FR_OK)$ U3 \, z3 b% I8 F9 d
  46.   {
    : k# c$ S( J5 s0 R: ^" j: f8 v% h
  47.     while(1);1 j. l4 g( v. W1 J: o6 r
  48.   }
    ( X0 u: L8 B0 v
  49.   if(f_close(&SDFile) != FR_OK)0 o% q4 D/ [$ v' N1 ?
  50.   {
    4 n6 @* G. t$ P; _
  51.     while(1);1 v6 y: L7 c8 r  @
  52.   } & y% n+ ~$ t3 f, O' @; L7 Z$ F0 O8 ^+ w
  53. }
复制代码
: P4 j1 `) D4 X' U0 c
SD写入结果:- V" E, T: _/ ~8 i1 o4 A( @6 B" ^- o0 x
( Z) p# v) Q9 c
20180521190454697.png
  C) X) C* o! ?. s, u
$ _1 X- ]* S. `* L* a

2 o9 p3 `. g! j' V+ j. e; b3 J
收藏 评论0 发布时间:2021-12-16 21:00

举报

0个回答

所属标签

相似技术帖

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