编写程序之前,需要对SD卡有一个了解,建议先搜搜网上各种牛人的笔记,然后去看官方的SD卡资料,这样理解起来比较容易(https://www.sdcard.org/home/ 官网)。在查找文档之前,需要选择适合自己SD卡的文档,因为卡有不同的版本,不同大小的存储量的SD卡支持的命令不同,比如有的SD卡支持COM1命令,有的却不支持。
总结了2G以下SD卡的初始化(SPI mode),如下:
首先说明一下,网上大多数的人说初始化的时钟频率要低于400KHZ(为了兼容MMC卡),正式读写可以达到25M,但是实际证明我的1G卡初始化的频率可以跑到5M,可能是现在的SD卡的协议有变。
1. 上电后,给SD卡一段时间的准备时间,例如50us(相对于FPGA,对于MCU,就不必要了,因为速度本身很慢);
2. 在片选无效的情况下发送至少74clks(本人建议发送104clks);
3. 发送CMD0(复位SD卡),接下来的8clks(片选有效)接收SD返回来的数据,如果是8’hff,继续接收(合理设定一个最大接收次数,超过了就重新发送CMD0);如果不是8’hff,分两种情况(1)接收的是8’h01,务必发送8clks(片选无效,让SD完成内部没有完成的操作),然后可以接下去发送下一个命令(2)接收的不是8‘h01,重新发送CMD0 (下面几个命令和CMD0的操作流程差不多);
4. 发送CMD55,情况和CMD0一样,SD卡的返回值也是8’h01;
5. 发送ACMD41,理想情况是要接收到8’h00,如果接收到的是8’h01或者接收的次数超过了设定值,返回第四步;
6. 到这里SD卡就初始化完成了,接下来就可以发送读写相关命令了,例如发送CMD16设置读写块的大小(例如设定为512个字节,对其读,发送CMD17(内含地址),SD卡返回8’h00,然后返回8’hfe+512字节+2字节CRC)
这幅图是data tokens数据格式。(data tokens数据是连续发送或接收)
读步骤:
(1)发送CMD17(单块)或CMD18(多块)读命令,返回0x00
(2)接收数据开始令牌0xfe+正式数据512Bytes + CRC校验2Bytes
默认正式传输的数据长度是512Bytes,可用CMD16设置块长度。
写步骤:
(1)发送CMD24(单块)或CMD25(多块)写命令,返回0x00
(2)发送数据开始令牌0xfe+正式数据512Bytes + CRC校验2Bytes
擦除步骤:
(1)发送CMD32,跟一个参数来指定首个要擦除的起始地址(SD手册上说是块号)
(2)发送CMD33,,指定最后的地址
(3)发送CMD38,擦除指定区间的内容
注:此3步顺序不能颠倒。
6字节的指令
发送物理地址时(不时逻辑地址),byte2 是最高的8八位
发送CMD16设置一块的长度,bytes2-5的数值表示长度 ,byte2也是最高位
附上文档下载地址:
https://www.sdcard.org/downloads/pls/simplified_specs/
补充:
SD卡就只有V1.0(V1.1),V2.0(SDHC).严格来说SDHC卡就是V2.0的卡.
V2.0的卡又分为普通容量的卡与高容量卡.高容量卡就叫SDHC.
他们的区别就是判断OCR的第30位,是否为1.如果是1,说明是一张SDHC的卡,如果是0,说明是一张普通容量的SD卡.
SDHC卡初始化步骤:
2.0版本以上一定要执行CMD8
SD卡按照内存容量大小分3类:
SDSC(标准容量SD内存卡) :最大支持为2GByte。
SDHC(大容量SD内存卡) :SD卡容量介于2Gyte~32GByte。
SDXC(扩展容量SD卡内存卡):SD卡容量介于32GByte~2TByte