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

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

[复制链接]
STMCU小助手 发布时间:2021-12-16 21:00
简介( t) Y" C; ?2 t9 _% {$ Y( [" h
最近项目中可能需要使用到SD卡,所以需要对SD卡的配置和使用调研,在配置过程中遇到了一些问题,在此记录一下。
8 l. \- F8 Z! V
) u8 x# a8 @9 S2 h; e5 X( o: tSTM32Cube配置
6 u. }( E# f; R, \: J/ x9 i7 qPinout3 P% M3 e2 z! O% U' q7 ~& e4 I. a

2 r1 ~/ i  e/ `9 C9 R  O
20180521180114826.png
+ T$ \* y# ]0 t* B

3 s' Y) k( T! j7 g: e$ E3 T
20180521180129690.png

( k  U4 }, k1 o1 J! r& U3 h; U
只需要注意绿色部分的设定
- ^9 J3 s2 R/ U& g3 I
/ r& ~% U( z2 V; e; C5 Q; YClock配置  G4 W0 l; O  t1 u. o: {/ ^  U% @
20180521180815759.png
7 K; B' G9 p  Z$ N) H. E! _' c

; V5 r" W9 v9 e, X& c; N& ]这里使用了最大的Clock,SDMMC1的时钟是48MHz6 a0 o( ?- s% e1 O4 T

: P1 {7 g" L6 V7 n" P! |FATFS配置
* \# t7 _$ B6 C  r; {
1 M- q& n( X$ \- p1 W# c# \
20180521181353894.png

! W  V' [$ o, E9 q1 c4 X1 ^9 e1 d
# i2 A* k9 I, T7 c/ [, v* IFreertos配置
, L+ c' j' D# U6 F) R
! k9 n6 Y& j( a
20180521183255134.png

9 ~0 R. h2 f* u$ i3 x4 A: w2 k. U5 `7 D* {, E% c8 z
这里增大了Heap size,使用了heap_4的内存管理方式。+ F1 Z& I7 J6 w( s1 ]2 [7 `  c* ~7 b

9 u& m9 Z; `2 ~; n- hSD卡配置
% |# x5 k% [" k; M, {, @* l' O
4 [4 e/ N8 O8 y2 b4 t
20180521183527404.png
. f% q! B( O* m' u* B

2 S; [! u2 }) D. B; D  L
2018052118353658.png

' _1 c& m) n, e! Q9 n; W% C" G& m5 j7 c' _  Z3 |8 G! c
在这里打开SD的全局中断,并使用DMA2的方式传输数据, }/ g' n  z4 \+ }: k, T8 K
. A, @. U2 n9 p; g) `- Y! [( T
NVIC配置
1 _. }, X. Q8 @& `+ k8 j
" D; d3 t' z; n$ v7 b* V
20180521183735142.png

8 x) m6 g* e1 K  M: _, M( k3 P8 K6 W* g9 _) }" \! Y4 s  Z1 C5 G7 i
SD的全局中断配置为5,DMA中断配置为6,5的优先级更高。
* ?/ p# D5 t$ X" z, ^" Z$ n
2 T! u1 B8 [2 i: F5 L5 }工程配置
- U1 w" ^4 ]& U$ |( O
* B0 X% Y* S2 F7 x6 D0 ^
20180521184020944.png

! p. \* f: J  }: }9 e" F/ k; S& }5 [8 Q$ z* J7 e- O4 E  k
20180521184028381.png
( O8 y3 o& Y& w

8 r$ C* Y2 e; {9 d以上就是所有的配置内容了,配置完成后,直接使用Code generate功能就能自动生成keil工程。
  V3 x# l' U2 ^- z4 j) M) t( Q; }7 K& y4 t
代码修改: |  O  ]& }8 W, Y
初始化SD卡. g: R1 K6 S) \
我生成的工程中需要手动添加BSP_SD_Init()函数,我是在MX_FATFS_Init()之前添加的。+ ^% Y- {: H* o- j/ p- M
  1. /* StartDefaultTask function */' f. H  q+ I* N" B2 H& }6 u
  2. void StartDefaultTask(void const * argument)* f" r, j! \% J, g3 f. r5 |
  3. {
    5 Q% |! Q; B9 ]0 c8 }
  4.   BSP_SD_Init();
    ' Z; _3 C( h2 N6 }' {' M5 L# z# j
  5.   /* init code for FATFS */
    0 p: C9 u2 G  J0 L
  6.   MX_FATFS_Init();8 P+ u# z( R$ w
  7. 1 C# ]8 M. B8 F( B4 r, e5 t4 U% w
  8.   /* USER CODE BEGIN StartDefaultTask */; G! A: `0 F5 e
  9.   /* Infinite loop */
    : s5 M" a) X5 s$ S' J
  10.   for(;;)1 h/ V+ ?. F# m
  11.   {
    8 |* L5 ]! X! q3 Q5 X2 u2 K* T3 n
  12.     MX_FATFS_Run();
    1 }" @% y+ U/ X$ [/ p/ I, F& O: }  o
  13.     vTaskDelay( 5000 );, M- L- U: P% H
  14.   }7 K) R- Z8 C  R* M7 ?9 [8 s& g
  15.   /* USER CODE END StartDefaultTask */
    / E2 k4 y/ b: e9 h0 k" `. S
  16. }
复制代码
6 @: [5 M2 {& h# ?. T& K
添加DMA中断处理函数) @: v3 ?6 {9 |  u* R8 h
stm32f7xx_it.c文件中,需要添加下面两个中断处理函数:
3 O4 I" A( y7 C5 w) x4 e+ D8 z) S
  1. void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
    $ ~1 U# c' S2 z  u
  2. {
    % q' S( K3 w+ h! B) J( D
  3.   BSP_SD_WriteCpltCallback();
    ( w# j6 {0 C( A6 M  h- u/ @
  4. }
    3 E) v9 e- q1 v. y2 H4 \5 F& i

  5. 7 }3 ?$ y3 ?9 N) m
  6. void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
    1 C  c' r9 L$ f+ X
  7. {9 T' Q, U0 G4 K. z2 a' c
  8.   BSP_SD_ReadCpltCallback();
    ) B- U6 g" o- {1 |' t  B( b1 h
  9. }
复制代码
6 l6 F8 E) t6 w; ?
创建Queue
- l. t& r$ ~% K$ @# m7 R在自动生成的Demo中,使用了SDQueueID这个Queue,但并没有自动创建它,所以需要手动创建一下。我是在SD_initialize()这个函数中创建的,具体创建的地方可能需要再仔细考虑清楚。8 {1 M$ H/ x. P8 q
  1. DSTATUS SD_initialize(BYTE lun)
    % s1 D# F" P0 k/ Y  T0 B
  2. {4 R2 R& ~0 X; M' c+ E" s# ?7 R
  3.   osMessageQDef(myQueueSD, QUEUE_SIZE, uint8_t*);) |% X  o7 f5 u
  4.   SDQueueID = osMessageCreate(osMessageQ(myQueueSD), NULL);# {3 |$ X8 l3 |' m" q
  5.   return SD_CheckStatus(lun);
    4 P& l! I) O; w! _
  6. }
复制代码
: X" z; P  u: M: i$ b
将Pin的配置改为上拉. ~5 x! F- l* L. F# h0 u& w
在默认配置函数中HAL_SD_MspInit()对SDIO的Pin的默认配置是GPIO_NOPULL,但我在使用过程中发现,程序会卡死在SD_FindSCR()函数的以下这段代码中:
- O0 z3 \0 u- T: Y/ I+ c- j* p8 S
  1.   /*卡在这个循环中出不去*/  `4 i) r2 S  u; d
  2.   while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))* V) ^6 `5 U$ J6 [- N
  3.   {' U: E+ \, @5 h3 G7 {8 h
  4.     if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXDAVL))
    ( A- h. I' f: I: X
  5.     {& r' W  p* t( m% k& x) x+ }$ ?
  6.       *(tempscr + index) = SDMMC_ReadFIFO(hsd->Instance);* q) t% X9 S7 e. M2 f6 [' p
  7.       index++;
    % s& w  W6 m  F- Q& B, c& e
  8.     }
    % e9 m, U+ _0 J7 m

  9. 0 w5 J: A: U+ C
  10.     if((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
    + V- [% m! r9 @+ E9 P0 h: h
  11.     {1 F/ Z% v7 g. i1 P8 h$ K" `. [
  12.       return HAL_SD_ERROR_TIMEOUT;
    - O6 z* _  X4 j/ ?! q7 |
  13.     }
    , ~) X( I% ~: U
  14.   }
复制代码

. E; r- c0 b. k$ S$ C( W后面我将GPIO改为GPIO_PULLUP后解决了这个问题,具体原因暂时还不清楚。' H4 @+ L* y: B  A/ m, P& p; C
/ g5 @1 t* G: J7 j( t; Z( I
  1.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 / j9 G7 E- ]. q+ E, y( r8 G0 T
  2.                           |GPIO_PIN_12;
    * I$ w" T# Z" I8 l
  3.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;* ~) X( b" z* T0 e% e8 i$ u, Y
  4.     GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;' L; c; j$ e# \! c. K, i$ l
  5.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    ' u: c& p3 {4 g8 V) n- G3 c8 L
  6.     GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    & ~7 h% C4 V# f0 s* u  C+ f
  7.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    % z, C0 p& [4 h8 R
  8. 2 s+ s! Y- \% b  k7 Q
  9.     GPIO_InitStruct.Pin = GPIO_PIN_2;
    / ?/ R( x, e+ w
  10.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;2 k" b; s+ N, K, o7 o# u# S  u
  11.     GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;! T5 j& p/ ^3 n1 \
  12.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;7 J4 D( ~$ ~. e, N8 q% s3 V
  13.     GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    + J9 ]; m, ]+ s' ^4 O
  14.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
复制代码

+ k, f2 Q% _7 j简单Fatfs应用
' j3 @+ g/ a7 Y+ J
  1. void StartDefaultTask(void const * argument)
    # S+ q+ A8 X/ d& F
  2. {
    ! o2 @1 X0 M( _. {; h
  3.     BSP_SD_Init();; n! @& L$ Z+ I& s( O0 j8 w
  4.   /* init code for FATFS */
    # [7 c& }: Y; I7 V( f0 l4 O& E) Z
  5.   MX_FATFS_Init();' c: y' F& ]8 ^
  6. 5 F7 S' p/ z8 J# q% Y( A. v
  7.   /* USER CODE BEGIN StartDefaultTask */. X$ L! f5 J4 Y4 c  y  `7 {  l
  8.   /* Infinite loop */
    % _# p& j/ f6 u1 |* N" N5 l
  9. ) t0 ?( T" v8 Q9 y% O/ P4 q
  10.   for(;;)
    ; b; a/ F& n4 s, h) B6 }% g& W
  11.   {6 v% @1 u) l1 f& Y7 {9 j4 P$ m# a
  12.     /*自己实现一个Run方法,每隔5秒往SD卡中的文件写入数据*/9 X: w, V: J& @# u+ q* E5 Q' }
  13.     MX_FATFS_Run();
    6 Z; z  I" c6 t' c! V* Z
  14.     vTaskDelay( 5000 );
    ( c3 g! A/ e9 @+ \9 l
  15.   }- j% Y. O  L0 l
  16.   /* USER CODE END StartDefaultTask */
    $ H* m8 x  y$ n; a2 ]* L) L
  17. }/ A  W: l6 f  `% V

  18. + j- m* I8 H$ S; o7 G+ n
  19. void MX_FATFS_Init(void) ) u% P3 F, K% ~
  20. {
    6 t& ^* O. G  u. e  v3 _$ ]; W+ c/ M6 g
  21.   /*## FatFS: Link the SD driver ###########################*/6 D* o% `2 d+ F& r/ A& Y
  22.   retSD = FATFS_LinkDriver(&SD_Driver, SDPath);
    5 ~7 @2 M: m: j' }. T. k3 U* r
  23. 3 K+ h& V$ V3 X
  24.   /* USER CODE BEGIN Init */$ z* T: ~- |3 ^% T! K
  25.   /* 在Init的时候挂载文件系统 */     
    + F: I/ v% v) |3 ?& c* E
  26.   if(f_mount(&SDFatFS, SDPath,0) != FR_OK)  ( L- p- v7 k# `/ E& u, Q
  27.   {  9 ~7 p8 a0 }4 b/ @
  28.     while(1);
    3 L* ?: U1 g6 J
  29.   }   
    # }" |( S) @9 d: h7 e
  30.   /* USER CODE END Init */
    & W; I/ W0 n3 d: m% B
  31. }
    / Z8 M- e% I$ W- _4 F$ P7 w9 v# d

  32. + z8 }" y" U3 X8 I8 \
  33. void MX_FATFS_Run(void)/ e9 b; I; E, m$ [8 d
  34. {) g$ d; v4 c( p3 l: Q9 \, O
  35.   UINT writeBytes;
    5 V! G: j$ D0 b% B
  36.   /*文件系统基本操作:打开文件,定位到文件结尾,写入内容,关闭文件*/
    0 l& i4 X( U& i. u( H5 M
  37.   if(f_open(&SDFile, "SDTest.txt", FA_READ|FA_WRITE|FA_OPEN_ALWAYS) != FR_OK)
    * L- k7 v  y3 w- u. t
  38.   {
    ; ?- Y1 Z& c* P) d* I" A$ d$ A
  39.     while(1);
    ' O* B4 D# N1 ~$ v* R  O
  40.   }, N: D, @3 Y/ A- p
  41.   if(f_lseek(&SDFile, f_size(&SDFile)) != FR_OK)% f, r- z2 {, i. V9 g; j
  42.   {
    9 Z0 ?) N! \0 |% x
  43.     while(1);3 s% j* E# m& Y/ B6 J5 z
  44.   }
    % k; L/ u9 v) o5 U$ ^- q
  45.   if(f_write(&SDFile, "sd Loop", sizeof("sd Loop"), &writeBytes) != FR_OK)3 ~9 r2 D% M# G8 y( _( N% P" ]
  46.   {
    2 K( d4 \: W+ Q1 \/ F, E8 M; ]
  47.     while(1);/ V0 E' }/ s" I. J1 z
  48.   }
    0 }2 f& S  K7 R# G
  49.   if(f_close(&SDFile) != FR_OK)
    9 D& V& z$ ?7 o- }( u- X1 P
  50.   {. b1 A3 Y- O* S- N- x$ p6 E
  51.     while(1);' r0 r& F7 K* \3 e" U
  52.   } 3 Z, c) g' p. {' V8 u( N7 k
  53. }
复制代码
0 j0 x; V1 H4 h$ A
SD写入结果:3 B8 {' \" _# X2 G& A

+ ^; g! g& c- l- n8 ^
20180521190454697.png
) c7 l" k0 p- d) o- j
" S, ^3 S& \* Q( ]8 @( u# ]. o
3 x; {3 _( ~, e9 g$ [
收藏 评论0 发布时间:2021-12-16 21:00

举报

0个回答

所属标签

相似技术帖

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