单片机IO模拟SPI操作SD卡,CMD9命令不能返回数据起始令牌0xFE

程序员小哈
嵌入式领域优质创作者
博客专家认证
2011-10-24 09:16:48
我手里一共三张SD卡,64M,1G,2G的,64M的初始化程序一切正常,返回也正常,因为我想加一个FAT32文件系统,64M的不够大,所以换成1G的,2G的,但是CMD9命令就不对了,以至于没法求出SD卡大小,很是困惑,网上有人说延时时间不够,我加大了,效果依旧一样。
我的问题换个说法,就是同一段代码,可以求出64M SD卡的容量,但是1G/2G的卡就求不出来结果?

我初始化SD卡部分代码如下:

//********************************************
unsigned int SD_Overall_Initiation()
{
unsigned int Response,Response_2;
Response=0x0000;
Response_2=0xff00;

sd_dao=1; //[1] Do High
//[1] Do must be High when there is no transmition

do
{
Response=SD_Reset_Card();//[2] Send CMD0
}while (Response!=0xff01);

printf("CMD0 return %x \r\n ",Response); //ff01

if (Response!=0xff01)
Response_2+=8;

//Response=SD_CMD_Write(8,0x00000000,1,0);//Send CMD8

Response=SD_Initiate_Card();//[3] Send CMD55+ACMD41
if (Response==0xff00)
;
else
{
Response_2+=4;
;
}

do
{
Response=SD_Get_CardInfo();//[4] Read CSD
}while (Response!=0xff00);

printf("SD_Get_CardInfo return %x \r\n ",Response); //ff00

if (Response==0xff01)
Response_2+=2;

return Response_2;
// 0000|0000||0000|0000 Response_2
// |||_CSD Fail
// ||__CMD55+ACMD41 Fail
// |___CMD0 Fail
}
//********************************************
unsigned int SD_Get_CardID()//Read CID register
{
unsigned int temp,Response,MaximumTimes;
MaximumTimes=10;

for(temp=0;temp<MaximumTimes;temp++)
{
Response=SD_CMD_Write(10,0x00000000,1,1);//Send CMD9
if (Response==0xff00)
temp=MaximumTimes;
}

for (temp=0;temp<8;temp++)//Provide 8 clock to romove the first byte of data response (0x00fe)
{
sd_clk=0;//CLK Low
Delay5us();
sd_clk=1;//CLK High
Delay5us();
}

for (temp=0;temp<8;temp++)
DataBuffer[temp]=SD_2Byte_Read();//Get the CID data

for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC)
{
sd_clk=0;//CLK Low
Delay5us();
sd_clk=1;//CLK High
Delay5us();
}

sd_cse=1;//CS_High()

for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
{
sd_clk=0;//CLK Low
Delay5us();
sd_clk=1;//CLK High
Delay5us();
}

return Response;
}
//********************************************

//********************************************
unsigned int SD_Get_CardInfo()//Read CSD register CSD 16 BYTE
{
unsigned int temp,Response,MaximumTimes,retry,Int16;
unsigned long int C_SIZE;
unsigned long int C_SIZE_MULT; //其中:(C_SIZE_MULT < 8)
unsigned long int MULT;
unsigned long int READ_BL_LEN; //其中:(READ_BL_LEN < 12)
unsigned long int BLOCK_LEN;

C_SIZE = 0;
C_SIZE_MULT = 0;
MULT = 0;
READ_BL_LEN = 0;
BLOCK_LEN = 0;
MaximumTimes=50;

for(temp=0;temp<MaximumTimes;temp++)
{
Response=SD_CMD_Write(9,0x00000000,1,1);//Send CMD9
if (Response==0xff00)
temp=MaximumTimes;
}




//等待SD卡发回数据起始令牌0xFE
retry = 0;

do
{
Int16 = SD_Read();

retry++;
if(retry>0x2000) //0x2000次等待后没有应答,退出报错
{
return 1;
}
}while(Int16 != 0xFFFE);

printf("Int16 = %04x \r\n ",Int16);

for (temp=0;temp<8;temp++)
DataBuffer[temp]=SD_2Byte_Read();//Get the CSD data

for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC)
{
sd_clk=0;//CLK Low
Delay5us();
sd_clk=1;//CLK High
Delay5us();
}

sd_cse=1;//CS_High()

for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
{
sd_clk=0;//CLK Low
Delay5us();
sd_clk=1;//CLK High
Delay5us();
}

/*
C_SIZE_MULT [49:47] //device size multiplier
C_SIZE [73:62] //device size
READ_BL_LEN [83:80] //max. read data block length

memory capacity = BLOCKNR * BLOCK_LEN
where
BLOCKNR = (C_SIZE+1) * MULT
C_SIZE_MULT+2
MULT = 2 //其中:(C_SIZE_MULT < 8)

READ_BL_LEN
BLOCK_LEN = 2 //其中:(READ_BL_LEN < 12)

Therefore, the maximum capacity which can be coded is 4096*512*2048 = 4 GBytes. Example: A four MByte card
with BLOCK_LEN = 512 can be coded with C_SIZE_MULT = 0 and C_SIZE = 2047.
*/
//BlockNR=((DataBuffer[3]<<2)&0x0fff)+((DataBuffer[4]>>14)&0x0003)+1; //Calcuate MULT
//BlockNR=BlockNR*(0x0002<<(((DataBuffer[4]<<1)&0x0007)+((DataBuffer[5]>>15)&0x0001)+1)); //Calcuate Block_Number

printf("DataBuffer[0] = %04x \r\n ",DataBuffer[0]); //00EF 第十六字节00 127-120|119-112 第十五字节EF
printf("DataBuffer[1] = %04x \r\n ",DataBuffer[1]); //0032 第十四字节00 111-104|103-96 第十三字节32
printf("DataBuffer[2] = %04x \r\n ",DataBuffer[2]); //5359 第十二字节53 95-88|87-80 第十一字节59
printf("DataBuffer[3] = %04x \r\n ",DataBuffer[3]); //83EA 第十字节83 79-72|71-64 第九字节EA
printf("DataBuffer[4] = %04x \r\n ",DataBuffer[4]); //30B5 第八字节30 63-56|55-48 第七字节B5
printf("DataBuffer[5] = %04x \r\n ",DataBuffer[5]); //FF9F 第六字节FF 47-40|39-32 第五字节9F
printf("DataBuffer[6] = %04x \r\n ",DataBuffer[6]); //9640 第四字节96 31-24|23-16 第三字节40
printf("DataBuffer[7] = %04x \r\n ",DataBuffer[7]); //002D 第二字节00 15-8|7-0 第一字节2D

C_SIZE = ((DataBuffer[3]&0x03FF)<<2)&0x0FFC + ((DataBuffer[4]>>14)&0x0003); //[73:62]
printf("C_SIZE = %ld Byte \r\n ",C_SIZE);

C_SIZE_MULT = ( ((DataBuffer[4]&0x0003)<<1)&0x0006 ) + ( ((DataBuffer[5]>>15)&0x0001) ); //[49:47]
printf("C_SIZE_MULT = %ld Byte \r\n ",C_SIZE_MULT);

READ_BL_LEN = (DataBuffer[2]&0x000f ); //[83:80]
printf("READ_BL_LEN = %ld Byte \r\n ",READ_BL_LEN);

MULT = (0x0001<< ( C_SIZE_MULT + 2 ));
printf("MULT = %ld Byte \r\n ",MULT);

BLOCK_LEN = (0x0001<< 9);
printf("BLOCK_LEN = %ld Byte \r\n ",BLOCK_LEN);

BlockNR=(C_SIZE+1) * MULT * BLOCK_LEN;

printf("device size = %ld M \r\n ",BlockNR/1024/1024);

return Response;
}


SD_Get_CardInfo这个函数中的下面部分,怎么也返回不了正常的0xFE?
do
{
Int16 = SD_Read();

retry++;
if(retry>0x2000) //0x2000次等待后没有应答,退出报错
{
return 1;
}
}while(Int16 != 0xFFFE);


麻烦大家帮忙看看,谢谢啦
...全文
952 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
程序员小哈 2011-10-28
  • 打赏
  • 举报
回复
结贴啦,问题没解决啊
程序员小哈 2011-10-26
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 woshi_ziyu 的回复:]

你可以把读64M的程序打印出来

然后和读1G的数据比较一下

应该前段部分的数据是一样的
[/Quote]

初始化部分一模一样,就是读大小,CSD寄存器时有问题,╮(╯▽╰)╭
woshi_ziyu 2011-10-25
  • 打赏
  • 举报
回复
你可以把读64M的程序打印出来

然后和读1G的数据比较一下

应该前段部分的数据是一样的
codesnail 2011-10-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 rsd102 的回复:]

引用 6 楼 codesnail 的回复:

引用 4 楼 rsd102 的回复:

引用 2 楼 codesnail 的回复:

是不是sd卡控制器接口不支持,或者不兼容。


估计是不兼容,可是不知道不兼容的地方是哪里?没法往下进行了,╮(╯▽╰)╭

如果是从硬件上不兼容或者不支持,例如有些sd卡控制器支持的sd大小有限制,从软件上是无能为力的。。。。。


估……
[/Quote]
你是说笔记本的读卡器还是你买的读卡器?

你拿一个32g以上的sd卡插到一个老式的笔记本读卡槽试试。。。。。
程序员小哈 2011-10-25
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 codesnail 的回复:]

引用 4 楼 rsd102 的回复:

引用 2 楼 codesnail 的回复:

是不是sd卡控制器接口不支持,或者不兼容。


估计是不兼容,可是不知道不兼容的地方是哪里?没法往下进行了,╮(╯▽╰)╭

如果是从硬件上不兼容或者不支持,例如有些sd卡控制器支持的sd大小有限制,从软件上是无能为力的。。。。。
[/Quote]

估计还是哪里我处理的不对,不然为什么所有的卡,在电脑上看却一切正常呢,╮(╯▽╰)╭,不知道哪里弄得不对
codesnail 2011-10-24
  • 打赏
  • 举报
回复
是不是sd卡控制器接口不支持,或者不兼容。
woshi_ziyu 2011-10-24
  • 打赏
  • 举报
回复
1. Int16 = SD_Read();
------------
查看SD_Read()的返回类型是否是int,试试定义为long

2.
改一下


Int16 = SD_Read();
do
{
retry++;
if(retry>0x2000) //0x2000次等待后没有应答,退出报错
{
return 1;
}
}while(Int16 != 0xFFFE);
codesnail 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 rsd102 的回复:]

引用 2 楼 codesnail 的回复:

是不是sd卡控制器接口不支持,或者不兼容。


估计是不兼容,可是不知道不兼容的地方是哪里?没法往下进行了,╮(╯▽╰)╭
[/Quote]
如果是从硬件上不兼容或者不支持,例如有些sd卡控制器支持的sd大小有限制,从软件上是无能为力的。。。。。
程序员小哈 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 woshi_ziyu 的回复:]

1. Int16 = SD_Read();
------------
查看SD_Read()的返回类型是否是int,试试定义为long

2.
改一下

C/C++ code

Int16 = SD_Read();
do
{
retry++;
if(retry>0x2000) //0x2000次等待后没有应答,退出报错
……
[/Quote]

我按您说的,返回值换成了Long型,
long SD_Read_Long()
{
long BitCounter,Buffer;
Buffer=0xffffffff;

sd_dai = 1;

for (BitCounter=0;BitCounter<8;BitCounter++)
{
Buffer=Buffer<<1; //Because the MSB is transmitted firstly, shift to next lower bit.
//Because the LSB will be damaged, we can not put this line under next line.

sd_clk=0; //CLK Low
Delay5us();
sd_clk=1; //CLK High

if(sd_dao == 1)
Buffer++; //If SPI_Din=1 then the LSB_of_Buffer=1.
}

return Buffer;
}
下面程序的Int16也换成了long型:
do
{
//Int16 = SD_Read();
Int16 = SD_Read_Long();
printf("Int16 = %08lx \r\n ",Int16);

retry++;
if(retry>0x10) //0x200次等待后没有应答,退出报错
{
return 1;
}
}while(Int16 != 0xFFFE);



此结果打印出效果如下:

CMD0 return ff01

CMD55 return ff05

ACMD41 return ff05

CMD55 return ff01

ACMD41 return ff01

CMD55 return ff01

ACMD41 return ff00

Int16 = ffffff00

Int16 = ffffff5d

Int16 = ffffff00

Int16 = ffffff32

Int16 = ffffff5b

Int16 = ffffff5a

Int16 = ffffff83

Int16 = ffffffbf

Int16 = ffffffff

Int16 = ffffffff

Int16 = ffffffff

Int16 = ffffff80

Int16 = ffffff16

Int16 = ffffff80

Int16 = ffffff00

Int16 = ffffff67

Int16 = fffffffa

Int16 = ffffff00

Int16 = ffffff5d

Int16 = ffffff00

Int16 = ffffff32

Int16 = ffffff5b

Int16 = ffffff5a

Int16 = ffffff83

Int16 = ffffffbf

Int16 = ffffffff

Int16 = ffffffff

Int16 = ffffffff

Int16 = ffffff80

Int16 = ffffff16

Int16 = ffffff80

Int16 = ffffff00

Int16 = ffffff67

Int16 = fffffffa

Int16 = ffffff00

Int16 = ffffff5d

Int16 = ffffff00
... ...

返回的值没有fe结尾的呀
程序员小哈 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 codesnail 的回复:]

是不是sd卡控制器接口不支持,或者不兼容。
[/Quote]

估计是不兼容,可是不知道不兼容的地方是哪里?没法往下进行了,╮(╯▽╰)╭
程序员小哈 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 woshi_ziyu 的回复:]

1. Int16 = SD_Read();
------------
查看SD_Read()的返回类型是否是int,试试定义为long

2.
改一下

C/C++ code

Int16 = SD_Read();
do
{
retry++;
if(retry>0x2000) //0x2000次等待后没有应答,退出报错
……
[/Quote]


谢谢你的回复,我把我的SD_Read()定义发给你看看

unsigned int SD_Read()
{
unsigned int BitCounter,Buffer;
Buffer=0xffff;

sd_dai = 1;

for (BitCounter=0;BitCounter<8;BitCounter++)
{
Buffer=Buffer<<1; //Because the MSB is transmitted firstly, shift to next lower bit.
//Because the LSB will be damaged, we can not put this line under next line.

sd_clk=0; //CLK Low
Delay5us();
sd_clk=1; //CLK High

if(sd_dao == 1)
Buffer++; //If SPI_Din=1 then the LSB_of_Buffer=1.
}

return Buffer;
}


如果我换成long型,那这个函数也要换吧,换成占四个字节的类型?期待您的回复

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧