[STM32F1] SPI SD卡初始化 ACMD41 返回0x05 无法初始化

[复制链接]
6202|17
 楼主| qxs773@163.com 发表于 2015-6-7 09:09 | 显示全部楼层 |阅读模式
我用的STM32F103C8,SPI模式 进**初始化,代码如下:
//设置SPI速度为低速
        SPI_SetSpeed(0);


    //先产生>74个脉冲,让SD卡自己初始化完成
    for(i=0;i<10;i++)
    {
        SPI_ReadWriteByte(0xFF);
    }

    //-----------------SD卡复位到idle开始-----------------
    //循环连续发送CMD0,直到SD卡返回0x01,进入IDLE状态
    //超时则直接退出
    retry = 0;
    do
    {
        //发送CMD0,让SD卡进入IDLE状态
        r1 = SD_SendCommand(CMD0, 0, 0x95);
        retry++;
    }while((r1 != 0x01) && (retry<200));
    //跳出循环后,检查原因:初始化成功?or 重试超时?

    if(retry==200)
    {        ///sd.errer=1;
        return 1;   //超时返回1  
    }
    //-----------------SD卡复位到idle结束-----------------



    //获取卡片的SD版本信息
    r1 = SD_SendCommand_NoDeassert(8, 0x1aa, 0x87);
    if(r1 == 0x01)
    {
        //V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令
        buff[0] = SPI_ReadWriteByte(0xFF);  //should be 0x00
        buff[1] = SPI_ReadWriteByte(0xFF);  //should be 0x00
        buff[2] = SPI_ReadWriteByte(0xFF);  //should be 0x01
        buff[3] = SPI_ReadWriteByte(0xFF);  //should be 0xAA
     
        SD_CS_DISABLE();
        //the next 8 clocks
        SPI_ReadWriteByte(0xFF);
                       
               
        //判断该卡是否支持2.7V-3.6V的电压范围
        if(buff[2]==0x01 && buff[3]==0xAA)
        {
            //支持电压范围,可以操作
            retry = 0;
            //发卡初始化指令CMD55+ACMD41
                                                do
                                                {
                                                                r1 = SD_SendCommand(CMD55, 0, 0);
                                                                if(r1!=0x01)
                                                                {
                                                                        return r1;
                                                                }
                                                    //for(i=0;i<0xff;i++);
                                                                r1 = SD_SendCommand(ACMD41, 0x40000000, 0);    //此处ACMD41 总是返回 0x05 SD卡命令错误
                                                                if(retry>400)   
                                                                {        ///sd.errer=r1;
                                                                                return r1;  //超时则返回r1状态
                                                                }
                                                                retry++;
                                                 }while(r1!=0  );
                                               
            //初始化指令发送完成,接下来获取OCR信息

            //-----------鉴别SD2.0卡版本开始-----------
            r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
            if(r1!=0x00)
            {        ///sd.errer=r1;
                return r1;  //如果命令没有返回正确应答,直接退出,返回应答
            }
            //读OCR指令发出后,紧接着是4字节的OCR信息
            buff[0] = SPI_ReadWriteByte(0xFF);
            buff[1] = SPI_ReadWriteByte(0xFF);
            buff[2] = SPI_ReadWriteByte(0xFF);
            buff[3] = SPI_ReadWriteByte(0xFF);

            //OCR接收完成,片选置高
            SD_CS_DISABLE();
            SPI_ReadWriteByte(0xFF);

            //检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC
            //如果CCS=1:SDHC   CCS=0:SD2.0
            if(buff[0]&0x40)    //检查CCS
            {
                SD_Type = SD_TYPE_V2HC;
            }
            else
            {
                SD_Type = SD_TYPE_V2;
            }
            //-----------鉴别SD2.0卡版本结束-----------
         
            //设置SPI为高速模式
            SPI_SetSpeed(1);  
        }

现在的情况 是 我用三种SD卡测试,有两种可以初始化成功,步步高手机的2G卡可以初始化成功,还有一张卡叫不上型号来(也是手机带的)也可以初始化成功,Kingston的2G卡就不成功,ACMD41返回0x05,请教大神有没有人遇到过这种情况呢,应该怎么解决呢?
是不是金士顿的SD卡初始化命令与其它卡不一样?不应该吧。
求救。。。。
 楼主| qxs773@163.com 发表于 2015-6-7 09:12 | 显示全部楼层
是否与SD卡初始化有关呢,SPI速度也已经用的是最慢的啦

/* Enable SPI1 and GPIO clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1|RCC_APB2Periph_AFIO, ENABLE);

  /* Configure SPI1 pins: SCK, MISO and MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;//SPI_SCK,SPI_MISO,SPI_MOSI
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//
  GPIO_Init(GPIOA, &GPIO_InitStructure);
/* SPI1 configuration */
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//低速模式
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);

  /* Enable SPI1  */
  SPI_Cmd(SPI1, ENABLE);
airwill 发表于 2015-6-7 18:09 | 显示全部楼层
从 SD 卡的协议看, 这应该是多媒体卡. 上传一份 SD 卡资料你详细研究一下.
SD卡MiniSD卡与MicroSD卡的引脚定义等资料.pdf (422.17 KB, 下载次数: 75)
 楼主| qxs773@163.com 发表于 2015-6-8 09:33 | 显示全部楼层
airwill 发表于 2015-6-7 18:09
从 SD 卡的协议看, 这应该是多媒体卡. 上传一份 SD 卡资料你详细研究一下.

miniSD卡和MicroSD 卡的协议不一样吗?
能给详细说一下吗?
你的意思是我要更改初始化协议吗?
309030106 发表于 2015-6-12 21:11 | 显示全部楼层
硬件有没有问题呢
yuezhongliang 发表于 2015-10-20 11:42 | 显示全部楼层
问题解决了吗?我也是相同的问题。头大。
lytga 发表于 2015-11-10 22:41 | 显示全部楼层
请问解决了吗,我也是同样问题
清风化雪 发表于 2016-1-12 11:30 | 显示全部楼层
这个是你的CRC设置错误 SD_SendCommand(CMD55, 0, 0)和r1 = SD_SendCommand(ACMD41, 0x40000000, 0);
改成 SD_SendCommand(CMD55, 0, 1)和r1 = SD_SendCommand(ACMD41, 0x40000000, 1); 就可以了
 楼主| qxs773@163.com 发表于 2016-4-4 10:54 | 显示全部楼层
这么久了,近来又拿出板子来又试了试,慢慢调度时发现。 SDV2.0的卡也有 MMC之说? 不理解 ,但是我把MMC卡的命令放在这可以返回正确的回应,初始化可以正常通过 ,并且后面对SD进行读写也可以,但是 读写速率明显要慢很多,很多。
不知道 这样子做法对不对呢。
//判断该卡是否支持2.7V-3.6V的电压范围
        if(buff[2]==0x01 && buff[3]==0xAA)
        {
                                                retry = 0;
                                                do
                                                {
                                                                r1 = SD_SendCommand(CMD55, 0, 0);                        //先发CMD55,应返回0x01;否则出错
                                                                if(r1 != 0x01)
                                                                {       
                                                                                return r1;  
                                                                }
                                                                for(i=0;i<0x800;i++);
                                                                r1 = SD_SendCommand(ACMD41,0x40000000,0x00);
                                                                retry++;
                                                }while((r1!=0x00) && (retry<400));



                                {                                               
                                                // 判断是超时还是得到正确回应
                                                // 若有回应:是SD卡;没有回应:是MMC卡
                                                //----------MMC卡额外初始化操作开始------------
                                                if(retry>=400)
                                                {
                                                                retry = 0;
                                                                //发送MMC卡初始化命令(没有测试)
                                                                do
                                                                {
                                                                                r1 = SD_SendCommand(1, 0, 0);
                                                                                retry++;
                                                                }while((r1!=0x00)&& (retry<400));
                                                                if(retry>=400)
                                                                {       
                                                                                return 1;   //MMC卡初始化超时
                                                                }
                                                                //写入卡类型
                                                                SD_Type = SD_TYPE_MMC;
                                                }
                                        }
           
thytsx 发表于 2017-5-8 10:08 | 显示全部楼层
你好,不知道你现在是否还有在做spi读写sd卡,在acmd返回值这里出现了0x05的返回值,我也遇到了同样的问题,想请教一下你是怎么解决的
thytsx 发表于 2017-5-8 15:34 | 显示全部楼层
yuezhongliang 发表于 2015-10-20 11:42
问题解决了吗?我也是相同的问题。头大。

你的解决了吗,我遇到同样的问题
yujielun 发表于 2017-5-8 17:24 | 显示全部楼层
无法初始化,检查不到存在。
yujielun 发表于 2017-5-8 17:26 | 显示全部楼层
SPI SD卡初始化的时候是否读取判断SD存在的卡吗?
wzszzxj 发表于 2017-5-11 15:02 | 显示全部楼层
我的也是
wzszzxj 发表于 2017-5-11 15:04 | 显示全部楼层
我的也是卡在这里ACMD41返回0X05,头不是一般的大!! 照文档说是非法命令?!
wzszzxj 发表于 2017-5-11 16:37 | 显示全部楼层
天亮了,好了
huangyanga 发表于 2017-7-15 17:05 | 显示全部楼层
怎么好的呢,楼主
814297 发表于 2020-4-22 16:51 | 显示全部楼层
huangyanga 发表于 2017-7-15 17:05
怎么好的呢,楼主

CMD55必须在ACMD41前面发,不能单独或反复单独发ACMD41,
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

49

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部