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

【经验分享】STM32 SDIO详解

[复制链接]
STMCU小助手 发布时间:2022-4-17 21:15
1、SDIO简介. X, F. O: a" |2 ~9 A6 |
SDIO,全称:Secure Digital Input and Output,即安全数字输入输出接口。它是在SD卡接口的基础上发展而来,它可以兼容之前的SD卡,并可以连接SDIO接口设备,比如:蓝牙、WIFI、照相机等。
; C* }0 Q2 S, I+ G9 q* w, z/ t" o& L: V- @3 ]+ e
SDIO和SD卡规范间的一个重要区别是增加了低速标准。低速卡的目标应用是以最小的硬件开支支持低速I/O能力。低速卡支持类似调制解调器、条码扫描仪和GPS接收器等应用。
1 k  t, i8 c- r% q- V; u" o2 `6 G" w7 E$ T9 b9 t0 v
STM32的SDIO控制器支持多媒体卡(MMC卡)、SD存储卡、SDI/O卡和CE-ATA设备。1 q* t( H; z( V+ c' w
! U6 i3 Q& U! N+ F7 a8 e
SDIO框图# M: w  [( d( P& o& Q+ }* Q2 ?

7 x* X6 ?1 s$ {6 [ fce26341379d9bf350b4ff04ee7e2d8c.png
& y$ b9 C, |; M. \, I5 e% S
" Q& t7 C" K! N( @0 E复位后SDIO_D0用于数据传输。初始化后主机可以改变数据总线的宽度(通过ACMD6命令设置)$ a* l$ \, C5 [& q8 `" O6 _

3 [5 J" z3 C! a* O0 Y: t如果一个多媒体卡接到了总线上,则SDIO_D0、SDIO_D[3:0]或SDIO_D[7:0]可以用于数据传输。      
% }0 L) k# B, X( d7 U. V' D1 n; e# x- I
MMC版本V3.31和之前版本的协议只支持1位数据线,所以只能用SDIO_D0(为了通用性考虑,在程序里面我们只要检测到是MMC卡就设置为1位总线数据)
+ B1 `8 R; R) _$ t: T$ N
7 L9 T9 b. T% d9 ^- e' s02、SDIO特点0 i( x# @/ L7 D9 P+ N/ p$ A
①与多媒体卡系统规格书版本4.2全兼容。支持三种不同的数据总线模式:1位(默认)、4位和8位。  }% V! s! b# [7 P5 G
; [8 B2 m0 p) W) b
②与较早的多媒体卡系统规格版本全兼容(向前兼容)。) n# M  g& K& n/ w: Q+ u

+ b4 A1 _7 B: |* Q' f- }4 N, v③与SD存储卡规格版本2.0全兼容。
1 _; I( D$ b$ G4 H  J# Q3 u8 }2 z5 N, x- H3 i# j+ _1 [! h, ]
④与SDI/O卡规格版本2.0全兼容:支持两种不同的数据总线模式:1位(默认)和4位。
: @$ i, l3 }' @& P# e, F# E
) D5 J8 O* g+ y1 N3 y& c/ j/ [⑤完全支持CE-ATA功能(与CE-ATA数字协议版本1.1全兼容)。8位总线模式下数据传输速率可达48MHz。  c  E: d" v  {* G; P+ w

: E6 i7 o0 B2 b/ a$ h⑥数据和命令输出使能信号,用于控制外部双向驱动器。4 B/ l9 f& S6 X7 k# b) _) [

8 v8 X- n8 I6 E0 r" _7 ?03、SDIO时钟
; c  ~( ]0 {  V) M% `  C  p1.卡时钟(SDIO_CK):每个时钟周期在命令和数据线上传输1位命令或数据。对于SD或SD I/O卡,时钟频率可以在0MHz至25MHz间变化。
- l5 [0 z1 R. a8 K+ U2 d1 [: P, l, }5 W+ x
2.SDIO适配器时钟(SDIOCLK):该时钟用于驱动SDIO适配器,可用于产生SDIO_CK时钟。SDIOCLK来自PLL48CK(48Mhz)。$ I7 ], o# z4 [! G% M

+ J$ X, @3 @* w" ~# k/ wAPB2总线接口时钟(PCLK2):该时钟用于驱动SDIO的APB2总线接口,其频率为PCLK2=84Mhz。
6 {; p" s( P% ?4 u9 F
" T' E. [+ c; h" ]6 F0 h& M" Z# JSDIO_CK计算公式:SDIO_CK=SDIOCLK/(2+CLKDIV)
. a7 ?( Y% Y$ ?" S; [* W* p
8 E1 s: S4 N2 w, n/ q5 A( Z7 o注意:在SD卡初始化时,SDIO_CK不可以超过400Khz,初始化完成后,可以设置为最大频率(但不可以超过SD卡最大操作频率)% p2 `+ k% X. t- o2 x
7 S2 u# g! ?9 h, {4 S8 i( |/ F  }
04、SDIO的命令与响应; n. [9 c* D- a! w, [/ w) H/ t
命令
, t" ]+ F0 ^! x6 A5 r- B2 F) B1 v

  P  T" J& K- c- Z2 j, \1.SDIO的命令分为:应用相关命令(ACMD)和通用命令(CMD)两部分。发送ACMD时,需先发送CMD55。) k9 o* S4 R' r

! L/ N! a. A) z/ k1 k2.SDIO所有的命令和响应都是在SDIO_CMD引脚上面传输的,命令长度固定为48位,SDIO命令格式如下表所示:  X' o6 P/ ]/ [2 c! N, E

8 y! Z, M- p6 t; a  h( W" B! e 2d83122ee069189e9e437916e670248a.png , t" g& V" s4 N+ ?  c
0 f" G* E1 h8 d2 ^/ o
其中:除了命令索引和参数需要我们设置,其他都是由SDIO硬件自动控制。命令索引(如CMD0,CMD1之类)由SDIO_CMD寄存器设置,命令参数则由SDIO_ARG寄存器设置8 n5 S3 _4 Q4 s& `
6 N, x* t2 \3 s
响应" p6 s8 V8 o  {& N% j1 P

5 [5 i* {' F+ B1 l% P1.一般SD卡在接收到命令行,都会有一个应答(CMD0例外),这个应答我们也称之为响应。STM32的SDIO接口,支持2种响应类型:短响应(48位)和长响应(136位)  \7 f6 B, |6 Q( h6 p$ e2 {
- U/ \! e0 o/ }' q
2.STM32 SDIO短响应(48位)格式如下表所示:
( I/ p0 l9 e, @5 Y: h
  k6 e, a8 p2 P% B4 ]# M 130718cbce19662d2e848517a1a88e99.png 9 x, h; m; h2 y: K$ l6 b9 u# ]1 k
6 \: q7 w0 g! M$ Q0 H
STM32 SDIO长响应(136位)格式如下表所示
& H- P' D; }/ P2 H  f8 o' P4 e2 c5 y; ]8 R% t
6de500f8462d205c9c47660cef1fac2d.png
( `. M# k. z( v' D* G& d" h8 ?
% `. J6 m6 R- p; v% K  r( |  Q不论是短响应还是长响应,硬件都会自动滤除了起始位、传输位、CRC7以及结束位等信息,对于短响应,命令索引存放在SDIO_RESPCMD寄存器,参数则存放在SDIO_RESP1寄存器里面。对于长响应,则仅留CID/CSD位域,存放在SDIO_RESP1~SDIO_RESP4等4个寄存器。. g- M, }* r2 A& W1 b% ~1 I

* w0 J& R' V( d0 E" p# H, hSD卡的响应- P$ I7 N! S8 Q( B$ S
' P* v; t! i2 ^$ i  @* z
SD卡总共有6类响应(R1、R1b、R2、R3、R6、R7),我们这里以R1为例简单介绍一下。R1(普通响应命令)响应属于短响应,其长度为48位,如下表所示:4 U% V: S& e3 J) c; F: d/ |

( X6 b6 h3 Q# O% \4 f* f) Z$ y 8b314e8d311ad91b556f02f55c421abf.png 8 m2 G  b# h! m8 A; w8 b3 B

& _. U1 P& C& [8 e在收到R1响应后,我们可以从SDIO_RESPCMD寄存器和SDIO_RESP1寄存器分别读出命令索引和卡状态信息。关于其他响应的介绍,请大家参考光盘:《SD卡2.0协议.pdf》* K$ x7 O* B7 K" u; d
" P* m4 t; [! O! K$ J. F' B
05、SDIO块数据传输
: `2 ^( e$ t$ a1 a( m" c+ ~多数据块读操作
8 i3 o9 o1 _0 C  o9 V
  |6 t0 `# a$ G, b
SDIO与SD卡通信一般以数据块的形式进行传输,SDIO(多)数据块读操作,如下图所示' _1 H9 k0 v, i+ B$ w
# k/ b) X& a) q  m6 l& Z" w1 }
e7bb859ba99ff447fce0f73a6e1e4d72.png " b6 e" `: h$ S9 _4 Q6 H$ R5 I
# l- h. g% V. y9 M8 j' m5 J
从机在收到主机相关命令后,开始发送数据块给主机,所有数据块都带CRC校验(由硬件自动处理),单个数据块读的时候,在收到1个数据块以后即可以停止了,不需要发送停止命令(CMD12).但是多块数据读的时候,SD卡将一直发送数据给主机,直到接到主机发送的STOP命令(CMD12)
: T/ \) z# \4 ^! E! \% G* R; a" e0 f/ b% f) j) [8 ~6 i8 k0 F$ T
多数据块写操作
7 i: D; r, y; z+ z7 D, u6 x
. t& t  h9 G% p- f: {) TSDIO(多)数据块写操作,如下图所示
2 N7 Z5 O6 ~# a7 X
3 w* i8 Y2 G' Y8 ? 81e60d5e1e51cda815e041e241647551.png
& f5 b2 a- E+ J; M
+ R" h' {  u/ L5 a数据块写操作同数据块读操作基本类似,只是数据块写的时候,多了一个繁忙判断,新的数据块必须在SD卡非繁忙的时候发送。这里的繁忙信号由SD卡拉低SDIO_D0,以表示繁忙,SDIO硬件自动控制,不需要我们软件处理。$ c4 K, H: ~% N+ ]
7 i7 ]2 W3 M  h: K5 {5 ^
注意:当SDIO_CK频率过快时,可能导致SD卡通信失败,此时,建议降低SDIO_CK试试。
9 n; D' i% R+ u4 i8 A- q7 L' q. ^( h3 t" z; U
06、代码
/ x) }4 c* F6 PSTM32的SDIO控制器驱动还是很复杂的,ST提供了stm32f2x_sdio_sd.c驱动文件,我们组要修改对应的GPIO驱动即可。
7 s: u- G( u0 r/ n8 f8 P* p; ~: C. T9 p$ P, h# \3 k
  1. /**
    . j9 b9 ?/ s% O5 H4 C# M9 i, B% I, Q
  2.   * @brief  Initializes the SD Card and put it into StandBy State (Ready for 3 W3 v* X4 r* N0 M9 W
  3.   *         data transfer).3 Y& [) H9 Z/ P
  4.   * @param  None
    8 ~& F: B1 T: S# H* c% j0 e" V/ S
  5.   * @retval None
    % |7 a( X" ~& L. n4 ~
  6.   */
    7 D) C/ B; `  x& ~
  7. void SD_LowLevel_Init(void)
    5 g; j& n% ^! H
  8. {
    8 u5 |9 N2 ^+ L1 @" u7 X
  9.   GPIO_InitTypeDef  GPIO_InitStructure;7 b- s+ F% T1 m: j7 D" F& H

  10. % r& @" u. O( ?0 }1 z6 q1 S
  11.   /* GPIOC and GPIOD Periph clock enable */
    9 H& z/ x" [7 F
  12.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | SD_DETECT_GPIO_CLK, ENABLE);
    ) l: `' h7 u+ n3 Z- z  i4 y
  13. 8 u8 q) B) R; `1 e- f
  14.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_SDIO);
    1 x* V! i3 I' y3 S# ]' D
  15.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_SDIO);
      M, d, [- L) |! [
  16.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SDIO);
    4 x" t: a) {* y6 ]1 X( u
  17.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_SDIO);; U4 y( m8 x" Y
  18.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SDIO);) }: Z7 y9 Z8 \% F" T
  19.   GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_SDIO);# A3 l  W- H# |- U/ u: r! E& K+ Y

  20.   F: ?1 H6 l7 ^; c0 W
  21.   /* Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins */
    7 g' s! U" P# ?
  22.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
    0 J2 Z& ]9 r2 H# I, Z& W- ^: n
  23.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
    7 |# k% L7 N3 j
  24.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    ) e8 G% D: o* A0 ]
  25.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    2 n% Y$ d2 R( y: ^6 h, E
  26.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    , c5 m( O, R! o4 N1 P: H; [* F
  27.   GPIO_Init(GPIOC, &GPIO_InitStructure);: Q1 \; H6 F! ?- i

  28. + _2 m' j: r/ t3 L/ L
  29.   /* Configure PD.02 CMD line */  V3 I* Y4 Y# r
  30.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    - n; H" H7 I5 W' e8 U+ @; z- k
  31.   GPIO_Init(GPIOD, &GPIO_InitStructure);
    5 X7 [, j* S  j% Z5 D9 ^5 D8 z! H2 [
  32. 9 u4 F; K) F& L$ E: H+ O  ~
  33.   /* Configure PC.12 pin: CLK pin */& }2 g6 _* f" t4 L
  34.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    * @9 a" p" u/ {* q. V* K
  35.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;0 a! k5 l7 W1 T0 u/ A" j
  36.   GPIO_Init(GPIOC, &GPIO_InitStructure);6 x% m" A. V7 M; D# j

  37. # q# B. a! _9 ~' d5 s
  38.   /*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */( f7 {0 B1 O( x$ X, s" K
  39.   /*GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN;
    * K5 l/ H* ]- f4 j6 c# @
  40.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    6 ]1 Y/ S- r2 c& `, e# A
  41.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    . {/ k( i( B+ X9 e' A6 q
  42.   GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure);*/" H, h! w! w1 b) u9 ~4 ?9 ]

  43. 8 ]6 J* _( Q: J0 a! R8 b
  44.   /* Enable the SDIO APB2 Clock */2 v9 u: a* H, e3 q. [2 }
  45.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, ENABLE);
    0 r$ }0 @$ c4 I; N5 u' x% }" R  S6 z

  46.   E0 a8 m* I+ Q6 V6 z& T/ _, Z! u5 {
  47.   /* Enable the DMA2 Clock *// p* ~4 C+ ^- P
  48.   RCC_AHB1PeriphClockCmd(SD_SDIO_DMA_CLK, ENABLE);
    8 L' b6 ]" ?2 k) }5 O
  49. }% `, l3 t' T( C5 ~$ b6 g( s' K
复制代码

: z2 k2 ~# O2 i/ D; xDMA等配置使用默认的即可。
' L1 ]  q; R) A9 c, I7 _0 a4 B5 j& I: b; z1 Y! _$ n
我们需要使用的函数接口有
/ v  z# n( i( F. E5 E$ M& B# ~' r
  1. SD_Error SD_Init(void);
    0 P9 S% u5 o$ T2 T$ T  E! w
  2. SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr);
    8 ?9 l* [5 z$ m9 W5 {3 P
  3. SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize);
    6 H  x) L, w' g' J7 |7 i+ B1 M9 Z
  4. SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize);
复制代码

4 u7 A9 p% ^) F+ C$ I' u5 Y$ l+ Z下载验证
0 r: m! {* C% m% Y( ]. [% c9 M( }8 V
b1f6570da5c37cff0345099d9051d796.png
: o" O1 @  t! ~' }4 @9 I5 a
+ X1 l, p$ Z; t7 [% d! j, b
/ B0 d% v; j9 f9 h* G2 n" e4 e
+ F: Q0 g8 l9 T( ~  P
赞 收藏 评论0 发布时间:2022-4-17 21:15

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版