开发板原理图设计
[编辑] SDIO[编辑] SDIO原理[编辑] SDIO简介SD/SDIO MMC卡主机模块(SDIO)在AHB外设总线和多媒体卡(MMC)、SD存储卡、SDIO卡和CE-ATA设备间提供了一个操作接口。 关于多媒体卡的详细描述,可参见MMCA技术委员会发布的多媒体卡系统规范(多媒体卡协会网站http://www./)。 SDIO的主要特性如下:
注:
多媒体卡/SD总线将所有卡与控制器相连。 当前版本的SDIO在同一时间里只能支持一个SD/SDIO/MMC 4.2的卡,但可以支持多个MMC版本4.1或以前版本的卡。 SDIO总线的通信是基于命令和数据的传输。 [编辑] SDIO功能描述SDIO包含2个部分:
复位后默认情况下SDIO_D0用于数据传输。初始化后主机可以改变数据总线的宽度。 SDIO_CMD有两种操作模式:
SDIO_CK是卡的时钟:每个时钟周期在命令和数据线上传输1位命令或数据。对于MMC V3.31协议,时钟频率可达20MHz;对于MMC V4.0/4.2协议,时钟频率可达48MHz;对于SD或SD I/O卡,时钟频率可达25MHz。
下表适用于多媒体卡/SD/SD I/O卡总线: [编辑] SDIO适配器SDIO适配器是多媒体/加密数字存储卡总线的主设备(主机),用于连接一组多媒体卡或一个加密数字存储卡,它包含以下5个部分:
注意:适配器寄存器和FIFO使用AHB总线一侧的时钟(HCLK/2),控制单元、命令通道和数据通道使用SDIO适配器一侧的时钟(SDIOCLK)。 [编辑] 适配器寄存器模块适配器寄存器模块包含所有系统寄存器。该模块还产生清除多媒体卡中静态标志的信号,当在SDIO清除寄存器中的相应位写’1’时会产生清除信号。 [编辑] 控制单元控制单元包含电源管理功能和为存储器卡提供的时钟分频。
上图为控制单元的框图,包括电源管理和时钟管理子单元。
[编辑] 命令通道命令通道单元向卡发送命令并从卡接收响应。
当写入命令寄存器并设置了使能位,开始发送命令。命令发送完成时,命令通道状态机(CPSM)设置状态标志并在不需要响应时进入空闲状态,在需要响应时,则等待响应(见下图)。当收到响应后,接收到的CRC码将会与内部产生的CRC码比较,然后设置相应的状态标志。 当进入等待(Wait)状态时,命令定时器开始运行;在CPSM进入接收(Receive)状态之前,如果产生了超时,则设置超时标志并进入空闲(Idle)状态。
命令:命令是用于开始一项操作。主机向一个指定的卡或所有的卡发出带地址的命令或广播命令(广播命令只适合于MMC
V3.31或之前的版本)。命令在CMD线上串行传送。所有命令的长度固定为48位,下表给出了多媒体卡、SD存储卡和SDIO卡上一般的命令格式。
CE-ATA命令是MMC V4.2命令的扩充,所以具有相同的格式。 命令通道操作于半双工模式,这样命令和响应可以分别发送和接收。如果CPSM不处在发送状态,SDIO_CMD输出处于高阻状态,如上图所示。SDIO_CMD上的数据与SDIO_CK的上升沿同步。 响应:响应是由一个被指定地址的卡发送到主机,对于MMC V3.31或以前版本所有的卡同时发送响应;响应是对先前接收到命令的一个应答。响应在CMD线上串行传送。
注:如果响应不包含CRC(如CMD1的响应),设备驱动应该忽略CRC失败状态。 命令寄存器包含命令索引(发至卡的6位)和命令类型;这决定了命令本身是否需要响应和响应的类型(48位还是136位)。下表列出了命令通道中的状态标志:
计算CRC码之前所有位的CRC校验和,包括开始位、发送位、命令索引和命令参数(或卡状态)。对于长响应格式,CRC校验和计算的是CID或CSD的前120位;注意,长响应格式中的开始位、传输位和6个保留位不参与CRC计算。
[编辑] 数据通道数据通道子单元在主机与卡之间传输数据。下图是数据通道的框图。 在时钟控制寄存器中可以配置卡的数据总线宽度。如果选择了4位总线模式,则每个时钟周期四条数据信号线(SDIO_D[3:0])上将传输
4位数据;如果选择了8位总线模式,则每个时钟周期八条数据信号线(SDIO_D[7:0])上将传输8位数据;如果没有选择宽总线模式,则每个时钟周期
只在SDIO_D0上传输1位数据。
DPSM工作频率为SDIO_CK,卡总线信号线上的数据与SDIO_CK的上升沿同步。DPSM有6个状态,如下图所示:
注:DPSM会在Wait_S状态保持至少2个时钟周期,以满足NWR的时序要求,NWR是接收到卡的响应至主机开始数据传输的间隔。
数据FIFO(先进先出)子单元是一个具有发送和接收单元的数据缓冲区。
当使能了SDIO的发送功能,数据可以通过AHB接口写入发送FIFO。
当数据通道子单元接收到一个数据字,它会把数据写入FIFO,写操作结束后,写指针自动加一;在另一端,有一个读指针始终指向FIFO中的当前数
据。如果关闭了接收FIFO,所有的状态标志均被清除,读写指针也被复位。当接收到数据时,数据通道子单元设置RXACT。下表列出了接收FIFO的状态
标志。通过32个连续的地址可以访问接收FIFO。 [编辑] SDIO AHB接口AHB接口产生中断和DMA请求,并访问SDIO适配器寄存器和数据FIFO。它包含一个数据通道、寄存器译码器和中断/DMA控制逻辑。 [编辑] SDIO中断当至少有一个选中的状态标志为高时,中断控制逻辑产生中断请求。有一个屏蔽寄存器用于选择可以产生中断的条件,如果设置了相应的屏蔽标志,则对应的状态标志可以产生中断。 [编辑] SDIO/DMA接口:SDIO和存储器之间数据传输的过程在下面的例子中,使用CMD24(WRITE_BLOCK)从SDIO主控制器传送512字节到MMC卡。DMA控制器用于从存储器向SDIO的FIFO填充数据。
[编辑] SDIO寄存器描述下表列出了SDIO寄存器地址映射。必须以字(32位)的方式访问这些外设寄存器。 [编辑] SDIO电源控制寄存器(SDIO_POWER)位31:2 保留,始终读为0。
注意:写数据后的7个HCLK时钟周期内,不能写入这个寄存器。 [编辑] SDIO时钟控制寄存器(SDIO_CLKCR)位31:15 保留,始终读为0。 位14 HWFC_EN:硬件流控制使能(HW Flow Control enable)
位13 NEGEDGE:SDIO_CK相位选择位(SDIO_CK dephasing selection bit)
位12:11 WIDBUS:宽总线模式使能位(Wide bus mode enable bit)
位10 BYPASS:时钟分频器旁路使能位(Clock divider bypass enable bit)
位9 PWRSAV:省电配置位(Power saving configuration bit)
位8 CLKEN:时钟使能位(Clock enable bit)
位7:0 CLKDIV:时钟分频系数(Clock divide factor)
[编辑] SDIO参数寄存器(SDIO_ARG)SDIO_ARG寄存器包含32位命令参数,它将作为命令的一部分发送到卡中。 位31:0 CMDARG:命令参数 (Command argument)
[编辑] SDIO命令寄存器(SDIO_CMD)SDIO_CMD寄存器包含命令索引和命令类型位。命令索引是作为命令的一部分发送到卡中。命令类型位控制命令通道状态机(CPSM)。 位31:15 保留,始终读为0 位14 ATACMD:CE-ATA命令 (CE-ATA command)
位13 nIEN:不使能中断 (not interrupt enable)
位12 ENCMDcompl:使能CMD完成 (Enable CMD completion)
位11 SDIOSuspend:SD I/O暂停命令 (SD I/O suspend command)
位10 CPSMEN:命令通道状态机(CPSM)使能位 (Command path state machine (CPSM) Enable bit)
位9 WAITPEND:CPSM等待数据传输结束(CmdPend内部信号) (CPSM Waits for ends of data transfer (CmdPend internal signal))
位8 WAITINT:CPSM等待中断请求(CPSM waits for interrupt request)
位7:6 WAITRESP:等待响应位(Wait for response bits)
位5:0 CMDINDEX:命令索引(Command index)
注意:
[编辑] SDIO命令响应寄存器(SDIO_RESPCMD)SDIO_RESPCMD寄存器包含最后收到的命令响应中的命令索引。如果传输的命令响应不包含命令索引(长响应或OCR响应),尽管它应该包含111111b(响应中的保留域值),但RESPCMD域的内容未知。 位31:6 保留,始终读为0 位5:0 RESPCMD:响应的命令索引(Response command index)
[编辑] SDIO响应1..4寄存器(SDIO_RESPx)SDIO_RESP1/2/3/4寄存器包含卡的状态,即收到响应的部分信息。 位31:0 CARDSTATUSx:见下表。
[编辑] SDIO数据定时器寄存器(SDIO_DTIMER)SDIO_DTIMER寄存器包含以卡总线时钟周期为单位的数据超时时间。 位31:0 DATATIME:数据超时时间(Data timeout period)
注意:在写入数据控制寄存器进行数据传输之前,必须先写入数据定时器寄存器和数据长度寄存器。 [编辑] SDIO数据长度寄存器(SDIO_DLEN)SDIO_DLEN寄存器包含需要传输的数据字节长度。当数据传输开始时,这个数值被加载到数据计数器中。 位31:25 保留,始终读为0。 位24:0 DATALENGTH:数据长度(Data length value)
注意:对于块数据传输,数据长度寄存器中的数值必须是数据块长度(见SDIO_DCTRL)的倍数。在写入数据控制寄存器进行数据传输之前,必须先写入数据定时器寄存器和数据长度寄存器。 [编辑] SDIO数据控制寄存器(SDIO_DCTRL)位31:12 保留,始终读为0。 位11 SDIOEN:SD I/O使能功能(SD I/O enable functions)
位10 RWMOD:读等待模式(Read wait mode)
位9 RWSTOP:读等待停止(Read wait stop)
位8 RWSTART:读等待开始(Read wait start)
位7:4 DBLOCKSIZE:数据块长度(Data block size)
位3 DMAEN:DMA使能位(DMA enable bit)
位2 DTMODE:数据传输模式(Data transfer mode selection)
位1 DTDIR:数据传输方向(Data transfer direction selection)
位0 DTEN:数据传输使能位(Data transfer enabled bit)
注意:写数据后的7个HCLK时钟周期内不能写入这个寄存器。 [编辑] SDIO数据计数器寄存器(SDIO_DCOUNT)当DPSM从空闲状态进入Wait_R或Wait_S状态时,SDIO_DCOUNT寄存器从数据长度寄存器加载数值(见SDIO_DLEN),在数据传输过程中,该计数器的数值递减直到减为0,然后DPSM进入空闲状态并设置数据状态结束标志DATAEND。 位31:25 保留,始终读为0。 位24:0 DATACOUNT:数据计数数值(Data count value) 读这个寄存器时返回待传输的数据字节数,写这个寄存器无作用。 注意:只能在数据传输结束时读这个寄存器。 [编辑] SDIO状态寄存器(SDIO_STA)SDIO_STA是一个只读寄存器,它包含两类标志:
位31:24 保留,始终读为0。
位17 RXFIFOF:接收FIFO满
位16 TXFIFOF:发送FIFO满
位1 DCRCFAIL:已发送/接收数据块(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 [编辑] SDIO数据FIFO寄存器(SDIO_FIFO)接收和发送FIFO是以32位宽度进行读写的一组寄存器,它包含32个地址连续的寄存器,CPU可以使用FIFO读写多个数据。 位31:0 FIFODATA:接收的或发送的FIFO数据
[编辑] 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实例[编辑] 系统结构设计[编辑] 程序设计分析[编辑] 程序流程图[编辑] 代码实现及分析上代码,初始化代码 [编辑] 实验操作及现象
|
|