基于stm32f103zet6的FAT16文件系统学习0(读SD卡扇区)
扫描二维码
随时随地手机看文章
SD卡已经看了两天了,主要是因为测试出来的卡容量不对,所以一直找原因,最终还是发现了,总比不过是单位上面出现了问题,或许是之前没有接触到SD的缘故吧,所以对其中的一些寄存器很不了解,一切都是重新开始,对照这寄存器手册,理解程序,修改程序。一步步还是总结一下!
首先关于SD卡的协议是有必要了解的,我今天花了一上午的课堂时间来理解这个SD卡的协议,就是基于这个文档的,这个文档很适合入门SD协议的(个人认为)。http://download.csdn.net/detail/king_bingge/5218183
初识SD之后,就可以开始正式学习SD卡了!
一、要使用SD卡,那么首先肯定得对SD卡进行初始化,那么如何进行初始化呢?(命令的参数暂且不提)
1、这里涉及到很多指令了。协议规定了在给SD卡上电之后需要给出至少74个时钟脉冲后,才能进行相关的SD初始化工作,虽然是这么说,但是我不给74个时钟,他照样能初始化,看看。
for(i=0;i<10;i++)SD_SPI_ReadWriteByte(0XF);
但是,或许为了能够更加成功的初始化吧,所以有这个规定所以,我们还是规规矩矩的好,给它74个时钟,没关系的嘛!
2、然后就是协议中说到当我们复位或者上电的时候,SD卡的SD控制寄存器处于卡识别模式中的空闲模式的,暂且这样称吧。本来我们是不需要发送复位命令了的,但是我们不知道我们的SD所支持的电压范围。所以,我们最好还是先给出一条复位指令,然后紧接着一条获取工作电压的指令,这样也是比较保险,如果多SD卡工作电压有疑问的,那么就得去看芯片手册了。有了这个知识,那下面的代码就不成问题了
retry=20;
do
{
r1=SD_SendCmd(CMD0,0,0x95);//进入IDLE状态
}while((r1!=0X01)&&retry--);
SD_Type=0;//默认无卡
if(r1==0X01)
{
if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SDV2.0
{
for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//GettrailingreturnvalueofR7resp
if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
3、协议上还提到ACMD41命令的目的是给予 SD卡控制器一个识别 SD卡是否可以在所给Vdd 范围下工作的机制,如果 SD 卡无法在指定 Vdd 范围内工作,则它会进入非活动状态(Inactive state ),所以我们接下来需要发送这个命令,但是在发送这个命令之前,要知道这是一个应用型的命令,所以要加上CMD55命令,所以有了下面的代码。
if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
{
retry=0XFFFE;
do
{
SD_SendCmd(CMD55,0,0X01);//发送CMD55
r1=SD_SendCmd(CMD41,0x40000000,0X01);//发送CMD41
}while(r1&&retry--);
if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始//获取供电状态
{
for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC;//检查CCS
elseSD_Type=SD_TYPE_V2;
}
这样就获取了卡的类型了,至此卡的初始化基本完成,当然根据协议上,我们还可以在这里修改相对地址之类的。如果有必要的话,可以这样做!
二、初始化完SD卡,接下来如果你想查看我们SD的容量,可以这样做!
之前就是因为卡容量的问题,所以郁闷了好久,理解了个大概!注意这里函数名是读取扇区数,实际上返回的值是我们卡的容量,这里得注意了。
1、首先看代码
u32SD_GetSectorCount(void)
{
u8csd[16];
u32Capacity_KB,Capacity_MB;
u8n;
u16csize;
//取CSD信息,如果期间出错,返回0
if(SD_GetCSD(csd)!=0)return0;
n=(csd[5]&15)+((csd[10]&128)>>7)+((csd[9]&3)<<1)+2;
csize=(csd[8]>>6)+((u16)csd[7]<<2)+((u16)(csd[6]&3)<<10)+1;
Capacity_KB=(u32)csize<<(n-10);//得到扇区数,这里的单位是KB
Capacity_MB=Capacity_KB/1024;
returnCapacity_MB;
}
这个计算的问题必须得看SD卡的手册,也就是128位的CSD寄存器。这里我把我分析的过程贴出来,我不得不说比较乱,或许只有我自己能看懂了,懒得整理了,仅供参考!
MySD_Card
CSD寄存器中的值如下:
007fff32bit(127-96)csd0-csd3
5f5983cbbit(95--64)csd4-csd701011111010110011000001111001011
76dbdfffbit(63--32)csd8-csd1101110110110110111101111111111111
96400097bit(31---0)csd12-csd15
csize{62,73}
csize_muti{47,49}
read{80,83}
csize=111100101101=3885
csize_muti=111=7
read=1001=9
计算公式:
blocknr=(csize+1)*mult=
mult=(csize_muti<8)*(2^(csize_muti+2))
block_len=(read<12)*(2^(read))
capacity=blocknr*block_len=13*4*3516*98304
依据下面代码来计算我的容量:
n=(csd[5]&15)+((csd[10]&128)>>7)+((csd[9]&3)<<1)+2;
csize=(csd[8]>>6)+((u16)csd[7]<<2)+((u16)(csd[6]&3)<<10)+1;
Capacity_KB=(u32)csize<<(n-10);//得到扇区数,这里的单位是KB//007fff325f5983cb76dbdfff96400097
Capacity_MB=Capacity_KB/1024;
1、(csd[8]>>6)得到的是bit62和bit63的值去掉2位
2、((u16)csd[7] << 2)得到的是bit64--bit69的值 去掉6位