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

【经验分享】STM32 SDIO详解

[复制链接]
STMCU小助手 发布时间:2022-4-17 21:15
1、SDIO简介
! j) E( l  A* R+ k9 h# }+ ~( ^# WSDIO,全称:Secure Digital Input and Output,即安全数字输入输出接口。它是在SD卡接口的基础上发展而来,它可以兼容之前的SD卡,并可以连接SDIO接口设备,比如:蓝牙、WIFI、照相机等。
" O2 N) F5 ^# O
" B& J; Z1 B+ j% L  _4 T# z' XSDIO和SD卡规范间的一个重要区别是增加了低速标准。低速卡的目标应用是以最小的硬件开支支持低速I/O能力。低速卡支持类似调制解调器、条码扫描仪和GPS接收器等应用。
: \3 e2 X& B! W3 s) P. K
5 @' c6 C2 Q0 I5 jSTM32的SDIO控制器支持多媒体卡(MMC卡)、SD存储卡、SDI/O卡和CE-ATA设备。
& @/ X" Q+ A) I1 H. A
- u/ }& s" A% y6 Z( c: ASDIO框图* ?' m1 o& C  H3 R
9 K0 I2 E/ q9 G- h% a1 O5 H1 R% Y
fce26341379d9bf350b4ff04ee7e2d8c.png 7 U, U" ^" x5 T2 Y6 l
  r& p0 @0 Z9 Y# I3 v! l1 D8 \: Y( X% \
复位后SDIO_D0用于数据传输。初始化后主机可以改变数据总线的宽度(通过ACMD6命令设置)
6 v' _, f/ d( c& X' N
: Y$ b( x2 x1 Y* Z- ~! _) T如果一个多媒体卡接到了总线上,则SDIO_D0、SDIO_D[3:0]或SDIO_D[7:0]可以用于数据传输。      
7 n* W7 M8 r7 x; j0 x; l; o# n; Y' E( D5 S' j( W
MMC版本V3.31和之前版本的协议只支持1位数据线,所以只能用SDIO_D0(为了通用性考虑,在程序里面我们只要检测到是MMC卡就设置为1位总线数据)4 c8 @. c. o; C) \/ s2 L) s
% g% G. t3 M! E6 @" r9 f
02、SDIO特点- d2 U9 s  F% L0 o2 t
①与多媒体卡系统规格书版本4.2全兼容。支持三种不同的数据总线模式:1位(默认)、4位和8位。( h1 c0 e* w/ [( p% X: I4 o

1 s% |4 P" R% Z0 I" s: f) a②与较早的多媒体卡系统规格版本全兼容(向前兼容)。
; ]" G8 s6 |& e& \( @- Q$ b) H# a9 A! ~
③与SD存储卡规格版本2.0全兼容。& v' P8 B- A7 D. X+ _' v0 V% _

/ w7 }0 r$ F5 l0 m) q1 J2 H7 N1 S④与SDI/O卡规格版本2.0全兼容:支持两种不同的数据总线模式:1位(默认)和4位。/ A( ?  s5 A  C: e7 R

5 r, A; i7 E9 O" V. b⑤完全支持CE-ATA功能(与CE-ATA数字协议版本1.1全兼容)。8位总线模式下数据传输速率可达48MHz。
+ C  H3 P  X% N# z
$ q7 R  w, `: H, u⑥数据和命令输出使能信号,用于控制外部双向驱动器。2 h9 P. y: v9 h, c5 v+ @
4 [' E( K/ w& e4 E1 ^5 @
03、SDIO时钟
2 \! i# {. w1 W5 v- {1.卡时钟(SDIO_CK):每个时钟周期在命令和数据线上传输1位命令或数据。对于SD或SD I/O卡,时钟频率可以在0MHz至25MHz间变化。
6 r# j7 v; G" x" K1 x2 x
0 p. G" n5 r" m  H: }2.SDIO适配器时钟(SDIOCLK):该时钟用于驱动SDIO适配器,可用于产生SDIO_CK时钟。SDIOCLK来自PLL48CK(48Mhz)。
) U3 e3 w. e; n- P/ a( M/ C8 \9 a! P5 L9 g+ N0 E! H" M
APB2总线接口时钟(PCLK2):该时钟用于驱动SDIO的APB2总线接口,其频率为PCLK2=84Mhz。& ?! c  J7 C7 `: |* g9 [

0 N+ d/ X: g) f" `SDIO_CK计算公式:SDIO_CK=SDIOCLK/(2+CLKDIV)
2 x; W2 ~& h8 l
4 @4 s3 T; U' s' V- n9 ]7 w4 c注意:在SD卡初始化时,SDIO_CK不可以超过400Khz,初始化完成后,可以设置为最大频率(但不可以超过SD卡最大操作频率)
! |- f' R3 J+ R3 X* ]' \
, k9 J1 m& Y) ?& n; F' _& p* o/ y04、SDIO的命令与响应6 n5 B0 W8 _* C4 J' c$ [+ l% V! N
命令

. @1 B4 L! _% e6 E9 H$ B" [
0 w8 c+ f2 z5 h1.SDIO的命令分为:应用相关命令(ACMD)和通用命令(CMD)两部分。发送ACMD时,需先发送CMD55。
1 m& W' D0 I/ ^3 ?7 W. o/ ~7 H7 W- a. z" `# ^" J
2.SDIO所有的命令和响应都是在SDIO_CMD引脚上面传输的,命令长度固定为48位,SDIO命令格式如下表所示:
" l, I8 B; g0 f, }) d; \1 z- a
8 \! \3 n* Y/ \" k0 S 2d83122ee069189e9e437916e670248a.png
7 y/ w. x8 C5 W/ z3 P5 \/ K9 k% c
* E& O. t* h( j( O4 T2 ~其中:除了命令索引和参数需要我们设置,其他都是由SDIO硬件自动控制。命令索引(如CMD0,CMD1之类)由SDIO_CMD寄存器设置,命令参数则由SDIO_ARG寄存器设置
- _8 O/ ]4 }' s4 P& G1 V3 d2 i" v$ r: Q- a$ }. j+ _5 F# g8 l) U7 U
响应1 m9 z& G1 T1 }# b4 k6 G3 O' D2 D
6 z# a! G! c0 w/ N6 O4 q
1.一般SD卡在接收到命令行,都会有一个应答(CMD0例外),这个应答我们也称之为响应。STM32的SDIO接口,支持2种响应类型:短响应(48位)和长响应(136位)  Q. `0 ?8 f% H0 Z4 M4 A3 I4 {+ f/ l
. r5 e+ J/ H0 G- X
2.STM32 SDIO短响应(48位)格式如下表所示:+ g$ V, p% \% E+ \9 m; f
9 Y. }2 z( d+ e. e  n. d& y
130718cbce19662d2e848517a1a88e99.png ! G  ]& _6 m& v1 u2 Q
$ F6 d6 _4 p; }4 [
STM32 SDIO长响应(136位)格式如下表所示
4 ^* s1 n& Q8 R1 z. F
. v* ~: t8 N" P. L: f  n 6de500f8462d205c9c47660cef1fac2d.png
8 j' Z  p4 u5 J4 G( c& T$ q! O! B( e. F
不论是短响应还是长响应,硬件都会自动滤除了起始位、传输位、CRC7以及结束位等信息,对于短响应,命令索引存放在SDIO_RESPCMD寄存器,参数则存放在SDIO_RESP1寄存器里面。对于长响应,则仅留CID/CSD位域,存放在SDIO_RESP1~SDIO_RESP4等4个寄存器。
! |; L" ~8 ^  w  p# E
  q% c; h' G& W( ~# ?SD卡的响应
1 O  O7 g" T; O& D2 a) N4 f  V) s/ u# {3 @
SD卡总共有6类响应(R1、R1b、R2、R3、R6、R7),我们这里以R1为例简单介绍一下。R1(普通响应命令)响应属于短响应,其长度为48位,如下表所示:
5 D: j- v, u! v  O+ p
. |& D: b$ s6 P7 k: b3 @ 8b314e8d311ad91b556f02f55c421abf.png 8 C; f6 s# t. S5 M
7 J/ y% B$ Q- L4 Q* y
在收到R1响应后,我们可以从SDIO_RESPCMD寄存器和SDIO_RESP1寄存器分别读出命令索引和卡状态信息。关于其他响应的介绍,请大家参考光盘:《SD卡2.0协议.pdf》
: z. _& z( v6 X
: l2 Z; p. H; ~" Y" _3 O  Q05、SDIO块数据传输( n1 t/ N) g3 }/ I% P! d, d8 T
多数据块读操作
" X7 E) J2 O, S& [

) S: f4 `: A5 CSDIO与SD卡通信一般以数据块的形式进行传输,SDIO(多)数据块读操作,如下图所示& _$ B; ]% `- ?

$ i4 G1 C) ^9 L( m8 U8 @6 G' | e7bb859ba99ff447fce0f73a6e1e4d72.png + m; n# J+ S1 G" E7 I
/ d% \; B9 R5 ~) Z- p" x  G
从机在收到主机相关命令后,开始发送数据块给主机,所有数据块都带CRC校验(由硬件自动处理),单个数据块读的时候,在收到1个数据块以后即可以停止了,不需要发送停止命令(CMD12).但是多块数据读的时候,SD卡将一直发送数据给主机,直到接到主机发送的STOP命令(CMD12)  E; }/ d  T$ [* A! W, r; g
; l' q0 [. Q: |
多数据块写操作
2 f% P* J( [% m5 p* i2 m7 D. {, r7 z) j6 g' M( ?
SDIO(多)数据块写操作,如下图所示
* T; l# ?* c2 z  ~
0 f* R1 u  m4 h7 o 81e60d5e1e51cda815e041e241647551.png ) a' r0 Q7 l) K
' p( m9 f$ K9 ?- j& I
数据块写操作同数据块读操作基本类似,只是数据块写的时候,多了一个繁忙判断,新的数据块必须在SD卡非繁忙的时候发送。这里的繁忙信号由SD卡拉低SDIO_D0,以表示繁忙,SDIO硬件自动控制,不需要我们软件处理。1 B7 |$ r8 l0 m- L; H7 ]7 N0 o

$ u: Z5 U1 B5 W6 r  `+ C注意:当SDIO_CK频率过快时,可能导致SD卡通信失败,此时,建议降低SDIO_CK试试。3 ]. \& I' J% Q% D' i, |+ c
4 z$ @+ K2 F) y9 @( h8 i
06、代码& s" D6 l  C2 `9 h( C
STM32的SDIO控制器驱动还是很复杂的,ST提供了stm32f2x_sdio_sd.c驱动文件,我们组要修改对应的GPIO驱动即可。
4 p% l1 F/ O' f" \, h. H$ U4 Z
! p! ^4 y1 r" N+ v% g) k
  1. /**
    2 C5 m0 p* u* L3 d- h' a* X
  2.   * @brief  Initializes the SD Card and put it into StandBy State (Ready for
    3 F5 f4 _  d' i' b" G# ~% c' n" u
  3.   *         data transfer).
    , w( ^: }, _. R6 E" F& M3 T3 {
  4.   * @param  None' x) X' s* R* H' y6 U$ i% b# [  R7 q
  5.   * @retval None) r" p6 y7 b7 Y6 S2 @& D' v
  6.   */
      c% w4 J7 l1 \! a& x
  7. void SD_LowLevel_Init(void)
    / u0 G0 l. e/ H
  8. {6 U, [4 \" a& v! _, U. |2 x* G" I+ s
  9.   GPIO_InitTypeDef  GPIO_InitStructure;6 ]9 N# s7 e! e6 ?9 p' b, z
  10. ! h1 r2 i' e. z# n
  11.   /* GPIOC and GPIOD Periph clock enable */! R" Z: z4 q$ J. d, w" v% F$ `
  12.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | SD_DETECT_GPIO_CLK, ENABLE);4 [1 @  _# Z4 j; O) y+ F. D

  13. ; d# G) C9 r8 U2 E$ r# P3 x% o
  14.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_SDIO);9 J2 l" _. O  c! R9 i& E( @, K
  15.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_SDIO);
    , L# w6 B/ j* v: R( B
  16.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SDIO);. O4 X9 K( P% ^. B* X
  17.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_SDIO);
    7 x$ @5 P  A: L8 g
  18.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SDIO);; y2 l/ a& j9 R" u' J
  19.   GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_SDIO);
    1 G* n8 ]$ Y; ^! k& U' s8 J6 k4 u

  20. ( _' I& W4 t+ f
  21.   /* Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins */
    - ~( q9 E7 t5 n$ E& ]
  22.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
    * i/ C& l" |! \5 p; Z: a3 z, f: T
  23.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;6 H. |" N0 ^, Q/ j+ X- i
  24.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    4 e% O; |, d$ V" k( @8 Z
  25.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    / _4 k4 y! J* N$ g( U
  26.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;# Q7 {" O" J/ w" r
  27.   GPIO_Init(GPIOC, &GPIO_InitStructure);
    $ {+ Z9 d! N/ i: U0 _3 i

  28.   H) n; c3 \- W+ x* R9 j
  29.   /* Configure PD.02 CMD line */
    ; D8 g) d0 m! h  O) a
  30.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;. G! A0 U' v0 N8 H0 \
  31.   GPIO_Init(GPIOD, &GPIO_InitStructure);9 v* l* z7 _& z. ^9 U) _

  32. + W0 ]5 V1 K; ~: R
  33.   /* Configure PC.12 pin: CLK pin */
    & H8 M% T" b/ }
  34.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    7 d# k" r$ I  E" e9 q9 X! w! M, }
  35.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    * i! U) p" J* _# O
  36.   GPIO_Init(GPIOC, &GPIO_InitStructure);  {. Q  f1 R3 M4 g9 v% X: z$ s
  37. 0 O' Z2 J' N8 t
  38.   /*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */
    & Q' y, O5 \% O# y$ G  E4 q. C1 C; T
  39.   /*GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN;5 A9 ]" |, _: t  H0 x/ c8 b
  40.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;. \# e6 H, D1 F$ X( e% b3 o. O
  41.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;, g3 N, J, d# |5 Z8 b  S7 l
  42.   GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure);*/
    9 x4 K2 A( A1 b$ E' h* E% Z" J

  43. 2 b+ k1 D( L9 K
  44.   /* Enable the SDIO APB2 Clock */7 w3 T% d+ V' L1 K, h' ?; v- d! B/ |9 A
  45.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, ENABLE);
    4 `1 O3 w, n+ \+ x  A8 F" w9 N
  46. - A; w, S$ S) f$ P" A
  47.   /* Enable the DMA2 Clock */4 R8 A; K  Z) e- b% I
  48.   RCC_AHB1PeriphClockCmd(SD_SDIO_DMA_CLK, ENABLE);/ Y% p; \7 ^8 A) d7 ~* T
  49. }5 ^8 O4 r; G1 ~
复制代码

# w7 j7 J5 d( I6 S# SDMA等配置使用默认的即可。
' T( S1 K& R: G! h2 m6 N( {% @6 D$ y( Y9 o7 Q& S+ e# Y* R: W
我们需要使用的函数接口有
" a5 Z4 R7 a& Y" y" A. s0 ?# Z5 H+ u
  1. SD_Error SD_Init(void);
    7 p3 f. k4 ~; z$ s
  2. SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr);1 O2 p! x5 ?  @+ E
  3. SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize);& F( K0 }- h6 t' u# R
  4. SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize);
复制代码

: j4 ?/ Z8 n% {9 O7 h  p- m下载验证, z: |2 R% ]/ |

) r3 _9 A' o- J b1f6570da5c37cff0345099d9051d796.png
! |& V/ N5 B! w7 ~/ `  V( Z% u' W5 T: O* z

0 j3 x+ i5 a: _% U7 J7 l8 _0 B! G& |5 H, |
收藏 评论0 发布时间:2022-4-17 21:15

举报

0个回答

所属标签

相似分享

官网相关资源

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