开发板原理图设计 SD卡座
没有插入SD卡时,SD_CD#和SD_WP都为高电平;当SD卡正确插入卡座后,SD_CD#和SD_WP都为低电平。
注意:Micro-SD没有SD_WP引脚。
与主芯片的连接
[编辑]SDIO [编辑]SDIO原理 [编辑]SDIO简介
SD/SDIO MMC卡主机模块(SDIO)在AHB外设总线和多媒体卡(MMC)、SD存储卡、SDIO卡和CE-ATA设备间提供了一个操作接口。
SDIO的主要特性如下:
与多媒体卡系统规范4.2版本全兼容。支持三种不同的数据总线模式:1位(默认)、4位和8位。 与较早的多媒体卡系统规格版本全兼容(向前兼容)。 与SD存储卡规范2.0版本全兼容。 与SD I/O卡规范2.0版本全兼容:支持两种不同的数据总线模式:1位(默认)和4位。 完全支持CE-ATA功能(与CE-ATA数字协议版本1.1全兼容)。 8位总线模式下数据传输速率可达48MHz。 数据和命令输出使能信号,用于控制外部双向驱动器。
注:
SDIO没有SPI兼容的通信模式 在多媒体卡系统规范V2.11中定义,SD存储卡协议是多媒体卡协议的超集。只有I/O功能的SD卡或复合卡中的I/O部分不支持SD 存储设备所需的一些命令,其中有些命令在SD I/O设备中不起作用,如擦除命令,因此SDIO不支持这些命令。另外,SD存储卡和SD I/O卡中有些命令是不同的,SDIO也不支持这些命令。详情可以参考SD I/O卡规范V1.0。MMC接口使用现有的MMC命令机制,可以实现CE-ATA的支持。SDIO接口的电气和信号定义详见MMC参考资料。
多媒体卡/SD总线将所有卡与控制器相连。
当前版本的SDIO在同一时间里只能支持一个SD/SDIO/MMC 4.2的卡,但可以支持多个MMC版本4.1或以前版本的卡。
SDIO总线的通信是基于命令和数据的传输。
SDIO总线上的基本操作是命令/响应操作。这些总线操作类型在命令/响应结构间直接地传输它们的信息。另外,一些操作还有数据令牌。
SD/SDIO 存储卡的数据是以数据块的形式进行传输的。MMC的数据可以以块或流的形式进行传输。CE_ATA设备的数据也是以数据块的形式进行传输的。
[编辑]SDIO功能描述
SDIO包含2个部分:
SDIO适配器模块:实现所有MMC/SD/SD I/O卡的相关功能,如时钟的产生、命令和数据的传送。 AHB总线接口:操作SDIO适配器模块中的寄存器,并产生中断和DMA请求信号。
(图)SDIO结构框图
复位后默认情况下SDIO_D0用于数据传输。初始化后主机可以改变数据总线的宽度。
如果一个多媒体卡接到了总线上,则SDIO_D0、SDIO_D[3:0]或SDIO_D[7:0]可以用于数据传输。MMC V3.31和之前版本的协议只支持1位数据线,所以只能用SDIO_D0。
如果一个SD或SD I/O卡接到了总线上,可以通过主机配置数据传输使用SDIO_D0或SDIO_D[3:0]。所有的数据线都工作在推挽模式。
SDIO_CMD有两种操作模式:
用于初始化时的开漏模式(仅用于MMC V3.31或之前版本)用于命令传输的推挽模式(SD/SD I/O卡和MMC V4.2在初始化时也使用推挽驱动)
SDIO_CK是卡的时钟:每个时钟周期在命令和数据线上传输1位命令或数据。对于MMC V3.31协议,时钟频率可达20MHz;对于MMC V4.0/4.2协议,时钟频率可达48MHz;对于SD或SD I/O卡,时钟频率可达25MHz。
SDIO使用两个时钟信号:
SDIO适配器时钟(SDIOCLK=HCLK)AHB总线时钟(HCLK/2)
下表适用于多媒体卡/SD/SD I/O卡总线:
(表)SDIO引脚定义
[编辑]SDIO适配器
下图是简化的SDIO适配器框图:
(图)SDIO适配器
SDIO适配器是多媒体/加密数字存储卡总线的主设备(主机),用于连接一组多媒体卡或一个加密数字存储卡,它包含以下5个部分:
适配器寄存器模块 控制单元 命令通道 数据通道 数据FIFO
注意:适配器寄存器和FIFO使用AHB总线一侧的时钟(HCLK/2),控制单元、命令通道和数据通道使用SDIO适配器一侧的时钟(SDIOCLK)。
[编辑]适配器寄存器模块
适配器寄存器模块包含所有系统寄存器。该模块还产生清除多媒体卡中静态标志的信号,当在SDIO清除寄存器中的相应位写’1’时会产生清除信号。
[编辑]控制单元
控制单元包含电源管理功能和为存储器卡提供的时钟分频。
共有三种电源阶段:
电源关闭电源启动电源打开
(图)SDIO适配器控制单元
上图为控制单元的框图,包括电源管理和时钟管理子单元。
在电源关闭和电源启动阶段,电源管理子单元会关闭卡总线上的输出信号。
时钟管理子单元产生和控制SDIO_CK信号。SDIO_CK输出可以使用时钟分频或时钟旁路模式。下述情况下没有时钟输出:
复位后在电源关闭和电源启动阶段当启动了省电模式并且卡总线处于空闲状态(命令通道和数据通道子单元进入空闲阶段后的8个时钟周期) [编辑]命令通道
命令通道单元向卡发送命令并从卡接收响应。
(图)SDIO适配器命令通道
命令通道状态机(CPSM)
当写入命令寄存器并设置了使能位,开始发送命令。命令发送完成时,命令通道状态机(CPSM)设置状态标志并在不需要响应时进入空闲状态,在需要响应时,则等待响应(见下图)。当收到响应后,接收到的CRC码将会与内部产生的CRC码比较,然后设置相应的状态标志。
(图)命令通道状态机CPSM
当进入等待(Wait)状态时,命令定时器开始运行;在CPSM进入接收(Receive)状态之前,如果产生了超时,则设置超时标志并进入空闲(Idle)状态。
注:命令超时固定为64个SDIO_CK时钟周期。
如果设置了命令寄存器中的中断位,则关闭定时器,并且CPSM等待某一个卡发出的中断请求。如果设置了命令寄存器中的挂起位,则CPSM进入挂起 (Pend)状态并等待数据通道子单元发出的CmdPend信号。当检测到CmdPend信号时,CPSM进入发送(Send)状态,这使得数据计数器去 触发停止命令的传输。
注:CPSM保持在空闲状态至少8个SDIO_CK周期,以满足NCC和NRC时序限制。NCC是两个主机命令间的最小间隔;NRC是主机命令与卡响应之间的最小间隔。
(图)SDIO命令传输
命令和响应格式
命令:命令是用于开始一项操作。主机向一个指定的卡或所有的卡发出带地址的命令或广播命令(广播命令只适合于MMC V3.31或之前的版本)。命令在CMD线上串行传送。所有命令的长度固定为48位,下表给出了多媒体卡、SD存储卡和SDIO卡上一般的命令格式。 CE-ATA命令是MMC V4.2命令的扩充,所以具有相同的格式。
命令通道操作于半双工模式,这样命令和响应可以分别发送和接收。如果CPSM不处在发送状态,SDIO_CMD输出处于高阻状态,如上图所示。SDIO_CMD上的数据与SDIO_CK的上升沿同步。
(表)命令格式
响应:响应是由一个被指定地址的卡发送到主机,对于MMC V3.31或以前版本所有的卡同时发送响应;响应是对先前接收到命令的一个应答。响应在CMD线上串行传送。
SDIO支持2种响应类型,2种类型都有CRC错误检测:
48位短响应136位长响应
注:如果响应不包含CRC(如CMD1的响应),设备驱动应该忽略CRC失败状态。
(表)短响应格式
(表)长响应格式
命令寄存器包含命令索引(发至卡的6位)和命令类型;这决定了命令本身是否需要响应和响应的类型(48位还是136位)。下表列出了命令通道中的状态标志:
(表)命令通道状态标志
CRC发生器
计算CRC码之前所有位的CRC校验和,包括开始位、发送位、命令索引和命令参数(或卡状态)。对于长响应格式,CRC校验和计算的是CID或CSD的前120位;注意,长响应格式中的开始位、传输位和6个保留位不参与CRC计算。
CRC校验和是一个7位的数值:
CRC[6:0] = 余数[(M(x) * x7) / G(x)]G(x) = x7 + x3 + 1M(x) = (开始位) * x39 + … + (CRC前的最后一位) * x0, 或M(x) = (开始位) * x119 + … + (CRC前的最后一位) * x0 [编辑]数据通道
数据通道子单元在主机与卡之间传输数据。下图是数据通道的框图。
(图)SDIO适配器数据通道
在时钟控制寄存器中可以配置卡的数据总线宽度。如果选择了4位总线模式,则每个时钟周期四条数据信号线(SDIO_D[3:0])上将传输 4位数据;如果选择了8位总线模式,则每个时钟周期八条数据信号线(SDIO_D[7:0])上将传输8位数据;如果没有选择宽总线模式,则每个时钟周期 只在SDIO_D0上传输1位数据。
如果数据通道状态机(DPSM)被使能,则它将根据传输的方向(发送或接收)进入Wait_S或Wait_R状态:
发送:DPSM进入Wait_S状态。如果发送FIFO中有数据,则DPSM进入发送状态,同时数据通道子单元开始向卡发送数据。 接收:DPSM进入Wait_R状态并等待开始位;当收到开始位时,DPSM进入接收状态,同时数据通道子单元开始从卡接收数据。 数据通道状态机(DPSM)
DPSM工作频率为SDIO_CK,卡总线信号线上的数据与SDIO_CK的上升沿同步。DPSM有6个状态,如下图所示:
(图)数据通道状态机(DPSM)
空闲(Idle):数据通道不工作,SDIO_D[7:0]输出处于高阻状态。当写入数据控制寄存器并设置使能位时,DPSM为数据计数器加载新的数值,并跟据数据方向位,进入Wait_S或Wait_R状态。 Wait_R:如果数据计数器等于0,当接收FIFO为空时DPSM进入到空闲(Idle)状态。如果数据计数器不等于0,DPSM等待 SDIO_D上的开始位。如果DPSM在超时之前接收到一个开始位,它会进入接收(Receive)状态并加载数据块计数器。如果DPSM在检测到一个开 始位前出现超时,或发生开始位错误,DPSM将进入空闲状态并设置超时状态标志。 接收(Receive):接收到的串行数据被打包成字节并写入数据FIFO。根据数据控制寄存器中传输模式位的设置,数据传输模式可以是块传输或流传输: ─ 在块模式下,当数据块计数器达到0时,DPSM等待接收CRC码,如果接收到的代码与内部产生的CRC码匹配,则DPSM进入Wait_R状态,否则设置CRC失败状态标志,同时DPSM进入到空闲状态。─ 在流模式下,当数据计数器不为0时,DPSM接收数据;当计数器为0时,将移位寄存器中的剩余数据写入数据FIFO,同时DPSM进入Wait_R状态。如果产生了FIFO 上溢错误,DPSM设置FIFO的错误标志并进入空闲状态。 Wait_S:如果数据计数器为0,DPSM进入空闲状态;否则DPSM等待数据FIFO空标志消失后,进入发送状态。
注:DPSM会在Wait_S状态保持至少2个时钟周期,以满足NWR的时序要求,NWR是接收到卡的响应至主机开始数据传输的间隔。
发送(Send):DPSM开始发送数据到卡设备。根据数据控制寄存器中传输模式位的设置,数据传输模式可以是块传输或流传输: ─ 在块模式下,当数据块计数器达到0时,DPSM发送内部产生的CRC码,然后是结束位,并进入繁忙状态。─ 在流模式下,当使能位为高同时数据计数器不为0时,DPSM向卡设备发送数据,然后进入空闲状态。如果产生了FIFO下溢错误,DPSM设置FIFO的错误标志并进入空闲状态。 繁忙(Busy):DPSM等待CRC状态标志: ─ 如果没有接收到正确的CRC状态,则DPSM进入空闲状态并设置CRC失败状态标志。─ 如果接收到正确的CRC状态,则当SDIO_D0不为低时(卡不繁忙)DPSM进入Wait_S状态。当DPSM处于繁忙状态时发生了超时,则DPSM设置数据超时标志并进入空闲状态。当DPSM处于Wait_R或繁忙状态时,如果数据定时器被使能,则产生数据超时错误:─ 发送数据时,如果DPSM处于繁忙状态超过程序设置的超时间隔,则产生超时。─ 接收数据时,如果未收完所有数据,并且DPSM处于Wait_R状态超过程序设置的超时间隔,则产生超时。 数据:数据在数据线两端的主机和卡之间进行传输。数据存储在一个32字的FIFO中,每个字为32位宽。
(表)数据令牌格式
数据FIFO
数据FIFO(先进先出)子单元是一个具有发送和接收单元的数据缓冲区。
FIFO包含一个每字32位宽、共32个字的数据缓冲区,和发送与接收电路。因为数据FIFO工作的工作频率为AHB时钟(HCLK/2),所以,所有SDIO时钟(SDIOCLK)的信号都进行了重新同步。
跟据TXACT和RXACT标志,可以关闭FIFO、使能发送或使能接收。TXACT和RXACT由数据通道子单元设置而且是互斥的:
─ 当TXACT有效时,发送FIFO代表发送电路和数据缓冲区─ 当RXACT有效时,接收FIFO代表接收电路和数据缓冲区 发送FIFO:
当使能了SDIO的发送功能,数据可以通过AHB接口写入发送FIFO。
通过32个连续的地址可以访问发送FIFO。发送FIFO中有一个数据输出寄存器,包含读指针指向的数据字。当数据通道子单元装填了移位寄存器后,它移动读指针至下个数据并传输出数据。
如果未使能发送FIFO,所有的状态标志均被清除。当发送数据时,数据通道子单元设置TXACT为有效。
(表)发送FIFO状态标志
接收FIFO:
当数据通道子单元接收到一个数据字,它会把数据写入FIFO,写操作结束后,写指针自动加一;在另一端,有一个读指针始终指向FIFO中的当前数 据。如果关闭了接收FIFO,所有的状态标志均被清除,读写指针也被复位。当接收到数据时,数据通道子单元设置RXACT。下表列出了接收FIFO的状态 标志。通过32个连续的地址可以访问接收FIFO。
(表)接收FIFO状态标志
[编辑]SDIO AHB接口
AHB接口产生中断和DMA请求,并访问SDIO适配器寄存器和数据FIFO。它包含一个数据通道、寄存器译码器和中断/DMA控制逻辑。
[编辑]SDIO中断
当至少有一个选中的状态标志为高时,中断控制逻辑产生中断请求。有一个屏蔽寄存器用于选择可以产生中断的条件,如果设置了相应的屏蔽标志,则对应的状态标志可以产生中断。
[编辑]SDIO/DMA接口:SDIO和存储器之间数据传输的过程
在下面的例子中,使用CMD24(WRITE_BLOCK)从SDIO主控制器传送512字节到MMC卡。DMA控制器用于从存储器向SDIO的FIFO填充数据。
1. 执行卡识别过程2. 提高SDIO_CK频率3. 发送CMD7命令选择卡4. 按下述步骤配置DMA2:a) 使能DMA2控制器并清除所有的中断标志位b) 设置DMA2通道4的源地址寄存器为存储器缓冲区的基地址,DMA2通道4的目标地址寄存器为SDIO_FIFO寄存器的地址c) 设置DMA2通道4控制寄存器(存储器递增,非外设递增,外设和源的数据宽度为字宽度)d) 使能DMA2通道45. 发送CMD24(WRITE_BLOCK),操作如下:a) 设置SDIO数据长度寄存器(SDIO数据时钟寄存器应该在执行卡识别过程之前设置好)b) 设置SDIO参数寄存器为卡中需要传送数据的地址c) 设置SDIO命令寄存器:CmdIndex置为24(WRITE_BLOCK);WaitResp置为1(SDIO卡主机等待响应);CPSMEN置为1(使能SDIO卡主机发送命令),保持其它域为他们的复位值。d) 等待SDIO_STA[6]=CMDREND中断,然后设置SDIO数据寄存器:DTEN置为1(使能SDIO卡主机发送数据);DTDIR置为0(控制 器至卡方向);DTMODE置 为0(块数据传送);DMAEN置为1(使能DMA);DBLOCKSIZE置为0x9(512字节);其它域不用设置。e) 等待SDIO_STA[10]=DBCKEND6. 查询DMA通道的使能状态寄存器,确认没有通道仍处于使能状态。 [编辑]SDIO寄存器描述
下表列出了SDIO寄存器地址映射。必须以字(32位)的方式访问这些外设寄存器。
[编辑]SDIO电源控制寄存器(SDIO_POWER)
位31:2 保留,始终读为0。
位1:0PWRCTRL:电源控制位(Power supply control bits)
这些位用于定义卡时钟的当前功能状态:00:电源关闭,卡的时钟停止。01:保留10:保留的电源启动11:电源打开,卡的时钟开启。
注意:写数据后的7个HCLK时钟周期内,不能写入这个寄存器。
[编辑]SDIO时钟控制寄存器(SDIO_CLKCR)
SDIO_CLKCR寄存器控制SDIO_CK输出时钟。
位31:15 保留,始终读为0。
位14HWFC_EN:硬件流控制使能(HW Flow Control enable)
0:关闭硬件流控制1:使能硬件流控制当使能硬件流控制后,关于TXFIFOE和RXFIFOF中断信号的意义请参考SDIO状态寄存器的定义。
位13NEGEDGE:SDIO_CK相位选择位(SDIO_CK dephasing selection bit)
0:在主时钟SDIOCLK的上升沿产生SDIO_CK。1:在主时钟SDIOCLK的下降沿产生SDIO_CK。
位12:11WIDBUS:宽总线模式使能位(Wide bus mode enable bit)
00:默认总线模式,使用SDIO_D0。01:4位总线模式,使用SDIO_D[3:0]。10:8位总线模式,使用SDIO_D[7:0]。
位10BYPASS:时钟分频器旁路使能位(Clock pider bypass enable bit)
0:关闭旁路:驱动SDIO_CK输出信号之前,依据CLKDIV数值对SDIOCLK分频。1:使能旁路:SDIOCLK直接驱动SDIO_CK输出信号。
位9PWRSAV:省电配置位(Power saving configuration bit)
为了省电,当总线为空闲时,设置PWRSAV位可以关闭SDIO_CK时钟输出。0:始终输出SDIO_CK。1:仅在有总线活动时才输出SDIO_CK。
位8CLKEN:时钟使能位(Clock enable bit)
0:SDIO_CK关闭。1:SDIO_CK使能。
位7:0CLKDIV:时钟分频系数(Clock pide factor)
这个域定义了输入时钟(SDIOCLK)与输出时钟(SDIO_CK)间的分频系数:SDIO_CK频率 = SDIOCLK/[CLKDIV + 2]。注意: 当SD/SDIO卡或多媒体卡在识别模式,SDIO_CK的频率必须低于400kHz。 当所有卡都被赋予了相应的地址后,时钟频率可以改变到卡总线允许的最大频率。 写数据后的7个HCLK时钟周期内不能写入这个寄存器。对于SD I/O卡,在读等待期间可以停止SDIO_CK,此时SDIO_CLKCR寄存器不控制SDIO_CK。 [编辑]SDIO参数寄存器(SDIO_ARG)
SDIO_ARG寄存器包含32位命令参数,它将作为命令的一部分发送到卡中。
位31:0CMDARG:命令参数 (Command argument)
命令参数是发送到卡中命令的一部分,如果一个命令包含一个参数,必须在写命令到命令寄存器之前加载这个寄存器。 [编辑]SDIO命令寄存器(SDIO_CMD)
SDIO_CMD寄存器包含命令索引和命令类型位。命令索引是作为命令的一部分发送到卡中。命令类型位控制命令通道状态机(CPSM)。
位31:15 保留,始终读为0
位14ATACMD:CE-ATA命令 (CE-ATA command)
如果设置该位,CPSM转至CMD61。
位13nIEN:不使能中断 (not interrupt enable)
如果未设置该位,则使能CE-ATA设备的中断。
位12ENCMDcompl:使能CMD完成 (Enable CMD completion)
如果设置该位,则使能命令完成信号。
位11SDIOSuspend:SD I/O暂停命令 (SD I/O suspend command)
如果设置该位,则将要发送的命令是一个暂停命令(只能用于SDIO卡)。
位10CPSMEN:命令通道状态机(CPSM)使能位 (Command path state machine (CPSM) Enable bit)
如果设置该位,则使能CPSM。
位9WAITPEND:CPSM等待数据传输结束(CmdPend内部信号) (CPSM Waits for ends of data transfer (CmdPend internal signal))
如果设置该位,则CPSM在开始发送一个命令之前等待数据传输结束。
位8WAITINT:CPSM等待中断请求(CPSM waits for interrupt request)
如果设置该位,则CPSM关闭命令超时控制并等待中断请求。
位7:6WAITRESP:等待响应位(Wait for response bits)
这2位指示CPSM是否需要等待响应,如果需要等待响应,则指示响应类型。00:无响应,期待CMDSENT标志01:短响应,期待CMDREND或CCRCFAIL标志10:无响应,期待CMDSENT标志11:长响应,期待CMDREND或CCRCFAIL标志
位5:0CMDINDEX:命令索引(Command index)
命令索引是作为命令的一部分发送到卡中。
注意:
写数据后的7个HCLK时钟周期内不能写入这个寄存器。 多媒体卡可以发送2种响应:48位长的短响应,或136位长的长响应。SD卡和SD I/O卡只能发送短响应,参数可以根据响应的类型而变化,软件将根据发送的命令区分响应的类型。CE-ATA设备只发送短响应。 [编辑]SDIO命令响应寄存器(SDIO_RESPCMD)
SDIO_RESPCMD寄存器包含最后收到的命令响应中的命令索引。如果传输的命令响应不包含命令索引(长响应或OCR响应),尽管它应该包含111111b(响应中的保留域值),但RESPCMD域的内容未知。
位31:6 保留,始终读为0
位5:0RESPCMD:响应的命令索引(Response command index)
只读位,包含最后收到的命令响应中的命令索引。 [编辑]SDIO响应1..4寄存器(SDIO_RESPx)
SDIO_RESP1/2/3/4寄存器包含卡的状态,即收到响应的部分信息。
位31:0CARDSTATUSx:见下表。
根据响应类型,卡的状态长度是32位或127位。(表) 响应类型和SDIO_RESPx寄存器总是先收到卡状态的最高位,SDIO_RESP3寄存器的最低位始终为0。 [编辑]SDIO数据定时器寄存器(SDIO_DTIMER)
SDIO_DTIMER寄存器包含以卡总线时钟周期为单位的数据超时时间。
一个计数器从SDIO_DTIMER寄存器加载数值,并在数据通道状态机(DPSM)进入Wait_R或繁忙状态时进行递减计数,当DPSM处在这些状态时,如果计数器减为0,则设置超时标志。
位31:0DATATIME:数据超时时间(Data timeout period)
以卡总线时钟周期为单位的数据超时时间。
注意:在写入数据控制寄存器进行数据传输之前,必须先写入数据定时器寄存器和数据长度寄存器。
[编辑]SDIO数据长度寄存器(SDIO_DLEN)
SDIO_DLEN寄存器包含需要传输的数据字节长度。当数据传输开始时,这个数值被加载到数据计数器中。
位31:25 保留,始终读为0。
位24:0DATALENGTH:数据长度(Data length value)
要传输的数据字节数目。
注意:对于块数据传输,数据长度寄存器中的数值必须是数据块长度(见SDIO_DCTRL)的倍数。在写入数据控制寄存器进行数据传输之前,必须先写入数据定时器寄存器和数据长度寄存器。
[编辑]SDIO数据控制寄存器(SDIO_DCTRL)
SDIO_DCTRL寄存器控制数据通道状态机(DPSM)。
位31:12 保留,始终读为0。
位11SDIOEN:SD I/O使能功能(SD I/O enable functions)
如果设置了该位,则DPSM执行SD I/O卡特定的操作。
位10RWMOD:读等待模式(Read wait mode)
0:停止SDIO_CK控制读等待;1:使用SDIO_D2控制读等待。
位9RWSTOP:读等待停止(Read wait stop)
0:如果设置了RWSTART,执行读等待;1:如果设置了RWSTART,停止读等待。
位8RWSTART:读等待开始(Read wait start)
设置该位开始读等待操作。
位7:4DBLOCKSIZE:数据块长度(Data block size)
当选择了块数据传输模式,该域定义数据块长度:0000:块长度 = 20 = 1字节; 1000:块长度 = 28 = 256字节;0001:块长度 = 21 = 2字节; 1001:块长度 = 29 = 512字节;0010:块长度 = 22 = 4字节; 1010:块长度 = 210 = 1024字节;0011:块长度 = 23 = 8字节; 1011:块长度 = 211 = 2048字节;0100:块长度 = 24 = 16字节; 1100:块长度 = 212 = 4096字节;0101:块长度 = 25 = 32字节; 1101:块长度 = 213 = 8192字节;0110:块长度 = 26 = 64字节; 1110:块长度 = 214 = 16384字节;0111:块长度 = 27 = 128字节; 1111:保留。
位3DMAEN:DMA使能位(DMA enable bit)
0:关闭DMA;1:使能DMA。
位2DTMODE:数据传输模式(Data transfer mode selection)
0:块数据传输;1:流数据传输。
位1DTDIR:数据传输方向(Data transfer direction selection)
0:控制器至卡;1:卡至控制器。
位0DTEN:数据传输使能位(Data transfer enabled bit)
如果设置该位为1,则开始数据传输。根据DTSIR方向位,DPSM进入Wait_S或Wait_R状态,如果在传输的一开始就设置了RWSTART位,则DPSM进入读等待状态。不需要在数据传输结束后清除使能位,但必须更改SDIO_DCTRL以允许新的数据传输。
注意:写数据后的7个HCLK时钟周期内不能写入这个寄存器。
[编辑]SDIO数据计数器寄存器(SDIO_DCOUNT)
当DPSM从空闲状态进入Wait_R或Wait_S状态时,SDIO_DCOUNT寄存器从数据长度寄存器加载数值(见SDIO_DLEN),在数据传输过程中,该计数器的数值递减直到减为0,然后DPSM进入空闲状态并设置数据状态结束标志DATAEND。
位31:25 保留,始终读为0。
位24:0DATACOUNT:数据计数数值(Data count value)
读这个寄存器时返回待传输的数据字节数,写这个寄存器无作用。
注意:只能在数据传输结束时读这个寄存器。
[编辑]SDIO状态寄存器(SDIO_STA)
SDIO_STA是一个只读寄存器,它包含两类标志:
静态标志(位[23:22、10:0]):保持为’1’,直到被清除 (见SDIO_ICR) 动态标志(位[21:11]):只取决于对应的硬件逻辑(例如:FIFO满和空标志变高或变低随FIFO的数据写入而变化)。
位31:24 保留,始终读为0。
位23CEATAEND:CMD61收到CE-ATA命令完成信号
位22SDIOIT:收到SDIO中断
位21RXDVAL:接收FIFO中的数据有效
位20TXDVAL:发送FIFO中的数据有效
位19RXFIFOE:接收FIFO空
位18TXFIFOE:发送FIFO空
若使用了硬件流控制,当FIFO包含2个字时,TXFIFOE信号变为有效。
位17RXFIFOF:接收FIFO满
若使用了硬件流控制,当FIFO还差2个字满时,RXFIFOF信号变为有效。
位16TXFIFOF:发送FIFO满
位15RXFIFOHF:接收FIFO半满:FIFO中至少还有8个字。
位14TXFIFOHE:发送FIFO半空:FIFO中至少还可以写入8个字。
位13RXACT:正在接收数据
位12TXACT:正在发送数据
位11CMDACT:正在传输命令
位10DBCKEND:已发送/接收数据块(CRC校验成功)
位9STBITERR:在宽总线模式下,在所有数据线上都没有检测到起始位
位8DATAEND:数据结束(数据计数器SDIO_DCOUNT = 0)
位7CMDSENT:已发送命令(不需要响应)
位6CMDREND:已收到命令响应(CRC校验成功)
位5RXOVERR:接收FIFO上溢错误
位4TXUNDERR:发送FIFO下溢错误
位3DTIMEOUT:数据超时
位2CTIMEOUT:命令响应超时
命令超时时间是一个固定的值,为64个SDIO_CK时钟周期。
位1DCRCFAIL:已发送/接收数据块(CRC校验失败)
位0CCRCFAIL:已收到命令响应(CRC校验失败)
[编辑]SDIO中断清除寄存器(SDIO_ICR)
SDIO_ICR是一个只写寄存器,读该寄存器将返回复位值。在对应寄存器位写’1’将清除SDIO_STA状态寄存器中的对应位。
位31:24 保留,始终读为0 位21:11 保留,始终读为0(对应于11个不可清除的动态标志)
[编辑]SDIO屏蔽寄存器(SDIO_MASK)
将对应位置’1’,SDIO_MASK中断屏蔽寄存器决定哪一个状态位产生中断。
位31:24 保留,始终读为0
[编辑]SDIO FIFO计数器寄存器(SDIO_FIFOCNT)
SDIO_FIFOCNT寄存器包含还未写入FIFO或还未从FIFO读出的数据字数目。当在数据控制寄存器(SDIO_DCTRL)中设置了数据 传输使能位DTEN,并且DPSM处于空闲状态时,FIFO计数器从数据长度寄存器(见SDIO_DLEN)加载数值。如果数据长度未与字对齐(4的倍 数),则最后剩下的1~3个字节被当成一个字处理。
位31:24 保留,始终读为0
位23:0FIFOCOUNT:还未写入FIFO或还未从FIFO读出的数据字数目。
[编辑]SDIO数据FIFO寄存器(SDIO_FIFO)
接收和发送FIFO是以32位宽度进行读写的一组寄存器,它包含32个地址连续的寄存器,CPU可以使用FIFO读写多个数据。
位31:0FIFODATA:接收的或发送的FIFO数据
FIFO数据占据32个32位的字,地址为:(SDIO基址 + 0x80) 至 (SDIO基址 + 0xFC) [编辑]SDIO数据结构 [编辑]SDIO初始化结构类型定义
typedef struct { uint32_t SDIO_ClockEdge; //指定位捕捉的时钟边沿 uint32_t SDIO_ClockBypass; //指定是否使能SDIO时钟分频器旁路 uint32_t SDIO_ClockPowerSave; //指定当总线空闲时,是否使能SDIO时钟输出 uint32_t SDIO_BusWide; //指定SDIO总线宽度 uint32_t SDIO_HardwareFlowControl; //指定是否使能SDIO硬件流控制 uint8_t SDIO_ClockDiv; //指定SDIO控制器的时钟分频系数(0x00~0xFF) } SDIO_InitTypeDef; /* SDIO_Clock_Edge用于设置NEGEDGE位(SDIO_CLKCR[13]) */ #define SDIO_ClockEdge_Rising ((uint32_t)0x00000000) #define SDIO_ClockEdge_Falling ((uint32_t)0x00002000) /* SDIO_ClockBypass用于设置BYPASS位(SDIO_CLKCR[10]) */ #define SDIO_ClockBypass_Disable ((uint32_t)0x00000000) #define SDIO_ClockBypass_Enable ((uint32_t)0x00000400) /* SDIO_ClockPowerSave用于设置PWRSAV位(SDIO_CLKCR[9]) */ #define SDIO_ClockPowerSave_Disable ((uint32_t)0x00000000) #define SDIO_ClockPowerSave_Enable ((uint32_t)0x00000200) /* SDIO_BusWide用于设置WIDBUS位(SDIO_CLKCR[12:11]) */ #define SDIO_BusWide_1b ((uint32_t)0x00000000) #define SDIO_BusWide_4b ((uint32_t)0x00000800) #define SDIO_BusWide_8b ((uint32_t)0x00001000) /* SDIO_HardWareFlowControl用于设置HWFC_EN位(SDIO_CLKCR[14]) */ #define SDIO_HardwareFlowControl_Disable ((uint32_t)0x00000000) #define SDIO_HardwareFlowControl_Enable ((uint32_t)0x00004000) /* SDIO_ClockDiv用于设置CLKDIV位(SDIO_CLKCR[7:0]) */
[编辑]SDIO命令初始化结构类型定义
typedef struct { uint32_t SDIO_Argument; //指定命令参数 uint32_t SDIO_CmdIndex; //指定命令索引 uint32_t SDIO_Response; //指定响应类型 uint32_t SDIO_Wait; //指定是否等待中断请求 uint32_t SDIO_CPSM; //指定是否使能命令通道状态机(CPSM) } SDIO_CmdInitTypeDef; /* SDIO_Argument用于设置SDIO_ARG寄存器 */ /* SDIO_CmdIndex用于设置CMDINDEX位(SDIO_CMD[5:0]) */ #define IS_SDIO_CMD_INDEX(INDEX) ((INDEX) < 0x40) /* SDIO_Response用于设置WAITRESP位(SDIO_CMD[7:6]) */ #define SDIO_Response_No ((uint32_t)0x00000000) #define SDIO_Response_Short ((uint32_t)0x00000040) #define SDIO_Response_Long ((uint32_t)0x000000C0) /* SDIO_Wait用于设置WAITPEND和WAITINT位(SDIO_CMD[9:8]) */ #define SDIO_Wait_No ((uint32_t)0x00000000) //不等待,允许超时 #define SDIO_Wait_IT ((uint32_t)0x00000100) //SDIO等待中断请求 #define SDIO_Wait_Pend ((uint32_t)0x00000200) //SDIO等待传输结束 /* SDIO_CPSM用于设置CPSMEN位(SDIO_CMD[10]) */ #define SDIO_CPSM_Disable ((uint32_t)0x00000000) #define SDIO_CPSM_Enable ((uint32_t)0x00000400)
[编辑]SDIO数据初始化结构类型定义
typedef struct { uint32_t SDIO_DataTimeOut; //指定数据超时时间 uint32_t SDIO_DataLength; //指定待传输的数据字节长度 uint32_t SDIO_DataBlockSize; //指定块传输的数据块长度 uint32_t SDIO_TransferDir; //指定数据传输方向 uint32_t SDIO_TransferMode; //指定数据传输模式 uint32_t SDIO_DPSM; //指定是否使能数据通道状态机(DPSM) } SDIO_DataInitTypeDef; /* SDIO_DataTimeOut用于设置SDIO_DTIMER寄存器 */ /* SDIO_DataLength用于设置DATALENGTH位(SDIO_DLEN[24:0]) */ #define IS_SDIO_DATA_LENGTH(LENGTH) ((LENGTH) <= 0x01FFFFFF) /* SDIO_DataBlockSize用于设置DBLOCKSIZE位(SDIO_DCTRL[7:4]) */ #define SDIO_DataBlockSize_1b ((uint32_t)0x00000000) #define SDIO_DataBlockSize_2b ((uint32_t)0x00000010) #define SDIO_DataBlockSize_4b ((uint32_t)0x00000020) #define SDIO_DataBlockSize_8b ((uint32_t)0x00000030) #define SDIO_DataBlockSize_16b ((uint32_t)0x00000040) #define SDIO_DataBlockSize_32b ((uint32_t)0x00000050) #define SDIO_DataBlockSize_64b ((uint32_t)0x00000060) #define SDIO_DataBlockSize_128b ((uint32_t)0x00000070) #define SDIO_DataBlockSize_256b ((uint32_t)0x00000080) #define SDIO_DataBlockSize_512b ((uint32_t)0x00000090) #define SDIO_DataBlockSize_1024b ((uint32_t)0x000000A0) #define SDIO_DataBlockSize_2048b ((uint32_t)0x000000B0) #define SDIO_DataBlockSize_4096b ((uint32_t)0x000000C0) #define SDIO_DataBlockSize_8192b ((uint32_t)0x000000D0) #define SDIO_DataBlockSize_16384b ((uint32_t)0x000000E0) /* SDIO_TransferDir用于设置DTDIR位(SDIO_DCTRL[1]) */ #define SDIO_TransferDir_ToCard ((uint32_t)0x00000000) #define SDIO_TransferDir_ToSDIO ((uint32_t)0x00000002) /* SDIO_TransferMode用于设置DTMODE位(SDIO_DCTRL[2]) */ #define SDIO_TransferMode_Block ((uint32_t)0x00000000) #define SDIO_TransferMode_Stream ((uint32_t)0x00000004) /* SDIO_DPSM用于设置DTEN位(SDIO_DCTRL[0]) */ #define SDIO_DPSM_Disable ((uint32_t)0x00000000) #define SDIO_DPSM_Enable ((uint32_t)0x00000001)
[编辑]SDIO库函数 [编辑]函数SDIO_Init
/** * 功能描述 根据SDIO_InitStruct中指定的参数初始化SDIO外设 * 输入参数 SDIO_InitStruct: 指向结构SDIO_InitTypeDef的指针,包含了SDIO外设的配置信息 * 返回值 无 */ void SDIO_Init(SDIO_InitTypeDef* SDIO_InitStruct) { uint32_t tmpreg = 0; /* 检查输入参数 */ assert_param(IS_SDIO_CLOCK_EDGE(SDIO_InitStruct->SDIO_ClockEdge)); assert_param(IS_SDIO_CLOCK_BYPASS(SDIO_InitStruct->SDIO_ClockBypass)); assert_param(IS_SDIO_CLOCK_POWER_SAVE(SDIO_InitStruct->SDIO_ClockPowerSave)); assert_param(IS_SDIO_BUS_WIDE(SDIO_InitStruct->SDIO_BusWide)); assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(SDIO_InitStruct->SDIO_HardwareFlowControl)); /*---------------------------- SDIO CLKCR 配置 ------------------------*/ /* 获取 SDIO CLKCR 的值 */ tmpreg = SDIO->CLKCR; /* 清除 CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN 位 */ tmpreg &= CLKCR_CLEAR_MASK; /* 根据 SDIO_ClockDiv 的值设置 CLKDIV 位 */ /* 根据 SDIO_ClockPowerSave 的值设置 PWRSAV 位 */ /* 根据 SDIO_ClockBypass 的值设置 BYPASS 位 */ /* 根据 SDIO_BusWide 的值设置 WIDBUS 位 */ /* 根据 SDIO_ClockEdge 的值设置 NEGEDGE 位 */ /* 根据 SDIO_HardwareFlowControl 的值设置 HWFC_EN 位 */ tmpreg |= (SDIO_InitStruct->SDIO_ClockDiv | SDIO_InitStruct->SDIO_ClockPowerSave | SDIO_InitStruct->SDIO_ClockBypass | SDIO_InitStruct->SDIO_BusWide | SDIO_InitStruct->SDIO_ClockEdge | SDIO_InitStruct->SDIO_HardwareFlowControl); /* 回写 SDIO CLKCR */ SDIO->CLKCR = tmpreg; }
[编辑]函数SDIO_ClockCmd
/** * 功能描述 使能或失能 SDIO 时钟 * 输入参数 NewState:SDIO 时钟的新状态 * 该参数可以是: * ENABLE * DISABLE * 返回值 无 */ void SDIO_ClockCmd(FunctionalState NewState) { /* 检查输入参数 */ assert_param(IS_FUNCTIONAL_STATE(NewState)); /* 根据 NewState 设置或清除 SDIO_CLKCR 的 CLKEN 位 */ *(__IO uint32_t *) CLKCR_CLKEN_BB = (uint32_t)NewState; }
[编辑]函数SDIO_SetPowerState
/** * 功能描述 设置控制器的电源状态 * 输入参数 SDIO_PowerState:电源状态的新状态 * 该参数可以使下列值之一: * SDIO_PowerState_OFF * SDIO_PowerState_ON * 返回值 无 */ void SDIO_SetPowerState(uint32_t SDIO_PowerState) { /* 检查输入参数 */ assert_param(IS_SDIO_POWER_STATE(SDIO_PowerState)); /* 清除当前的电源状态 */ SDIO->POWER &= PWR_PWRCTRL_MASK; /* 根据 SDIO_PowerState 关闭或打开SDIO电源 */ SDIO->POWER |= SDIO_PowerState; }
[编辑]函数SDIO_GetPowerState
/** * 功能描述 获取控制器的电源状态 * 输入参数 无 * 返回值 控制器的电源状态The returned value can * 该返回值可能是下列值之一: * - 0x00: 电源关闭 * - 0x02: 电源启动 * - 0x03: 电源打开 */ uint32_t SDIO_GetPowerState(void) { return (SDIO->POWER & (~PWR_PWRCTRL_MASK)); }
[编辑]函数SDIO_ITConfig
/** * 功能描述 使能或失能SDIO中断 * 输入参数 SDIO_IT: 指定待使能或失能的 SDIO 中断源 * 该参数可以是下列值之一或任意组合: * SDIO_IT_CCRCFAIL: 已收到命令响应(CRC校验失败)中断 * SDIO_IT_DCRCFAIL: 已发送/接收数据块(CRC校验失败)中断 * SDIO_IT_CTIMEOUT: 命令响应超时中断 * SDIO_IT_DTIMEOUT: 数据超时中断 * SDIO_IT_TXUNDERR: 发送 FIFO 下溢错误中断 * SDIO_IT_RXOVERR: 接收 FIFO 下溢错误中断 * SDIO_IT_CMDREND: 已收到命令响应(CRC校验成功)中断 * SDIO_IT_CMDSENT: 已发送命令(不需要响应)中断 * SDIO_IT_DATAEND: 数据结束(数据计数器SDIDCOUNT为0)中断 * SDIO_IT_STBITERR: 在宽总线模式下,在所有的数据线号上没有检测到起始位中断 * SDIO_IT_DBCKEND: 已发送/接收数据块(CRC校验成功)中断 * SDIO_IT_CMDACT: 正在传输命令中断 * SDIO_IT_TXACT: 正在发送数据中断 * SDIO_IT_RXACT: 正在接收数据中断 * SDIO_IT_TXFIFOHE: 发送 FIFO 半空中断 * SDIO_IT_RXFIFOHF: 接收 FIFO 半满中断 * SDIO_IT_TXFIFOF: 发送 FIFO 满中断 * SDIO_IT_RXFIFOF: 接收 FIFO 满中断 * SDIO_IT_TXFIFOE: 发送 FIFO 空中断 * SDIO_IT_RXFIFOE: 接收 FIFO 空中断 * SDIO_IT_TXDAVL: 发送 FIFO 中的数据有效中断 * SDIO_IT_RXDAVL: 接收 FIFO 中的数据有效中断 * SDIO_IT_SDIOIT: 收到 SD I/O 中断中断 * SDIO_IT_CEATAEND: CMD61 收到 CE-ATA 命令完成信号中断 * 输入参数 NewState: 指定的SDIO中断的新状态 * 该参数可以是: * ENABLE * DISABLE * 返回值 无 */ void SDIO_ITConfig(uint32_t SDIO_IT, FunctionalState NewState) { /* 检查输入参数 */ assert_param(IS_SDIO_IT(SDIO_IT)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* 使能 SDIO 中断 */ SDIO->MASK |= SDIO_IT; } else { /* 失能 SDIO 中断 */ SDIO->MASK &= ~SDIO_IT; } }
[编辑]函数SDIO_DMACmd
/** * 功能描述 使能或失能 SDIO DMA 请求 * 输入参数 NewState: 选择的 SDIO DMA 请求的新状态 * 该参数可以是: * ENABLE * DISABLE * 返回值 无 */ void SDIO_DMACmd(FunctionalState NewState) { /* 检查输入参数 */ assert_param(IS_FUNCTIONAL_STATE(NewState)); /* 根据 NewState 设置或清除 SDIO_CLKCR 的 DMAEN 位 */ *(__IO uint32_t *) DCTRL_DMAEN_BB = (uint32_t)NewState; }
[编辑]函数SDIO_SendCommand
/** * 功能描述 根据 SDIO_CmdInitStruct 中指定的参数初始化 SDIO 命令,并且发送命令 * 输入参数 SDIO_CmdInitStruct:指向结构 SDIO_CmdInitTypeDef 的指针,包含了SDIO命令的配置信息 * 返回值 无 */ void SDIO_SendCommand(SDIO_CmdInitTypeDef *SDIO_CmdInitStruct) { uint32_t tmpreg = 0; /* 检查输入参数 */ assert_param(IS_SDIO_CMD_INDEX(SDIO_CmdInitStruct->SDIO_CmdIndex)); assert_param(IS_SDIO_RESPONSE(SDIO_CmdInitStruct->SDIO_Response)); assert_param(IS_SDIO_WAIT(SDIO_CmdInitStruct->SDIO_Wait)); assert_param(IS_SDIO_CPSM(SDIO_CmdInitStruct->SDIO_CPSM)); /*---------------------------- SDIO 参数寄存器配置 ------------------------*/ /* 根据SDIO_Argument的值设置SDIO参数寄存器 */ SDIO->ARG = SDIO_CmdInitStruct->SDIO_Argument; /*---------------------------- SDIO 命令寄存器配置 ------------------------*/ /* 获取SDIO命令寄存器的值 */ tmpreg = SDIO->CMD; /* 清除 CMDINDEX, WAITRESP, WAITINT, WAITPEND, CPSMEN 位 */ tmpreg &= CMD_CLEAR_MASK; /* 根据 SDIO_CmdIndex 的值设置 CMDINDEX 位 */ /* 根据 SDIO_Response 的值设置 WAITRESP 位 */ /* 根据 SDIO_Wait 的值设置 WAITINT 和 WAITPEND 位 */ /* 根据 SDIO_CPSM 的值设置 CPSMEN 位 */ tmpreg |= (uint32_t)SDIO_CmdInitStruct->SDIO_CmdIndex | SDIO_CmdInitStruct->SDIO_Response | SDIO_CmdInitStruct->SDIO_Wait | SDIO_CmdInitStruct->SDIO_CPSM; /* 回写SDIO命令寄存器 */ SDIO->CMD = tmpreg; }
[编辑]函数SDIO_GetCommandResponse
/** * 功能描述 返回上一个收到响应的命令的命令索引 * 输入参数 无 * 返回值 返回上一个收到响应的命令的命令索引 */ uint8_t SDIO_GetCommandResponse(void) { return (uint8_t)(SDIO->RESPCMD); }
[编辑]函数SDIO_GetResponse
/** * 功能描述 返回上一个命令从卡收到的响应 * 输入参数 SDIO_RESP: 指定SDIO响应寄存器 * 该参数可以是下列值之一: * SDIO_RESP1: 响应寄存器 1 * SDIO_RESP2: 响应寄存器 2 * SDIO_RESP3: 响应寄存器 3 * SDIO_RESP4: 响应寄存器 4 * 返回值 对应的响应寄存器的值 */ uint32_t SDIO_GetResponse(uint32_t SDIO_RESP) { __IO uint32_t tmp = 0; /* 检查输入参数 */ assert_param(IS_SDIO_RESP(SDIO_RESP)); tmp = SDIO_RESP_ADDR + SDIO_RESP; return (*(__IO uint32_t *) tmp); }
[编辑]函数SDIO_DataConfig
/** * 功能描述 根据SDIO_DataInitStruct中指定的参数初始化SDIO数据通道 * 输入参数 SDIO_DataInitStruct: 指向结构SDIO_DataInitTypeDef的指针,包含了SDIO数据的配置信息 * 返回值 无 */ void SDIO_DataConfig(SDIO_DataInitTypeDef* SDIO_DataInitStruct) { uint32_t tmpreg = 0; /* 检查输入参数 */ assert_param(IS_SDIO_DATA_LENGTH(SDIO_DataInitStruct->SDIO_DataLength)); assert_param(IS_SDIO_BLOCK_SIZE(SDIO_DataInitStruct->SDIO_DataBlockSize)); assert_param(IS_SDIO_TRANSFER_DIR(SDIO_DataInitStruct->SDIO_TransferDir)); assert_param(IS_SDIO_TRANSFER_MODE(SDIO_DataInitStruct->SDIO_TransferMode)); assert_param(IS_SDIO_DPSM(SDIO_DataInitStruct->SDIO_DPSM)); /*---------------------------- SDIO 数据定时器配置 ---------------------*/ /* 设置SDIO数据超时时间 */ SDIO->DTIMER = SDIO_DataInitStruct->SDIO_DataTimeOut; /*---------------------------- SDIO 数据长度寄存器配置 -----------------------*/ /* 设置SDIO数据长度 */ SDIO->DLEN = SDIO_DataInitStruct->SDIO_DataLength; /*---------------------------- SDIO 数据控制寄存器配置 ----------------------*/ /* 获取SDIO 数据控制寄存器的值 */ tmpreg = SDIO->DCTRL; /* 清除 DEN, DTMODE, DTDIR 和 DBCKSIZE 位 */ tmpreg &= DCTRL_CLEAR_MASK; /* 根据SDIO_DPSM的值设置DEN位 */ /* 根据SDIO_TransferMode的值设置DTMODE位 */ /* 根据SDIO_TransferDir的值设置DTDIR位 */ /* 根据SDIO_DataBlockSize的值设置DBCKSIZE位 */ tmpreg |= (uint32_t)SDIO_DataInitStruct->SDIO_DataBlockSize | SDIO_DataInitStruct->SDIO_TransferDir | SDIO_DataInitStruct->SDIO_TransferMode | SDIO_DataInitStruct->SDIO_DPSM; /* 回写SDIO数据控制寄存器 */ SDIO->DCTRL = tmpreg; }
[编辑]函数SDIO_ReadData
/** * 功能描述 从接收FIFO读一个数据字 * 输入参数 无 * 返回值 收到的数据 */ uint32_t SDIO_ReadData(void) { return SDIO->FIFO; }
[编辑]函数SDIO_WriteData
/** * 功能描述 向发送FIFO写一个数据字 * 输入参数 Data: 要写的32位数据字 * 返回值 无 */ void SDIO_WriteData(uint32_t Data) { SDIO->FIFO = Data; }
[编辑]函数SDIO_GetFlagStatus
/** * 功能描述 检查指定的SDIO标志设置与否 * 输入参数 SDIO_FLAG: 指定待检查的SDIO标志 * 该参数可以是下列值之一: * SDIO_FLAG_CCRCFAIL: 命令响应已接收(CRC校验失败) * SDIO_FLAG_DCRCFAIL: 数据块已发送/接收(CRC校验失败) * SDIO_FLAG_CTIMEOUT: 命令响应超时 * SDIO_FLAG_DTIMEOUT: 数据超时 * SDIO_FLAG_TXUNDERR: 发送FIFO下溢错误 * SDIO_FLAG_RXOVERR: 接收FIFO上溢 * SDIO_FLAG_CMDREND: 命令响应已接收(CRC校验通过) * SDIO_FLAG_CMDSENT: 命令已发送(不需要响应) * SDIO_FLAG_DATAEND: 数据传输结束(数据计数器SDIDCOUNT为0) * SDIO_FLAG_STBITERR: 在宽总线模式下,所有数据线都没检测到起始位 * SDIO_FLAG_DBCKEND: 数据块已发送/接收(CRC校验通过) * SDIO_FLAG_CMDACT: 正在传输命令 * SDIO_FLAG_TXACT: 正在发送数据 * SDIO_FLAG_RXACT: 正在接收数据 * SDIO_FLAG_TXFIFOHE: 发送FIFO半空 * SDIO_FLAG_RXFIFOHF: 接收FIFO半满 * SDIO_FLAG_TXFIFOF: 发送FIFO满 * SDIO_FLAG_RXFIFOF: 接收FIFO满 * SDIO_FLAG_TXFIFOE: 发送FIFO空 * SDIO_FLAG_RXFIFOE: 接收FIFO空 * SDIO_FLAG_TXDAVL: 发送FIFO中的数据有效 * SDIO_FLAG_RXDAVL: 接收FIFO中的数据有效 * SDIO_FLAG_SDIOIT: SD I/O 中断已接收 * SDIO_FLAG_CEATAEND: CE-ATA命令CMD61的完成信号已接收 * 返回值 SDIO标志的状态(SET 或 RESET). */ FlagStatus SDIO_GetFlagStatus(uint32_t SDIO_FLAG) { FlagStatus bitstatus = RESET; /* 检查输入参数 */ assert_param(IS_SDIO_FLAG(SDIO_FLAG)); if ((SDIO->STA & SDIO_FLAG) != (uint32_t)RESET) { bitstatus = SET; } else { bitstatus = RESET; } return bitstatus; }
[编辑]函数SDIO_ClearFlag
/** * 功能描述 清除SDIO的挂起标志 * 输入参数 SDIO_FLAG: 指定待清除的标志 * 该参数可以是下列值之一: * SDIO_FLAG_CCRCFAIL: 命令响应已接收(CRC校验失败) * SDIO_FLAG_DCRCFAIL: 数据块已发送/接收(CRC校验失败) * SDIO_FLAG_CTIMEOUT: 命令响应超时 * SDIO_FLAG_DTIMEOUT: 数据超时 * SDIO_FLAG_TXUNDERR: 发送FIFO下溢错误 * SDIO_FLAG_RXOVERR: 接收FIFO上溢错误 * SDIO_FLAG_CMDREND: 命令响应已接收(CRC校验通过) * SDIO_FLAG_CMDSENT: 命令已发送(不需要响应) * SDIO_FLAG_DATAEND: 数据传输结束(数据计数器SDIDCOUNT为0) * SDIO_FLAG_STBITERR: 在宽总线模式下,所有数据线都没检测到起始位 * SDIO_FLAG_DBCKEND: 数据块已发送/接收(CRC校验通过) * SDIO_FLAG_SDIOIT: SD I/O 中断已接收 * SDIO_FLAG_CEATAEND: CE-ATA命令CMD61的完成信号已接收 * 返回值 无 */ void SDIO_ClearFlag(uint32_t SDIO_FLAG) { /* 检查输入参数 */ assert_param(IS_SDIO_CLEAR_FLAG(SDIO_FLAG)); SDIO->ICR = SDIO_FLAG; }
[编辑]函数SDIO_GetITStatus
/** * 功能描述 检查指定的SDIO中断是否已发生 * 输入参数 SDIO_IT: 指定待检查的SDIO中断 * 该参数可以是下列值之一: * SDIO_IT_CCRCFAIL: 命令响应已接收(CRC校验失败)中断 * SDIO_IT_DCRCFAIL: 数据块已发送/接收(CRC校验失败)中断 * SDIO_IT_CTIMEOUT: 命令响应超时中断 * SDIO_IT_DTIMEOUT: 数据超时中断 * SDIO_IT_TXUNDERR: 发送FIFO下溢错误中断 * SDIO_IT_RXOVERR: 接收FIFO上溢错误中断 * SDIO_IT_CMDREND: 命令响应已接收(CRC校验通过)中断 * SDIO_IT_CMDSENT: 命令已发送(不需要响应)中断 * SDIO_IT_DATAEND: 数据传输结束(数据计数器SDIDCOUNT为0)中断 * SDIO_IT_STBITERR: 在宽总线模式下,所有数据线都没检测到起始位中断 * SDIO_IT_DBCKEND: 数据块已发送/接收(CRC校验通过)中断 * SDIO_IT_CMDACT: 正在传输命令中断 * SDIO_IT_TXACT: 正在发送数据中断 * SDIO_IT_RXACT: 正在接收数据中断 * SDIO_IT_TXFIFOHE: 发送FIFO半空中断 * SDIO_IT_RXFIFOHF: 接收FIFO半满中断 * SDIO_IT_TXFIFOF: 发送FIFO满中断 * SDIO_IT_RXFIFOF: 接收FIFO满中断 * SDIO_IT_TXFIFOE: 发送FIFO空中断 * SDIO_IT_RXFIFOE: 接收FIFO空中断 * SDIO_IT_TXDAVL: 发送FIFO中的数据有效中断 * SDIO_IT_RXDAVL: 接收FIFO中的数据有效中断 * SDIO_IT_SDIOIT: SD I/O 中断已接收中断 * SDIO_IT_CEATAEND: CE-ATA命令CMD61的完成信号已接收中断 * 返回值 SDIO_IT的新状态(SET 或 RESET). */ ITStatus SDIO_GetITStatus(uint32_t SDIO_IT) { ITStatus bitstatus = RESET; /* 检查输入参数 */ assert_param(IS_SDIO_GET_IT(SDIO_IT)); if ((SDIO->STA & SDIO_IT) != (uint32_t)RESET) { bitstatus = SET; } else { bitstatus = RESET; } return bitstatus; }
[编辑]函数SDIO_ClearITPendingBit
/** * 功能描述 清除SDIO的中断挂起位 * 输入参数 SDIO_IT: 指定待清除的中断挂起位 * 该参数可以是下列值的一个或任意组合: * SDIO_IT_CCRCFAIL: 命令响应已接收(CRC校验失败)中断 * SDIO_IT_DCRCFAIL: 数据块已发送/接收(CRC校验失败)中断 * SDIO_IT_CTIMEOUT: 命令响应超时中断 * SDIO_IT_DTIMEOUT: 数据超时中断 * SDIO_IT_TXUNDERR: 发送FIFO下溢错误中断 * SDIO_IT_RXOVERR: 接收FIFO上溢错误中断 * SDIO_IT_CMDREND: 命令响应已接收(CRC校验通过)中断 * SDIO_IT_CMDSENT: 命令已发送(不需要响应)中断 * SDIO_IT_DATAEND: 数据传输结束(数据计数器SDIDCOUNT为0)中断 * SDIO_IT_STBITERR: 在宽总线模式下,所有数据线都没检测到起始位中断 * SDIO_IT_SDIOIT: SD I/O 中断已接收中断 * SDIO_IT_CEATAEND: CE-ATA命令CMD61的完成信号已接收中断 * 返回值 无 */ void SDIO_ClearITPendingBit(uint32_t SDIO_IT) { /* 检查输入参数 */ assert_param(IS_SDIO_CLEAR_IT(SDIO_IT)); SDIO->ICR = SDIO_IT; }
[编辑]SDIO实例 SDIO实例分析 [编辑]系统结构设计
[编辑]程序设计分析 [编辑]程序流程图
[编辑]代码实现及分析
上代码,初始化代码
[编辑]实验操作及现象 使用Jlink或者Wiggler下载编译后生成的.hex文件在没有插入SD卡的情况下,LED0是熄灭的当正确插入SD卡后,LED0立即点亮