//获取SD卡的总扇区数(扇区数)
//返回值:0: 取容量出错
// 其他:SD卡的容量(扇区数/512字节) 返回值单位KB
//每扇区的字节数必为512,因为如果不是512,则初始化不能通过.
u32 SD_GetSectorCount(void)
{
u8 csd[16];
u32 Capacity;
u8 n;
u16 csize;
//取CSD信息,如果期间出错,返回0
if(SD_GetCSD(csd)!=0) return 0;
//如果为SDHC卡,按照下面方式计算
if((csd[0]&0xC0)==0x40) //V2.00的卡 //cisize最大只有16位。所以最大支持容量为32GB,还有6位没算本来可以支持到2TB
{
csize = csd[9] + ((u16)csd[8] << 8) + 1;
Capacity = (u32)csize << 9; //CISIZE*512KB 显示时>>10位化成MB好些
}else//V1.XX的卡
{
n = (csd[5] & 0xf) + ((csd[10] & 0x80) >> 7) + ((csd[9] & 0x03) << 1) + 2;
csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
Capacity= (u32)csize << (n - 9); //CAPACITY化成单位为KB,所以我觉得N-10好些
}
return Capacity;
}
第1个问题就是我改的地方
//等待卡准备好
//返回值:0,准备好了;其他,错误代码
u8 SD_WaitReady(void) //个人理解,这里目的是为了保证cmd发出前out线为高电平
{
u32 t=0;
do
{
if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
t++;
}while(t<0XFFFFFF);//等待
return 1;
}
第二个问题是这里的个人理解
//写SD卡
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
{
u8 r1;
if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//转换为字节地址
if(cnt==1)
{
r1=SD_SendCmd(CMD24,sector,0X01);//写命令
if(r1==0)//指令发送成功
{
r1=SD_SendBlock(buf,0xFE);//写512个字节
}
}else
{
if(SD_Type!=SD_TYPE_MMC) //SD卡发送特定命令,为MMC不需要直接发送CMD25
{ //不知道SD卡可不可以直接发送CMD25
SD_SendCmd(CMD55,0,0X01);
SD_SendCmd(CMD23,cnt,0X01);//发送指令
}
r1=SD_SendCmd(CMD25,sector,0X01);//连续读命令
if(r1==0)
{
do
{
r1=SD_SendBlock(buf,0xFC);//0xfc为开始写入令牌
buf+=512;
}while(--cnt && r1==0);
r1=SD_SendBlock(0,0xFD);//0xfd为结束令牌
}
}
SD_DisSelect();//取消片选
return r1;//
}
第三个问题是上面划线部分,MMC卡值支持基本指令,而SD卡V1.0的规范应该也兼容吧,可不可以不写CMD55+ACMD23而用CMD25代替呢?就像ACMD41和CMD1在激活时,用法相同
第四个问题:为什么初始化为什么没禁止CRC校验?貌似spi初始化后,没用到CRC
第五个问题,原子哥有没有测试过V1.0规范的SD卡和SPI模式的MMC卡?
注:以上问题都基于SPI模式,是在论坛下载修改后的代码,希望原子哥予以点评和解答 |