[color=rgba(0, 0, 0, 0.74902)]其实前面关于SDIO寄存器的讲解已经比较详细了,这里再借助于关于SDIO结构体再进行总结一遍。
[color=rgba(0, 0, 0, 0.74902)]标准库函数对 SDIO 外设建立了三个初始化结构体,分别为 SDIO 初始化结构体SDIO_InitTypeDef、SDIO 命令初始化结构体 SDIO_CmdInitTypeDef 和 SDIO 数据初始化结
构体 SDIO_DataInitTypeDef。这些结构体成员用于设置 SDIO 工作环境参数,并由 SDIO 相应初始化配置函数或功能函数调用,这些参数将会被写入到 SDIO 相应的寄存器,达到配置 SDIO 工作环境的目的。
构体 SDIO_DataInitTypeDef。这些结构体成员用于设置 SDIO 工作环境参数,并由 SDIO 相应初始化配置函数或功能函数调用,这些参数将会被写入到 SDIO 相应的寄存器,达到配置 SDIO 工作环境的目的。
[color=rgba(0, 0, 0, 0.74902)]至于为什么需要一个命令结构体与数据结构体,就是为了方便我们配置SDIO关于寄存器位,因为发送命令或者数据需要很多参数配置。
1.SDIO初始化结构体[color=rgba(0, 0, 0, 0.74902)]SDIO 初始化结构体用于配置 SDIO 基本工作环境,比如时钟分频、时钟沿、数据宽度等等。它被 SDIO_Init 函数使用。
1) SDIO_ClockEdge:主时钟 SDIOCLK 产生 CLK 引脚时钟有效沿选择,可选上升沿或下降沿。
2) SDIO_ClockBypass:时钟分频旁路使用,可选使能或禁用,如果使能旁路,SDIOCLK (72MHZ )直接驱动 CLK 线输出时钟(不满足最高25HZ的要求),如果禁用,使用 SDIO_CLKCR 寄存器的 CLKDIV 位值分频 SDIOCLK,然后输出到 CLK 线。一般选择禁用时钟分频旁路。

1) SDIO_ClockEdge:主时钟 SDIOCLK 产生 CLK 引脚时钟有效沿选择,可选上升沿或下降沿。

2) SDIO_ClockBypass:时钟分频旁路使用,可选使能或禁用,如果使能旁路,SDIOCLK (72MHZ )直接驱动 CLK 线输出时钟(不满足最高25HZ的要求),如果禁用,使用 SDIO_CLKCR 寄存器的 CLKDIV 位值分频 SDIOCLK,然后输出到 CLK 线。一般选择禁用时钟分频旁路。

[color=rgba(0, 0, 0, 0.74902)]3) SDIO_ClockPowerSave:节能模式选择,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 PWRSAV 位的值。如果使能节能模式,CLK 线只有在总线激活时才有时钟输出;如果禁用节能模式,始终使能 CLK 线输出时钟。

[color=rgba(0, 0, 0, 0.74902)]4) SDIO_BusWide:数据线宽度选择,可选 1 位数据总线、4 位数据总线或 8 为数据总线,系统默认使用 1 位数据总线,操作 SD 卡时在数据传输模式下一般选择 4 位数据总线。它设定 SDIO_CLKCR 寄存器的 WIDBUS 位的值。
[color=rgba(0, 0, 0, 0.74902)]

[color=rgba(0, 0, 0, 0.74902)]5) SDIO_HardwareFlowControl:硬件流控制选择,可选使能或禁用,它设定SDIO_CLKCR 寄存器的 HWFC_EN 位的值。硬件流控制功能可以避免 FIFO 发送上溢和下溢错误。
6) SDIO_ClockDiv:时钟分频系数,它设定 SDIO_CLKCR 寄存器的 CLKDIV 位的值,设置 SDIOCLK 与 CLK 线输出时钟分频系数:
CLK 线时钟频率=SDIOCLK/([CLKDIV+2])。

6) SDIO_ClockDiv:时钟分频系数,它设定 SDIO_CLKCR 寄存器的 CLKDIV 位的值,设置 SDIOCLK 与 CLK 线输出时钟分频系数:
CLK 线时钟频率=SDIOCLK/([CLKDIV+2])。
[color=rgba(0, 0, 0, 0.74902)]
2.SDIO命令初始化结构体
[color=rgba(0, 0, 0, 0.74902)]
1) SDIO_Argument:作为命令的一部分发送到卡的命令参数,它设定 SDIO 参数寄存器(SDIO_ARG)的值。

1) SDIO_Argument:作为命令的一部分发送到卡的命令参数,它设定 SDIO 参数寄存器(SDIO_ARG)的值。
[color=rgba(0, 0, 0, 0.74902)]
(2) SDIO_CmdIndex:命令号选择,它设定 SDIO 命令寄存器(SDIO_CMD)的 CMDINDEX位的值。

(2) SDIO_CmdIndex:命令号选择,它设定 SDIO 命令寄存器(SDIO_CMD)的 CMDINDEX位的值。

[color=rgba(0, 0, 0, 0.74902)](3) SDIO_Response:响应类型,SDIO 定义两个响应类型:长响应和短响应。根据命令号选择对应的响应类型。SDIO 定义了四个 32 位的 SDIO 响应寄存器(SDIO_RESPx,x=1…4),短响应只用SDIO_RESP1,长响应使用4个(SDIO_RESPx,x=1…4)。

[color=rgba(0, 0, 0, 0.74902)]1)命令响应寄存器
2)SDIO响应寄存器1~4

2)SDIO响应寄存器1~4

[color=rgba(0, 0, 0, 0.74902)]4) SDIO_Wait:等待类型选择,有三种状态可选,一种是无等待状态,超时检测功能启动,一种是等待中断,另外一种是等待传输完成。

[color=rgba(0, 0, 0, 0.74902)]5) SDIO_CPSM:命令路径状态机控制,可选使能或禁用 CPSM。它设定 SDIO_CMD 寄存器的 CPSMEN 位的值

[color=rgba(0, 0, 0, 0.74902)]只要我们使能的了命令状态机,则下面发送命令和接收响应的过程中的状态转换就不用我们管了

[color=rgba(0, 0, 0, 0.74902)]当我们要发送命令,我们只需要配置这个命令初始化结构体的成员,然后调用下图这个函数,则我们配置的参数写入对应的寄存器位中。
3.SDIO数据初始化结构体
[color=rgba(0, 0, 0, 0.74902)]
1) SDIO_DataTimeOut:设置数据传输以卡总线时钟周期表示的超时周期,它设定 SDIO数据定时器寄存器(SDIO_DTIMER)的值。在 DPSM 进入 Wait_R 或繁忙状态后开始递减,直到 0 还处于以上两种状态则将超时状态标志置 1(详情前面的数据通道小节)。

1) SDIO_DataTimeOut:设置数据传输以卡总线时钟周期表示的超时周期,它设定 SDIO数据定时器寄存器(SDIO_DTIMER)的值。在 DPSM 进入 Wait_R 或繁忙状态后开始递减,直到 0 还处于以上两种状态则将超时状态标志置 1(详情前面的数据通道小节)。

[color=rgba(0, 0, 0, 0.74902)]2) SDIO_DataLength:设置传输数据长度。

[color=rgba(0, 0, 0, 0.74902)]3) SDIO_DataBlockSize:设置数据块大小,有多种尺寸可选,不同命令要求的数据块可能不同。
4) SDIO_TransferDir:数据传输方向,可选从主机到卡的写操作,或从卡到主机的读操作。

4) SDIO_TransferDir:数据传输方向,可选从主机到卡的写操作,或从卡到主机的读操作。
[color=rgba(0, 0, 0, 0.74902)]

[color=rgba(0, 0, 0, 0.74902)]5) SDIO_TransferMode:数据传输模式,可选数据块或数据流模式。对于 SD 卡操作使用数据块类型。

[color=rgba(0, 0, 0, 0.74902)]6) SDIO_DPSM:数据路径状态机控制,可选使能或禁用 DPSM。它设定 SDIO_DCTRL寄存器的 DTEN 位的值。要实现数据传输都必须使能 SDIO_DPSM。
与命令一样使能了数据路径状态机,就不用高那么多麻烦的状态转换了
八.SD卡读写测试实验
与命令一样使能了数据路径状态机,就不用高那么多麻烦的状态转换了
[color=rgba(0, 0, 0, 0.74902)]我们平时使用的SD 卡都是已经包含有文件系统的,一般不会使用本实验的操作方式读写 SD 卡,但是对学习SD卡的驱动原理非常重要!!!
[color=rgba(0, 0, 0, 0.74902)]本实验是进行 SD卡最底层的数据读写操作,直接使用 SDIO 对 SD 卡进行读写,会损坏 SD 卡的文件系统,导致数据丢失,所以做这个实验之前需要备份SD卡数据。
[color=rgba(0, 0, 0, 0.74902)]主要是学习SD卡的卡识别过程,以及数据传输工过程,其实就是完全依照前面的两个流程图来实现代码的。
[color=rgba(0, 0, 0, 0.74902)]卡识别模式流程图
数据传输流程图
1.硬件设计
数据传输流程图

[color=rgba(0, 0, 0, 0.74902)]原理图:
[color=rgba(0, 0, 0, 0.74902)]
实物图:

实物图:

[color=rgba(0, 0, 0, 0.74902)]我这里用的是CS创世的贴片式SD卡,也称之为SD NAND , 内部存储单元架构为SLC,适合存代码。直接上板时相比于拔插式SD卡在抗震和抗PIN氧化方面更有优势,对于缩小整板体积也有一定帮助。
[color=rgba(0, 0, 0, 0.74902)]
2.代码讲解
[color=rgba(0, 0, 0, 0.74902)]先看主函数:

[color=rgba(0, 0, 0, 0.74902)]

[color=rgba(0, 0, 0, 0.74902)]SD_Terst函数:
我们主要讲解的就是SD卡的初始化
SD_Init()函数:
/**
我们主要讲解的就是SD卡的初始化

SD_Init()函数:
* 函数名:SD_Init
* 描述:初始化SD卡,使卡处于就绪状态(准备传输数据)
* 输入:无
* 输出:-SD_Error SD卡错误代码
* 成功时则为 SD_OK
* 调用:外部调用
*/SD_Error SD_Init(void){