[SD卡读求助]SPI模式下CMD17无法接收到0xfe的令牌
本帖最后由 Alimy 于 2013-4-28 15:02 编辑1GB的一个SD卡。。使用SPI模式,初始化时的时钟为375K
初始化成功后时钟转变为750K。。
初始化流程:
发CMD0,响应R1为0x01,正常。。
发CMD8, 响应R1是否支持此命令。。(此程序中没有处理下面这种情况 sd_card_type = SD_VER1X; //1.x版本不支持CMD8指令)此卡片响应支持这个命令
发CMD58(READ_OCR),检测电压,响应正常SD_OCR_Buff == 0xffSD_OCR_Buff == 0x80
发ACMD41,等待R1 = 0x00。
在发CMD58(READ_OCR) 响应的结果CCS ==0 说明是标准容量设备
---------初始化成功了------------------
发cmd16,设置块长为0x0100 (256字节)
初始化程序如下/*
*@Func: uint_8 SDMMC_Init(void)
* @Usage: for SD card init
*@parameter: none
*@retval:
* 初始化状态
* CMD0_ERRORcmd0发送错误
* CMD1_ERRORcmd1发送错误
*CMD8_ERRORcmd8发送错误
*CMD58_ERROR CMD58发送错误
*ACMD41_ERROR ACMD58响应有误
*INIT_SUCCESS 初始化成功
*@version: 2013-04-10 14:51:14
* */
uint_8 SDMMC_Init(void){
uint_8idx = 0;
uint_16 retry = 0;
bSDMMC_Init_Flag = 1;// 初始化标志位,初始化未成功
spi_cs_set();
for(;idx<0x0b;idx++){// 发送至少74个时钟信号
spi_send_byte(0xff);
}
do{
SD_SPISendCMD0(); // RESET CMD
GetRespenseR1();
if(200 == retry++){ //两百次超时
spi_cs_set();
return CMD0_ERROR;
}
}while(R1_Respense!=0x01);//响应为0x01,显示SD卡在Idle状态
SD_SPISendCMD8();
GetRespenseR7();
if(R1_Respense&R1_ILLAGAL_CMD){
sd_card_type = SD_VER1X; //1.x版本不支持CMD8指令
}
else{
sd_card_type = SD_VER20; // 2.0及以后版本才支持CMD8
if((R7_Respense!=CHECK_PATTERN)||(R7_Respense!=VHS_2P7_3P6V)){//valid response (check pattem error || non-compatible voltage)
sd_card_type = SD_UNUSABLE;
return 1;//初始化失败
}
//else card withcompatible Voltage range
SD_SPISendCMD58(); //Read OCR
GetRespenseR3();
if((SD_OCR_Buff!=0xff)||(SD_OCR_Buff!=0x80)){// 检查操作电压范围情况
sd_card_type = SD_UNUSABLE;
return 1;//初始化失败
}
retry = 0;
do{
WaitT0(10000);
SD_SPISendACMD41(); //是否完成初始化
GetRespenseR1();
if(70==retry++){
spi_cs_set();
return 1;
}
}while(R1_Respense!=0x00); //
SD_SPISendCMD58(); //Read OCR
GetRespenseR3();
if(SD_OCR_Buff&0x40){ //ccs == 1?
sd_card_type = SD_EXT_CAPACITY;// ccs == 1version2.00 or later high capacity SD memory card
}
else{
sd_card_type = SD_STANDARD_CAPACITY; // ccs == 0 version2.00 or later standard capacity SD memory carh
}
}
if(SD_STANDARD_CAPACITY == sd_card_type){
SD_SPISendCMD16();// SET_BLOCKLEN
GetRespenseR1();
}
spi_cs_set(); // 片选无效
bSDMMC_Init_Flag = 0; //初始化成功
return INIT_SUCCESS;
}
上面用375K初始化完成后,就切换了一下时钟到750K
然后调用
SDMMC_Read_Sector(0x00000000,SD_DATA_Buff); //SD_DATA_Buff是一个放在xdata中长度为256的数组的数组名
实现代码如下。。uint_8 SDMMC_Read_Sector(uint_32 addr,uint_8 *pbuff){
uint_16 idx = 0;
uint_8time = 0,temp = 0;
CMD_Buff = 0x51; // CMD17 0x40 + 17
addr <<= 9;// sector = sector*512将块地址(扇区地址)转换为字节地址
// addr *= 512;
CMD_Buff =((addr&0xff000000)>>24);
CMD_Buff =((addr&0x00ff0000)>>16);
CMD_Buff =((addr&0x0000ff00)>>8);
CMD_Buff =(addr&0x000000ff);
CMD_Buff = 0xff;
//TRY_LOOP:
spi_cs_clr();
Write_SD_CMD();
spi_read_byte();
temp =spi_read_byte();
while(0xfe!=spi_read_byte()) ; // 一直读,读到0xfe时,接下来就是256字节的数据
for(idx=0;idx<256;idx++){
*(pbuff+idx) = spi_read_byte();
}
spi_read_byte();
spi_read_byte(); // 两个字节的校验码
return 0;
}但是逻辑分析仪抓到的数据一直是0xff,我尝试等过2min一直等不到0xfe的命令包,我也在网络搜索过类似的情况,调整了timeout时间,时钟等。还是一样无法等到0xfe
一直卡在:
while(0xfe!=spi_read_byte()) ;
不清楚有没有前辈遇到过与我一样的问题,
还请不吝赐教!谢谢先!!! 自挽一楼。。俺的描述很难于被理解么?{:cry:}
页:
[1]