打印
[STM32F1]

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

[复制链接]
5261|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)

使用特权

评论回复
地板
qxs773@163.com|  楼主 | 2015-6-8 09:33 | 只看该作者
airwill 发表于 2015-6-7 18:09
从 SD 卡的协议看, 这应该是多媒体卡. 上传一份 SD 卡资料你详细研究一下.

miniSD卡和MicroSD 卡的协议不一样吗?
能给详细说一下吗?
你的意思是我要更改初始化协议吗?

使用特权

评论回复
5
309030106| | 2015-6-12 21:11 | 只看该作者
硬件有没有问题呢

使用特权

评论回复
6
yuezhongliang| | 2015-10-20 11:42 | 只看该作者
问题解决了吗?我也是相同的问题。头大。

使用特权

评论回复
7
lytga| | 2015-11-10 22:41 | 只看该作者
请问解决了吗,我也是同样问题

使用特权

评论回复
8
清风化雪| | 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); 就可以了

使用特权

评论回复
9
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;
                                                }
                                        }
           

使用特权

评论回复
10
thytsx| | 2017-5-8 10:08 | 只看该作者
你好,不知道你现在是否还有在做spi读写sd卡,在acmd返回值这里出现了0x05的返回值,我也遇到了同样的问题,想请教一下你是怎么解决的

使用特权

评论回复
11
thytsx| | 2017-5-8 15:34 | 只看该作者
yuezhongliang 发表于 2015-10-20 11:42
问题解决了吗?我也是相同的问题。头大。

你的解决了吗,我遇到同样的问题

使用特权

评论回复
12
yujielun| | 2017-5-8 17:24 | 只看该作者
无法初始化,检查不到存在。

使用特权

评论回复
13
yujielun| | 2017-5-8 17:26 | 只看该作者
SPI SD卡初始化的时候是否读取判断SD存在的卡吗?

使用特权

评论回复
14
wzszzxj| | 2017-5-11 15:02 | 只看该作者
我的也是

使用特权

评论回复
15
wzszzxj| | 2017-5-11 15:04 | 只看该作者
我的也是卡在这里ACMD41返回0X05,头不是一般的大!! 照文档说是非法命令?!

使用特权

评论回复
16
wzszzxj| | 2017-5-11 16:37 | 只看该作者
天亮了,好了

使用特权

评论回复
17
huangyanga| | 2017-7-15 17:05 | 只看该作者
怎么好的呢,楼主

使用特权

评论回复
18
814297| | 2020-4-22 16:51 | 只看该作者
huangyanga 发表于 2017-7-15 17:05
怎么好的呢,楼主

CMD55必须在ACMD41前面发,不能单独或反复单独发ACMD41,

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

48

帖子

4

粉丝