God_of_Death

SD卡编程小计

0
阅读(2546)

image

进过几天的奋战,终于对SD卡(这里不区分SD卡,SDHC卡和SDXC卡,统称为SD卡,如果需要会特别说明)有一个了解,在这里写下笔记,为了给自己以后有个提醒。(对于用verilog编写程序,难度还是很大的╭∩╮(︶︿︶)╭∩╮)

编写程序之前,你需要对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)

clip_image003

这幅图是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步顺序不能颠倒。


clip_image005




6字节的指令


发送物理地址时(不时逻辑地址),byte2 是最高的8八位

发送CMD16设置一块的长度,bytes2-5的数值表示长度 ,byte2也是最高位



小小抱怨一下,为啥感觉看官方资料有点乱。(╯﹏╰)



附上文档下载地址:

https://www.sdcard.org/downloads/pls/simplified_specs/

clip_image007


补充:

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