本文主要是介绍使用MCU的 GPIO口 模拟SDIO时序读写TF/SD卡的可能性。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
SD2.0协议详解:命令格式、初始化/读取/写入 - WangXuan的文章 - 知乎
https://zhuanlan.zhihu.com/p/610495260
参考上述与其它理解,若使用GPIO口模拟,重点与难点:
1. 时钟线问题:
在SD准备期间,需不间断一直发送频率为100kHz- 400kHz的时钟 以让SD卡初始化,在初始化完成后,时钟频率为0-25MHZ,此要求意味着:
在空闲时:需由PWM或定时器产生需要的持续时钟(初始化完成后应该可以停止了),
在工作时:暂停此时钟并使用GPIO模拟,工作完成后继续此时钟(初始化完成后应该可以关闭,但未验证)。
2. 校验码问题:
CMD线和每根DAT线,自身独立产生校验码,CMD线为CRC7, DAT线为CRC16,此要求
(1. 在写 CMD上时问题不大,写入前先计算好后一次性写入。
(2. 在读SD卡时返回时,若简化设计,可选择忽略。
(3.在向SD写入时,将产生一定的计算量,以4线为例每线为1024位,共512*8=4096位。
3. 其它:
(1. 模拟时,CMD的起始+方向+指令共6字节,可看作为一个字节,校验7位+停止位看作最后一字节。
2. 描述中的由host→card共6位指令的“CMDn”,中的n对应0-63,为标准指令,后跟对应32位数据。
3. 描述中的响应 (response) 即从 card 到 host,用"R1-7“表示,CMDn与之有对应关系见相关手册。格式同CMDn,但R2例外有共136bit。
物理IO层结构设计:
考虑到一个应用绝大多数情况只有一个SD卡即一条SDIO总线,故直接单例化设计以提高效率
1. 内部主要函数功能设计:(位于 SDIO_Soft.c中, 仅支持4线DAT模式)
_IoInit(): 初始化Clk线为输出,其它线为输入上拉。
_SetClk(HZ): 用于配置CLK为指定频率,需用PWM或定时器翻转IO实现
_OnClk(): 开始输出固定频率到Clk线上
_OffClk(): 关闭Clk
_NoneClk(U8): 发送指定个数据时钟,其它位不操作。
_Sendmd(u8 Cmd): 发送8位指令
_RcvCmd(u8 BitCount): 接收指定位应答入接收指令缓冲,返回收到位数长度
_SendData(u8只读指针,u16数据个数): 发送指定数据到4线dat上。
_RcvData(8只读指针,u16数据个数): 从4线dat上接收指定数据个数,内部可选接收期间同时收应答指令(放入接收指令缓冲中)。
2. 对外统一函数接口 SDIO.h
设计为SDIO操作的通用接口,对其它MCU的SDIO硬件可封装为此接口以方便上层操作。
SDIO_Init():初始化IO,开启时钟等。
SDIO_Cmd(u8指令, u32数据,u8前置),发送指令,此函数内部计算好校验码后依次发出,在U8指令信息的b7置位时,接收响应,接收的响应保存入SDIO单例化结构中。返回0正确,其它为错误码
SDIO_RdBlock(u8可写数据指针): 上层在带读数据的指令发出后,立即调用此函数读入一块数据,长度固定为512,注意多收尾部的校验码。返回0正确,其它为错误码
SDIO_WrBlock(u8只读数据指针): 上层在带写数据的指令发出后,立即调用此函数写出一块数据,长度固定为512,在内部提交计算好CRC16校验码,在尾部发出。返回0正确,其它为错误码
其它函数: 为可选, 仅硬件实现的SDIO支持,如:DMA, 读写多块等。
这篇关于使用MCU的 GPIO口 模拟SDIO时序读写TF/SD卡的可能性。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!