Alimy 发表于 2013-4-28 14:58:46

[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()) ;
不清楚有没有前辈遇到过与我一样的问题,
还请不吝赐教!谢谢先!!!

Alimy 发表于 2013-5-2 08:58:18

自挽一楼。。俺的描述很难于被理解么?{:cry:}
页: [1]
查看完整版本: [SD卡读求助]SPI模式下CMD17无法接收到0xfe的令牌