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

【经验分享】STM32 HAL库配置SDMMC(转载,软件版本STM32Cube_FW_F7_V1.14.0, en.stm32cubemx (5.0.0))

[复制链接]
STMCU小助手 发布时间:2021-12-15 11:00
1. 准备工作硬件准备
  • 开发板
    8 c( f, B  V% o+ \; ~首先需要准备一个开发板,这里我准备的是STM32L4的开发板(BearPi):/ y* n0 d8 u1 n3 k  o0 q! {' \

    ( ?" b+ d& _, j9 C% K

  • Micro SD卡0 b8 e" `9 h4 `# ?# [& ^  K
    小熊派开发板板载 Micro SD 卡槽,最大支持 32 GB,需要提前自行准备一张 Micro SD卡,如图:' V& Y; I6 w- h3 `2 k! b
    ) h* J2 d' ~1 E3 g3 o


2 V4 ]5 L; r1 p7 ?9 b软件准备
  • 需要安装好Keil - MDK及芯片对应的包,以便编译和下载生成的代码;
  • 准备一个串口调试助手,这里我使用的是Serial Port Utility;
    4 u8 p+ i" }& B6 F& w

    0 o8 `. O/ [9 |  K: \- J

. p( I5 r: P5 P8 V% P4 I% i
2.生成MDK工程3 n! U* ^$ m6 H) |
选择芯片型号

打开STM32CubeMX,打开MCU选择器:. s0 V+ T. d, f. S0 A

搜索并选中芯片STM32L431RCT6:
6 A. e3 H8 r7 u1 Z5 M4 m8 I

% H$ O2 f5 a, T5 B
配置时钟源
  • 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC;
  • 如果使用默认内部时钟(HSI),这一步可以略过;! L+ L4 ]6 x( {! f. J7 m; |% F
    0 ?# N8 P- p- d8 p

这里我都使用外部时钟:

8 I6 c6 z2 S/ Y0 S9 v6 K$ d# N
配置串口

小熊派开发板板载ST-Link并且虚拟了一个串口,原理图如下:

这里我将开关拨到AT-MCU模式,使PC的串口与USART1之间连接。

接下来开始配置USART1:


  d* K7 j( Q( m5 A, r4 ~配置 SDMMC 接口

知识小卡片 —— SDMMC接口

SDMMC接口的全称叫SD/SDIO MMC card host interface,SD/SDIO MMC 卡 主机接口,通俗的来说,就是这个接口支持SD卡,支持SDIO设备,支持MMC卡。

知识小卡片结束啦~

首先查看小熊派开发板的原理图:

然后根据原理图配置 SDMMC 接口:

' d9 O- r4 T  N+ x5 n
配置时钟树

STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz即可:


4 E$ R/ i1 y8 y6 o* O2 u6 X2 [生成工程设置

4 d: o; `' T/ s& z, w# t6 G! T
码生成设置
, R; Y" {6 K- i% z3 p0 n# D4 ~

最后设置生成独立的初始化文件:

& X7 W+ B4 g; y/ b1 |

生成代码

点击GENERATE CODE即可生成MDK-V5工程:


. ~  b0 {4 ~2 z; n2 T! o

3. 在MDK中编写、编译、下载用户代码
+ \: g) ], {4 s, q8 _& ?重定向printf( )函数3 X+ h/ V3 o2 \; d: z6 ?
读取SD卡信息并打印

SD 卡系统(包括主机和 SD 卡)定义了两种操作模式:

  • 卡识别模式
  • 数据传输模式! ~# r3 A9 p6 @9 |9 w0 b

    , d  Q1 Z8 K6 [8 [6 \/ u

在系统复位后,主机处于卡识别模式,寻找总线上可用的 SD卡设备;同时,SD 卡也处于卡
. a7 J* U8 Y* O8 S% E识别模式,直到被主机识别到。

使用STM32CubeMX初始化的工程中会自动生成 SDMMC 初始化函数,向 SD 卡发送命令,当 SD 卡接收到命令后, SD 卡就会进入数据传输模式,而主机在总线上所有卡被识别后也进入数据传输模式。

所以在操作之前,需要先检查 SD 卡是否处于数据传输模式并且处于数据传输状态:

在main函数中首先定义一个变量用于存储 SD 卡状态:

  1. <font color="#000000">int sdcard_status = 0;
      G0 Q2 u0 \/ u: _
  2. HAL_SD_CardCIDTypeDef sdcard_cid;</font>
复制代码

然后在while(1)之前编写如下读取信息代码:

  1. <font color="#000000">/* USER CODE BEGIN 2 */+ {* E4 v4 ]+ d! I# B) n7 `) a
  2. printf("Micro SD Card Test...\r\n");8 L8 `0 K( ^+ V  c5 r& _; z* F6 O
  3. </font>
复制代码


7 i2 K, j: v' Z) j! q: ^

/* 检测SD卡是否正常(处于数据传输模式的传输状态) */; _  s) A/ |3 r8 f
sdcard_status = HAL_SD_GetCardState(&hsd1);
2 f5 o. I8 M, C6 W% |9 N. Xif(sdcard_status == HAL_SD_CARD_TRANSFER)/ s" g5 E( d" x' W8 W/ {* b
{. N( w$ y9 Z# Q' Z
printf(“SD card init ok!\r\n\r\n”);

  1. <font color="#000000"><span class="token comment">//打印SD卡基本信息</span>0 M1 k5 K% H! E. L6 l' m% b
  2. <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"SD card information!\r\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span># D4 m% W2 S9 a; H7 C7 |0 G
  3. <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"CardCapacity: %llu\r\n"</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">unsigned</span> <span class="token keyword">long</span> <span class="token keyword">long</span><span class="token punctuation">)</span>hsd1<span class="token punctuation">.</span>SdCard<span class="token punctuation">.</span>BlockSize<span class="token operator">*</span>hsd1<span class="token punctuation">.</span>SdCard<span class="token punctuation">.</span>BlockNbr<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    6 p; x! M' g+ q3 q) w% P
  4. <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"CardBlockSize: %d \r\n"</span><span class="token punctuation">,</span>hsd1<span class="token punctuation">.</span>SdCard<span class="token punctuation">.</span>BlockSize<span class="token punctuation">)</span><span class="token punctuation">;</span>
    6 s- _; M8 ]" P' N7 D
  5. <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"RCA: %d \r\n"</span><span class="token punctuation">,</span>hsd1<span class="token punctuation">.</span>SdCard<span class="token punctuation">.</span>RelCardAdd<span class="token punctuation">)</span><span class="token punctuation">;</span>
    7 K5 X( k" J7 f  F
  6. <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"CardType: %d \r\n"</span><span class="token punctuation">,</span>hsd1<span class="token punctuation">.</span>SdCard<span class="token punctuation">.</span>CardType<span class="token punctuation">)</span><span class="token punctuation">;</span>
    3 z7 V- [" D! T' P" V
  7.   g6 A; I3 O: M; A0 F7 n" d
  8. <span class="token comment">//读取并打印SD卡的CID信息</span>& l. h6 H( I% w; Z9 {: g2 |
  9. <span class="token function">HAL_SD_GetCardCID</span><span class="token punctuation">(</span><span class="token operator">&</span>hsd1<span class="token punctuation">,</span><span class="token operator">&</span>sdcard_cid<span class="token punctuation">)</span><span class="token punctuation">;</span>2 b2 l. }- v" i: J+ @5 E9 D: p% G
  10. <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"ManufacturerID: %d \r\n"</span><span class="token punctuation">,</span>sdcard_cid<span class="token punctuation">.</span>ManufacturerID<span class="token punctuation">)</span><span class="token punctuation">;</span></font>
复制代码


9 f4 x- ~1 m' q1 `

}
: V( {- A4 T9 Q; _: P. x; n6 delse2 C) r1 L1 {7 e* Y0 y+ h
{3 W0 G* Q. l% H  \
printf(“SD card init fail!\r\n” );
/ W$ A/ r, [! Z4 l/ U# V( S$ kreturn 0;+ ]6 m3 x% l" R' M4 v
}
* @( E) B- r6 y- a1 C0 n" q/* USER CODE END 2 */

. u% l/ P% t0 I& m& A7 F& h: E

编译下载后串口助手输出结果如下:

7 G  z6 r  V9 e  g9 m/ i$ q3 x& M

擦除SD卡块数据

为了验证实验的正确性或,先擦除数据:

  1. /* 擦除SD卡块 */
    % k% u1 W) c  x4 |! b  z
  2. printf("------------------- Block Erase -------------------------------\r\n");
    7 C. Z  k; }/ R8 F/ s
  3. sdcard_status = HAL_SD_Erase(&hsd1, 0, 512);
    1 Z) @5 v2 _6 s5 g: d
  4. if (sdcard_status == 0)) F- U0 L2 l; F  o0 ~1 f
  5. {( `5 `0 O& p7 `4 G# H" r0 n
  6.     printf("Erase block ok\r\n");
    # |  H6 [+ k0 V* {" h
  7. }3 V7 V- U. q/ h
  8. else
    0 C9 z. I" b3 k# b0 X+ @( w
  9. {* |. H+ d& m: f$ |1 S
  10.     printf("Erase block fail\r\n");  Q% P6 `% Z+ e5 E
  11. }
    0 i  c3 g. F% O% `
复制代码
' `7 N$ d7 |- w' p! x
读取SD卡块数据
  1. /* Private user code ---------------------------------------------------------*/6 {/ ?. h0 _6 a# S; U- `' T, Z( j6 Q
  2. /* USER CODE BEGIN 0 */
    2 t' y  b5 y- v5 ?" ]# H1 C7 r
  3. uint8_t read_buf[512];' B" ~1 a0 M9 {5 _5 ^: e0 E
  4. /* USER CODE END 0 */- x1 I* z4 f8 s+ I# N" n" S# r
复制代码

1 L, `1 V+ }3 Y

然后在之前读取信息的代码之后添加读取数据的代码:

  1. /* 读取未操作之前的数据 */* I& b; C) O9 h1 t! L
  2. printf("------------------- Read SD card block data Test ------------------\r\n");2 I, ~# ~2 v: [; p  B  O% i5 z
  3. sdcard_status = HAL_SD_ReadBlocks(&hsd1,(uint8_t *)read_buf,0,1,0xffff);
    7 X/ P2 ^. e( }; |
  4. if(sdcard_status == 0)- M0 |- X+ ^. V7 V
  5. { 9 Z0 [$ X- r! V7 x
  6.     printf("Read block data ok \r\n" );+ k2 c( B3 U* t3 B; ]7 {% D) k  V
  7.     for(i = 0; i < 512; i++)  \2 [" x9 C, x5 ^: m/ P
  8.     {
    / c8 P! Z( E( `' N4 r
  9.         printf("0x%02x ", read_buf[i]);
    9 j- D* ~# q, n# k* U, e. m# p
  10.         if((i+1)%16 == 0)
    9 K/ b1 ^& C5 M" v- I  G
  11.         {4 B/ c1 l- n, v/ g( h
  12.             printf("\r\n");1 s' Q4 M& G) F1 N3 t' G4 q
  13.         }: D/ U7 C; a3 F
  14.     }6 d% z( w3 I" E: i/ N
  15. }
    ; D" K9 J% j3 c/ Q
  16. else
    4 A4 s8 k& `- o, t; M, M
  17. {0 s7 j( l0 x* p0 i+ N, Z
  18.     printf("Read block data fail!\r\n " );6 N; G9 N9 z6 z& ^1 d( p* @
  19. }
    & B; p" B( _# Y, A4 e( S
复制代码
2 ?$ v! J  a2 \" E, R8 |4 n
向SD卡块写入数据

同样的,开辟一个全局缓冲区,用于存放即将要写入SD卡的数据:

  1. uint8_t write_buf[512];6 t5 M: e/ b+ c: E, }: m6 z
复制代码
0 A; \5 R! Q4 ~# E1 y1 [

然后在之前读取数据的代码之后添加的代码,将缓冲区的数据赋初值:

  1. /* 填充缓冲区数据 */
    % c$ C  c8 ?! l
  2. for(i = 0; i < 512; i++)
    4 K: U! ?8 Z( I. t2 N
  3. {# n' F" d2 f* b2 c" W4 ~
  4.     write_buf[i] = i % 256;. Z4 [9 x& X4 U4 p( X  ?6 e6 S
  5. }9 l" p( j9 Z0 @6 H- a( f* M$ h. H
复制代码
" J' v% b( D8 S  L

然后继续添加代码,将该缓冲区数据写入SD卡:

  1. /* 向SD卡块写入数据 */
    ) B) X5 [( H$ m  V  N" Y: q
  2. printf("------------------- Write SD card block data Test ------------------\r\n");
    1 C  i9 ^5 R9 P4 n6 }' }: |
  3. sdcard_status = HAL_SD_WriteBlocks(&hsd1,(uint8_t *)write_buf,0,1,0xffff);
    & q4 D6 a7 U! M' G. L( E
  4. if(sdcard_status == 0)$ \  Z, N4 a  \- E
  5. {
    ( {# P; u. H$ j" N
  6.     printf("Write block data ok \r\n" );4 O3 g# Y: j6 C0 C5 T* ~( b: B
  7. }
    & a' I# z. ]  u- b" m3 R
  8. else/ _  ?6 f: m1 y7 t/ c: i
  9. {! H* I6 d' }0 }& r5 Z& y4 _
  10.     printf("Write block data fail!\r\n " );
    : z6 Z0 w- J- h0 M' g
  11. }
    + n0 _1 G' @4 Q. S
复制代码

/ B  G* V7 E; K: X6 o

添加完之后,为了检查数据是否正常写入,再将数据读出:

  1. /* 读取操作之后的数据 */
    5 W! ]* M. y+ B" ?. ^: c
  2. printf("------------------- Read SD card block data after Write ------------------\r\n");3 C/ K- l8 _* x$ M8 h" |/ o: k
  3. sdcard_status = HAL_SD_ReadBlocks(&hsd1,(uint8_t *)read_buf,0,1,0xffff);2 p) j/ I  ~7 M, ]% D* a& C
  4. if(sdcard_status == 0)
    + p5 Y, u4 F. f& u: h
  5. { 1 P; W5 c. @9 s
  6.     printf("Read block data ok \r\n" );, _/ `8 H! x, b: v0 c4 t$ j3 w0 d
  7.     for(i = 0; i < 512; i++)
    $ O5 c! z0 H) E# J  r' N
  8.     {+ e" a& N2 u. W& U
  9.         printf("0x%02x ", read_buf[i]);, a: G" u. \' f
  10.         if((i+1)%16 == 0)
    * l3 h' [1 T" S. J0 o
  11.         {
    0 [0 E; n5 m% M; T! v
  12.             printf("\r\n");
    - A# b, N: n4 D  d9 l4 [
  13.         }6 t9 p9 K/ D' Z
  14.     }! O. o; H1 _5 C# |7 T' h
  15. }
    . x8 J7 c" z6 R) F/ N
复制代码
9 V3 D. E8 \" V$ q# h0 _

将程序编译下载,最终的实验结果如下:


* O, D5 v3 F9 G5 Q& Q5 c

, W& B4 K( c8 h5 e5 E3 O$ H

& q7 f+ }9 u4 j1 ~7 s8 Q


' Z/ l$ b- S4 g+ c8 C- S! m5 y4 D( w% r
收藏 评论0 发布时间:2021-12-15 11:00

举报

0个回答

所属标签

相似技术帖

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