jazsmile 发表于 2012-8-10 20:39:00

SDHC卡CMD41应答01。为什么?

已完成sdhc卡的初始化,但是为了简介,对sd发送命令函数进行修改,就是这样的修改造成cmd41不能成功。

请大家看看。谢谢!!



1可实现CMD41和cmd55的函数
==================
1.1发送命令U08 SD_write_command (U08 *cmd)
{
        U08 tmp = 0xff;
        U16 Timeout = 0;

        SD_Disable();      //SD_CS = HIGH
        SD_write_byte(0xFF); //send 8 Clock Impulse
        SD_Enable();         //SD_CS = LOW   

        //send 6 Byte Command
    U08 a;
        for (a = 0;a<0x06;a++)
                {
                  SD_write_byte(*cmd++);
                }

        //get 16 bit response
        while (tmp == 0xff)       
                {
                tmp = SD_read_byte();//Only last 8 bit is used here.Read it out.
                if (Timeout++ > 500){break;}
                }
        return(tmp);
}1.2cmd55和41反复发送 Timeout = 0;
            //-------发卡初始化指令CMD55+ACMD41------------------------------
             do
             {
                                //-----2.1.3---- send CMD55---------
                        CMD=0x40+55;
                        CMD=0x00;CMD=0x00;
                        CMD=0x00;
                        CMD=0x00;
                        CMD=0x00;
                        r1 = SD_write_command(CMD);//不判断cmd55的应答
                        if(SD_Debug_On==1){Uart_SendB(0xbc);Uart_SendB(0x55);Uart_SendB(r1);Uart_SendB(Timeout);Uart_SendB(0xbb);}                        //ok输出==================
                       
             // if(r1!=0x01)
             // {
             //Uart_SendB(0xd3); Uart_SendB(r1);////将应答发送出来。---------zj-------------------
             //return 0x55; //CMD55 Error!0x55
             // }

                        //-----2.1.4---- send CMD41---------

                        CMD=0x40+41;
                        CMD=0x40;
                        CMD=0x00;
                        CMD=0x00;
                        CMD=0x00;
                        CMD=0x00;//网上有人对 CMD41初始化不成功,crc改成0x95成功了。
                r1 = SD_write_command(CMD);
                        Timeout++;
                      if(Timeout>200)   
                      {
                                                if(SD_Debug_On==1){Uart_SendB(0xac);Uart_SendB(0x41);Uart_SendB(r1);Uart_SendB(Timeout);Uart_SendB(0xab);}//错误输出=============///将应答发送出来。---------zj-------------------
                                                return 0x41; //超时则返回CMD41 Error!0x41
                      }
                        if(SD_Debug_On==1){Uart_SendB(0xbc);Uart_SendB(0x41);Uart_SendB(r1);Uart_SendB(Timeout);Uart_SendB(0xbb);        }                //ok输出==================               
             }while(r1!=0);//进队CMD41响应判断2=不能应答的===============为什么?==

2.1 发送命令和应答函数//============================================================
//检测SD卡的响应
unsigned char SD_Response(void)
{
    unsigned response=0xff;
        unsigned int i=0;
   
    while((i<=500))//& (response!=0xff))
    {
      response = SD_read_byte();
               
      if(response==0x00)
      break;
      else if(response==0x01)
      break;
                else if(response==0x05)
      break;
         
      i++;
    }
    return response;
}
//================================================================
//发命令到SD卡
void SD_Cmd(unsigned char command, unsigned long argument, unsigned char CRC)
{
        SD_Disable();      //SD_CS = HIGH
        SD_write_byte(0xFF); //send 8 Clock Impulse
       
        SD_Enable();         //SD_CS = LOW
    SD_write_byte(command|0x40);
    SD_write_byte(((unsigned char *)&argument));
    SD_write_byte(((unsigned char *)&argument));
    SD_write_byte(((unsigned char *)&argument));
    SD_write_byte(((unsigned char *)&argument));
    SD_write_byte(CRC);
}2.2cmd41和55do
             {
                        //- 1)------ send CMD55---------

                        SD_Cmd(55,0,0xff);//cmd55
                        r1 =SD_Response();//不判断cmd55的应答
                        //if(SD_Debug_On==1){Uart_SendB(0xbc);Uart_SendB(0x55);Uart_SendB(r1);Uart_SendB(Timeout);Uart_SendB(0xbb);}                        //ok输出==================
                       
             if(r1!=0x01)
                {
             if(SD_Debug_On==1){Uart_SendB(0xbc);Uart_SendB(0x55);Uart_SendB(r1);Uart_SendB(Timeout);Uart_SendB(0xbb);}        ////将应答发送出来。---------zj-------------------
             //return 0x55; //CMD55 Error!0x55
             }

                        //- 2)-------- send CMD41---------
                        SD_Cmd(41,0x40000000,0x95);//cmd41//网上有人对 CMD41初始化不成功,crc改成0x95成功了。
                        r1 =SD_Response();//

                        Timeout++;
                      if(Timeout>250)   
                      {
                                                if(SD_Debug_On==1){Uart_SendB(0xac);Uart_SendB(0x41);Uart_SendB(r1);Uart_SendB(Timeout);Uart_SendB(0xab);}//错误输出=============///将应答发送出来。---------zj-------------------
                                               SD_Disable();//SD_CS = high
                                                return 0x41; //超时则返回CMD41 Error!0x41
                      }
                        //if(SD_Debug_On==1){Uart_SendB(0xbc);Uart_SendB(0x41);Uart_SendB(r1);Uart_SendB(Timeout);Uart_SendB(0xbb);        }                //ok输出==================               
             }while(r1!=0);//进队CMD41响应判断

jazsmile 发表于 2012-8-10 20:40:24

仅是修改了命令发送方式,就造成了这样的情况。

之前的函数从反馈结果看 只需要循环发送 cmd55,41 3次就可实现。

jazsmile 发表于 2012-8-10 23:46:14

====================================================ing

mangoes 发表于 2012-8-11 08:13:31

3个不是绝对,这个和时间有点关系,我这边不管是SD2.0还是3.0的SDHC卡上电后第一次初始化都要发送几十至几百毫秒,其中CMD55 和 ACMD41占了80~90%的时间,估计有50~60 CMD55+ ACMD41这样的组合,但是上电后第二次初始化仅仅只需要发送一次就Busy =1。找找之前备份的代码,用排除法定位问题出在哪里吧。

jazsmile 发表于 2012-8-11 12:15:18

mangoes 发表于 2012-8-11 08:13 static/image/common/back.gif
3个不是绝对,这个和时间有点关系,我这边不管是SD2.0还是3.0的SDHC卡上电后第一次初始化都要发送几十至几 ...

谢谢。

我的cmd0,cmd8都可以。

就是cmd41卡着了。采用原来的方法, 3-5次即可。

jazsmile 发表于 2012-8-11 12:16:24

继续调试。看看原因。

mangoes 发表于 2012-8-11 16:11:02

jazsmile 发表于 2012-8-11 12:15 static/image/common/back.gif
谢谢。

我的cmd0,cmd8都可以。


刚刚测试了一下,ACMD41 的设置不正确的话无论发送多少ACMD41 Busy都不会等于1的,估计是你的命令参数有问题,改成这个试试0x51fc0000。

jazsmile 发表于 2012-8-11 16:24:42

mangoes 发表于 2012-8-11 16:11 static/image/common/back.gif
刚刚测试了一下,ACMD41 的设置不正确的话无论发送多少ACMD41 Busy都不会等于1的,估计是你的命令 ...

谢谢。

修改了 命令函数
r1=SD_SendCommand_NoDeassert(41,0x40000000,0xff);
2--5次成功。

对 读和写都操作了,但是不能同时实现读和写的功能。郁闷!!//================================================================//
U08 SD_SendCommand_NoDeassert(U08cmd, U32 arg, U08crc)
{
    unsigned char r1;
    unsigned char Retry = 0;

    //
    SD_write_byte(0xff);
    //片选端置低,选中SD卡
    SD_Enable();

    //发送
    SD_write_byte(cmd | 0x40);                         //分别写入命令
    SD_write_byte(arg >> 24);
    SD_write_byte(arg >> 16);
    SD_write_byte(arg >> 8);
    SD_write_byte(arg);
    SD_write_byte(crc);
   
    //等待响应,或超时退出
    while((r1 = SD_read_byte())==0xFF)
    {
      Retry++;
      if(Retry > 200)
      {
            break;
      }
    }
    //返回响应值
    return r1;
}

jazsmile 发表于 2012-8-11 16:27:24

mangoes 发表于 2012-8-11 16:11 static/image/common/back.gif
刚刚测试了一下,ACMD41 的设置不正确的话无论发送多少ACMD41 Busy都不会等于1的,估计是你的命令 ...

能否测试一下我的功能。

我的读和写不能同时实现。能否我将代码发给你,你看看在你的板子上能否成功。

我用的是sdhc卡
已经测试,1初始化成功。2,读成功;3写成功。

问题:读和写在一起就不行了。


能否在你板子上帮我测试下。谢谢。我将代码给你。

你的sd卡片选是多少?

mangoes 发表于 2012-8-11 16:43:37

jazsmile 发表于 2012-8-11 16:27 static/image/common/back.gif
能否测试一下我的功能。

我的读和写不能同时实现。能否我将代码发给你,你看看在你的板子上能否成功。


很抱歉,我的板子是STM32 SDIO模式的。至于SPI模式,这个没有调过。CMD17、18、24、25返回的Response是卡的状态寄存器的数值,可以通过这个状态寄存器配合原版SD2.0规格书来排查问题。这个寄存器可以记录很多错误的原因.

mangoes 发表于 2012-8-11 16:47:34

jazsmile 发表于 2012-8-11 16:27 static/image/common/back.gif
能否测试一下我的功能。

我的读和写不能同时实现。能否我将代码发给你,你看看在你的板子上能否成功。


建议看英文的。第84页,4.10.1 Card Status 章节 里面有详细的说明这个寄存器每个Bit的意义

jazsmile 发表于 2012-8-11 16:47:58

mangoes 发表于 2012-8-11 16:43 static/image/common/back.gif
很抱歉,我的板子是STM32 SDIO模式的。至于SPI模式,这个没有调过。CMD17、18、24、25返回的Response是卡 ...

谢谢!

我的读是 cmd17,

写是cmd25。 其它没有用。

返回都是符合sd协议的。因为我用串口监测每个步骤的返回和结果。

jazsmile 发表于 2012-8-11 16:48:45

mangoes 发表于 2012-8-11 16:47 static/image/common/back.gif
建议看英文的。第84页,4.10.1 Card Status 章节 里面有详细的说明这个寄存器每个Bit的意义 ...

好的。我认真看看!

谢谢!!

jazsmile 发表于 2012-8-11 17:13:30

mangoes 发表于 2012-8-11 16:47 static/image/common/back.gif
建议看英文的。第84页,4.10.1 Card Status 章节 里面有详细的说明这个寄存器每个Bit的意义 ...

card status 怎么有32位。

实际在做的时候仅用了8位啊。

mangoes 发表于 2012-8-11 18:34:27

本帖最后由 mangoes 于 2012-8-11 18:40 编辑

jazsmile 发表于 2012-8-11 17:13 static/image/common/back.gif
card status 怎么有32位。

实际在做的时候仅用了8位啊。

你说的是高8位对吧?每个命令(command)以及响应(Response)长度都为48Bit(除R2外,即CMD2、CMD9、CMD10的响应),其中高8位为start bit + 方向 (1=command 0=reaponse) + CMD Index,中间32位为command或者reposne的参数.最后8为中有7位是CRC7 以及1Bit是Stop Bit,而返回类型为R1的所有response中间的32bit参数都是card status 寄存器。

yfgww 发表于 2012-9-24 13:37:06

{:smile:}{:smile:}{:smile:}{:smile:}

banruoxiaoyi 发表于 2013-4-11 11:29:32

我最近在搞sdio读sd卡,sdio是模拟的,现在标准sd卡是读写没问题的,但是sdhc读总是出问题,卡上电第一次读是正确的,之后读就会出错,跟楼主的情况一样吗?楼主留个联系方式,请教一下 我qq1035548005般若
页: [1]
查看完整版本: SDHC卡CMD41应答01。为什么?