SD卡初始化以及命令详解
扫描二维码
随时随地手机看文章
SD卡是嵌入式设备中很常用的一种存储设备,体积小,容量大,通讯简单,电路简单所以受到很多设备厂商的欢迎,主要用来记录设备运行过程中的各种信息,以及程序的各种配置信息,很是方便,有这样几点是需要知道的
SD卡是基于flash的存储卡。
SD卡和MMC卡的区别在于初始化过程不同。SD卡并不是我们通常意义上的手机扩展卡,那种卡叫做TF卡,但是通讯以及驱动模式是类似的.
SD卡的通信协议包括SD和SPI两类,SD卡上电之后默认处于SD状态。
SD卡使用卡内智能控制模块进行FLASH操作控制,包括协议、安全算法、
数据存取、ECC算法、缺陷处理和分析、电源管理、时钟管理。这些都不需要用户关系,这是SD卡厂商做的事情
驱动SD卡主要要实现读扇区,写扇区,初始化,获取SD卡相关配置信息这几个就可以了,
另外.SD卡本身只是一种数据介质,它不含有文件系统,文件系统是一种文件的组织格式,是独立于存储介质的一种规范
标准SD卡引脚序列
SD卡引脚功能表
TF卡引脚排序
TF卡引脚功能表
由此可见,TF卡比SD卡少了一个VSS引脚,也就是少了一个供电引脚
另外电路设计时若SD卡使用SPI模式,那么不用的几根数据线应加上上拉电阻,否者会因为这几根数据线的电流震荡引起电流损耗,造成电路上的不稳定
SD卡电路SPI驱动模式
SD卡内部有五个我们可以读取的寄存器,分别如下
要读取这些信息就需要与卡通讯,SD通讯是用命令+数据的形式进行的,命令格式如下
也就是说,一次SD卡命令发送一共要发送6个字节,对于SPI通讯而言,就是SPI总线上传送六个字节
字节1的最高2位固定为01,低6位为命令号(比如CMD16,
为10000即16进制的0X10,完整的CMD16,第一个字节为01010000,即0X10+0X40)。
字节2~5为命令参数,有些命令是没有参数的。对于没有参数的命令默认发送0即可
字节6的高七位为CRC值,最低位恒定为1,crc计算遵循以下规律
GX为生成多项式,具体计算方法请查看CRC计算相关,不过有一点好处就是,在SPI驱动模式下,不需要CRC校验(默认SD卡在SPI模式下不开启CRC校验,在SD模式下默认开始CRC校验),所以我们只需要对CMD0进行CRC就可以了,后面的CRC都可以不管(因为在CMD0之前是SD模式,所以第一个命令需要,切换之后就不用了),而CMD0的CRC为0x95(加上了之后的一位1)
注:SPI模式下打开crc校验需要用到CMD59的保留命令,请查阅相关资料
SD卡的命令表如下所示(以下仅写出SPI模式的CMD)
CMD0复位SD卡,重置所有卡到Idle状态,参数为0
CMD1设置SD卡到ACTIVATE模式,也就是推出IDLE模式
CMD8发送接口状态命令
CMD9读取CSD寄存器
CMD10读取CID寄存器
CMD12在多块读取的时候请求停止读取
CMD13读取SD卡状态寄存器
CMD16设置单个扇区的大小一般都设置为512字节一个扇区
CMD17读取扇区命令
CMD18读取多个扇区知道发送停止命令
CMD24写扇区命令
CMD25写多个扇区命令
CMD27编辑CSD位
CMD28设置地址组保护位。写保护由卡配置数据的WP_GRP_SIZE指定
CMD29清除保护位
CMD30要求卡发送写保护状态,参数中有要查询的地址
CMD32设置要擦除的第一个写数据块地址
CMD33设置要擦除的最后一个写数据块地址
CMD38擦除所有选中的块
CMD42设置SD卡的解锁或者上锁
CMD55告诉SD卡下一个命令式卡应用命令,不是标准命令
CMD56应用相关的数据块读写命令
CMD58读取OCR信息
CMD59设置crc校验的使能与关闭(前面说到过)
ACMD13发送SD卡状态
ACMD18保留作为SD安全应用(也就是这命令没用)
ACMD22发送写数据块的数目。响应为32位+CRC
ACMD23设置写前预擦除的数据块数目(用来加速多数据块写操作)。“1”=默认(一个块)(1)
不管是否使用ACMD23,在多数据块写操作中都需要STOP_TRAN(CMD12)命令
ACMD25 26 38保留作为安全应用
ACMD41要求访问的卡发送它的操作条件寄存器(OCR)内容
ACMD42连接[1]/断开[0]卡上CD/DAT3(pin 1]的50K欧姆上拉电阻。上拉电阻可用来检测卡
ACMD43-49保留作为安全应用
ACMD51读取SD配置寄存器SCR
ACMD命令,全称应该是application CMD,所以使用ACMD都需要在发送CMD55之后
发出命令后会收到相应的响应,所有响应通过CMD线传输,响应以MSB开始,不同类型的响应长度根据类型不同而不同。
响应以起始位开始(通常为“0”),接着这是传输方向的位(卡为0)。除了R3外其他
响应都有CRC。每个响应都以结束位(通常为“1”)结束。,SD卡响应格式有多种
1.R1响应
2.R1b响应
多了一个忙数据
3.R2响应
4.R3响应(针对于read ocr的响应CMD58)
5.响应R4和R5都是正对于SD mode的响应
6.针对CMD8命令的响应R7
SD卡的初始化以及识别过程(为了方便起见,我们只检测响应的R1状态)
1.初始化与SD卡连接的硬件条件(MCU的SPI配置,IO口配置);
2.上电延时(>74个CLK)(为了让卡正常启动)
3.复位卡(CMD0),进入IDLE状态,检测R1的最低位,是否为闲置状态
4.发送CMD8,检查是否支持2.0协议,因为这个命令是在2.0的协议里面才添加的
5.根据不同协议检查SD卡(命令包括:CMD55、CMD41、CMD58和CMD1等);
6.取消片选,发多8个CLK,结束初始化
具体请查看下图
以下是网络上找到的一份经我修改之后的SD卡驱动,不完全符合SD卡标准驱动,但是我用着一直还蛮正常,大家有兴趣可以看看改改
Spisd.c
#include"spisd.h"
//预定义SD卡类型
u8SD_Type=0;//SD卡的类型
//这部分应根据具体的连线来修改!
#defineSD_CSPAout(4)//SD卡片选引脚
//data:要写入的数据
//返回值:读到的数据
staticu8SdSpiReadWriteByte(u8data)
{
returnSpi1ReadWriteByte(data);
}
//SD卡初始化的时候,需要低速
staticvoidSdSpiSpeedLow(void)
{
Spi1SetSpeed(SPI_SPEED_256);//设置到低速模式用于初始化,最高spi速度为400k
}
//SD卡正常工作的时候,可以高速了
staticvoidSdSpiSpeedHigh(void)
{
Spi1SetSpeed(SPI_SPEED_4);//设置到高速模式初始化完成之后进行,最高可到25M,不过一般不用
}
staticvoidSdIOInit(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化A4
SD_CS=1;
Spi1Init();//初始化SPI接口
SdSpiSpeedLow();//初始化设置为低速
}
//等待卡准备好
//返回值:0,准备好了;其他,错误代码
staticu8SdWaitReady(void)
{
u32t=0;
do
{
if(SdSpiReadWriteByte(0XFF)==0XFF)return0;//OK
t++;
}while(t<0XFFFFFF);//等待
return1;
}
//取消选择,释放SPI总线
voidSD_DisSelect(void)
{
SD_CS=1;
SdSpiReadWriteByte(0xff);//提供额外的8个时钟
}
//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
u8SdSelect(void)
{
SD_CS=0;
if(SdWaitReady()==0)return0;//等待成功
SD_DisSelect();
return 1;//等待失败