[STM32F0] SDHC卡初始化问题

[复制链接]
 楼主| shashaa 发表于 2017-10-30 22:01 | 显示全部楼层 |阅读模式

我现在在弄读写TF卡,我发CMD0、CMD55、ACMD41返回值没错;不过发CMD8时,V1.x的卡返回0xFF,V2.0的卡返回0x01;2.0的卡前几个命令没错,但发到CMD58时出错了,返回0xFF。我还有一个F149的开发板,SD卡能读写,但SDHC卡也一样,也是在CMD58那返回0xFF,请问我该怎么解决,求大神指教!
qiangweii 发表于 2017-10-30 22:07 | 显示全部楼层
以前使用stm32读写tf卡,太大了就报错。
litengg 发表于 2017-10-30 22:07 | 显示全部楼层
是不是没有识别出sd卡的存在?
androidbus 发表于 2017-10-30 22:10 | 显示全部楼层
litengg 发表于 2017-10-30 22:07
是不是没有识别出sd卡的存在?

应该不是,要是没有识别出SD卡,那前几个命令的返回值应该都不对
feiqi1 发表于 2017-10-30 22:11 | 显示全部楼层

好像D卡只响应CMD8。
xia00 发表于 2017-10-30 22:14 | 显示全部楼层
CMD8返回第一字节是 判断是否为V2.0
hfdy01 发表于 2017-10-30 22:14 | 显示全部楼层
CMD8是在SD V2.0才出有的
CallReceiver 发表于 2017-10-30 22:18 | 显示全部楼层
没有必要判断sd卡类型吧。
boy1990 发表于 2017-10-30 22:18 | 显示全部楼层
跳过这个命令读写也不成功,所以我就想是不是初始化阶段哪里出了问题
 楼主| shashaa 发表于 2017-10-30 22:21 | 显示全部楼层

程序如下:
/***********************************************************************
函数功能:MMC/SD卡初始化
操作内容:1、拉高CS片选和MOSI至少74个时钟周期
          2、SPI发送10个FF
***********************************************************************/
uchar initMMC (void)
{
  int i;
  
  initSPI();
  CS_HIGH();
  for(i=0;i<=9;i++)
    spiSendByte(0xff);

  return (mmc_GoIdle());
}

/***********************************************************************
函数功能:MMC/SD卡空闲模式及初始化
操作内容:1、初始化MMC/SD卡工作在SPI模式,无论MMC还是SD卡都发送CMD0
          2、判断MMC卡还是SD卡
          3、SD卡循环10次发送CMD55+ACMD41,MMC卡发送CMD1
***********************************************************************/
char mmc_GoIdle()
{
  char response;
  unsigned char i;
  unsigned char sdcard=0x00;                                       //SD卡标志位,为0表示SDV1.x卡,为1表示为MMC卡,为2表示为SDHC卡,为3表示为SDV2.x卡
  CS_LOW();                                                        //选中MMC/SD卡,片选有效,接下来发送命令
  mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);                            //发送CMD0,MMC/SD卡设置为SPI模式,0x95为CRC值
  //Now wait for READY RESPONSE
  if(mmcGetResponse()!=0x01)
    return MMC_INIT_ERROR;
  else                                                                                           //bitIDLE=1
  {
        mmcSendCmd(MMC_CID,0x1aa,0x87);                                        //发送CMD8,判断SD卡版本
        response=mmcGetResponse();
        if(response != 0x01)                                                        //如果卡片版本信息是v1.0版本的,即response=0x05
        {
                CS_HIGH();
                spiSendByte(0xff);
                CS_LOW();
                if(sdcard==0x00)                                //先识别是否为SD卡,发送SD卡命令CMD55+ACMD41
                {
                        for(i=0;i<10;i++)                              //循环10次,如果为SD卡,一般2次即可正确返回0x00
                        {
                                mmcSendCmd(SD_APP_COND,0x00,0xff);            //发送SD卡判断命令,如果成功返回0x00,则为SD卡
                                while(response=mmcGetResponse()!=0x01);       //返回值为0x01,则表示处于空闲状态,再发ACMD41命令
   
                                mmcSendCmd(SD_APP_OP_COND,0x00,0xff);         //发送ACMD41命令
                                if(response=mmcGetResponse()==0x00)           //返回值为0x00,则初始化成功,否则使用MMC命令CMD1继续初始化
                                {
                                  CS_HIGH();
                                  spiSendByte(0xff);
                                  return MMC_SUCCESS;                        
                                }
                        }
                        sdcard=0x01;                                   //为1表示SD卡命令无效,卡为MMC卡,准备下面发送CMD1命令
                }
                i=0;                                                        
                do                                                        //准备发送MMC卡命令CMD1
                {
                        mmcSendCmd(MMC_SEND_OP_COND,0x00,0xff);       //发送MMC卡CMD1命令,成功则返回0x00
                        response=mmcGetResponse();                    //返回值为0x00,则表示MMC卡初始化成功
                        i++;
                }while((response!=0x00)&& (i<10));
                if(i==10)
                        return MMC_INIT_ERROR;
                else
                {
                        CS_HIGH();                                      //MMC/SD卡片选无效
                        spiSendByte(0xff);
                        return MMC_SUCCESS;                           
                }
        }
        else
        {                                                                //V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令
                buff[0] = spiSendByte(0xff);                                  //should be 0x00
                buff[1] = spiSendByte(0xff);                                  //should be 0x00
                buff[2] = spiSendByte(0xff);                                  //should be 0x01
                buff[3] = spiSendByte(0xff);                                  //should be 0xAA
                CS_HIGH();                                 
                spiSendByte(0xff);
                if(buff[2]==0x01&&buff[3]==0xAA)                                //判断该卡是否支持2.7V-3.6V的电压范围
                {
                        CS_LOW();
                        i=0;                                                     
                        while((response!=0x00)&& (i<10))                                //循环10次,如果为SD卡,一般2次即可正确返回0x00        
                        {                                                                                                //发送SD卡判断命令,如果成功返回0x00,则为SD卡
                                mmcSendCmd(SD_APP_COND,0x00,0xff);            //发送CMD55
                                while(response=mmcGetResponse()!=0x01);       //返回值为0x01,则表示处于空闲状态,再发ACMD41命令
   
                                mmcSendCmd(SD_APP_OP_COND,0x40000000,0xff);         //发送ACMD41命令
                                i++;
                        }
                        if(i==10)
                                return MMC_INIT_ERROR;
                        else
                        {
                                mmcSendCmd(0x7a,0,0);                                        //发送CMD58,获取OCR信息
                                response=mmcGetResponse();
                                if(response!=0x00)
                                {
                                        CS_HIGH();  
                                        return MMC_RESPONSE_ERROR;
                                }
                                else
                                {                                                        //读OCR指令发出后,紧接着是4字节的OCR信息
                                        buff[0] = spiSendByte(0xff);                                 
                                        buff[1] = spiSendByte(0xff);                                 
                                        buff[2] = spiSendByte(0xff);                                 
                                        buff[3] = spiSendByte(0xff);
                                        CS_HIGH();                                          //OCR接收完成,片选置高
                                        spiSendByte(0xff);
                                        //检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC
                                        //如果CCS=1:SDHC   CCS=0:SD2.0SD
                                        if(buff[0]&0x40)
                                        {
                                                sdcard=0x02;
                                                return MMC_SUCCESS;
                                        }                                                               
                                        else
                                        {
                                                sdcard=0x03;
                                                return MMC_RESPONSE_ERROR;        
                                        }               
                                }
                        }
                        //else return MMC_SUCCESS;                                                  
                }
        }
  }
}
 楼主| shashaa 发表于 2017-10-30 22:22 | 显示全部楼层

程序如下:
/***********************************************************************
函数功能:MMC/SD卡初始化
操作内容:1、拉高CS片选和MOSI至少74个时钟周期
          2、SPI发送10个FF
***********************************************************************/
uchar initMMC (void)
{
  int i;
  
  initSPI();
  CS_HIGH();
  for(i=0;i<=9;i++)
    spiSendByte(0xff);

  return (mmc_GoIdle());
}

/***********************************************************************
函数功能:MMC/SD卡空闲模式及初始化
操作内容:1、初始化MMC/SD卡工作在SPI模式,无论MMC还是SD卡都发送CMD0
          2、判断MMC卡还是SD卡
          3、SD卡循环10次发送CMD55+ACMD41,MMC卡发送CMD1
***********************************************************************/
char mmc_GoIdle()
{
  char response;
  unsigned char i;
  unsigned char sdcard=0x00;                                       //SD卡标志位,为0表示SDV1.x卡,为1表示为MMC卡,为2表示为SDHC卡,为3表示为SDV2.x卡
  CS_LOW();                                                        //选中MMC/SD卡,片选有效,接下来发送命令
  mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);                            //发送CMD0,MMC/SD卡设置为SPI模式,0x95为CRC值
  //Now wait for READY RESPONSE
  if(mmcGetResponse()!=0x01)
    return MMC_INIT_ERROR;
  else                                                                                           //bitIDLE=1
  {
        mmcSendCmd(MMC_CID,0x1aa,0x87);                                        //发送CMD8,判断SD卡版本
        response=mmcGetResponse();
        if(response != 0x01)                                                        //如果卡片版本信息是v1.0版本的,即response=0x05
        {
                CS_HIGH();
                spiSendByte(0xff);
                CS_LOW();
                if(sdcard==0x00)                                //先识别是否为SD卡,发送SD卡命令CMD55+ACMD41
                {
                        for(i=0;i<10;i++)                              //循环10次,如果为SD卡,一般2次即可正确返回0x00
                        {
                                mmcSendCmd(SD_APP_COND,0x00,0xff);            //发送SD卡判断命令,如果成功返回0x00,则为SD卡
                                while(response=mmcGetResponse()!=0x01);       //返回值为0x01,则表示处于空闲状态,再发ACMD41命令
   
                                mmcSendCmd(SD_APP_OP_COND,0x00,0xff);         //发送ACMD41命令
                                if(response=mmcGetResponse()==0x00)           //返回值为0x00,则初始化成功,否则使用MMC命令CMD1继续初始化
                                {
                                  CS_HIGH();
                                  spiSendByte(0xff);
                                  return MMC_SUCCESS;                        
                                }
                        }
                        sdcard=0x01;                                   //为1表示SD卡命令无效,卡为MMC卡,准备下面发送CMD1命令
                }
                i=0;                                                        
                do                                                        //准备发送MMC卡命令CMD1
                {
                        mmcSendCmd(MMC_SEND_OP_COND,0x00,0xff);       //发送MMC卡CMD1命令,成功则返回0x00
                        response=mmcGetResponse();                    //返回值为0x00,则表示MMC卡初始化成功
                        i++;
                }while((response!=0x00)&& (i<10));
                if(i==10)
                        return MMC_INIT_ERROR;
                else
                {
                        CS_HIGH();                                      //MMC/SD卡片选无效
                        spiSendByte(0xff);
                        return MMC_SUCCESS;                           
                }
        }
        else
        {                                                                //V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令
                buff[0] = spiSendByte(0xff);                                  //should be 0x00
                buff[1] = spiSendByte(0xff);                                  //should be 0x00
                buff[2] = spiSendByte(0xff);                                  //should be 0x01
                buff[3] = spiSendByte(0xff);                                  //should be 0xAA
                CS_HIGH();                                 
                spiSendByte(0xff);
                if(buff[2]==0x01&&buff[3]==0xAA)                                //判断该卡是否支持2.7V-3.6V的电压范围
                {
                        CS_LOW();
                        i=0;                                                     
                        while((response!=0x00)&& (i<10))                                //循环10次,如果为SD卡,一般2次即可正确返回0x00        
                        {                                                                                                //发送SD卡判断命令,如果成功返回0x00,则为SD卡
                                mmcSendCmd(SD_APP_COND,0x00,0xff);            //发送CMD55
                                while(response=mmcGetResponse()!=0x01);       //返回值为0x01,则表示处于空闲状态,再发ACMD41命令
   
                                mmcSendCmd(SD_APP_OP_COND,0x40000000,0xff);         //发送ACMD41命令
                                i++;
                        }
                        if(i==10)
                                return MMC_INIT_ERROR;
                        else
                        {
                                mmcSendCmd(0x7a,0,0);                                        //发送CMD58,获取OCR信息
                                response=mmcGetResponse();
                                if(response!=0x00)
                                {
                                        CS_HIGH();  
                                        return MMC_RESPONSE_ERROR;
                                }
                                else
                                {                                                        //读OCR指令发出后,紧接着是4字节的OCR信息
                                        buff[0] = spiSendByte(0xff);                                 
                                        buff[1] = spiSendByte(0xff);                                 
                                        buff[2] = spiSendByte(0xff);                                 
                                        buff[3] = spiSendByte(0xff);
                                        CS_HIGH();                                          //OCR接收完成,片选置高
                                        spiSendByte(0xff);
                                        //检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC
                                        //如果CCS=1:SDHC   CCS=0:SD2.0SD
                                        if(buff[0]&0x40)
                                        {
                                                sdcard=0x02;
                                                return MMC_SUCCESS;
                                        }                                                               
                                        else
                                        {
                                                sdcard=0x03;
                                                return MMC_RESPONSE_ERROR;        
                                        }               
                                }
                        }
                        //else return MMC_SUCCESS;                                                  
                }
        }
  }
}
bbapple 发表于 2017-10-30 22:24 | 显示全部楼层
CMD8返回第一字节是 判断是否为V2.0
handleMessage 发表于 2017-10-30 22:30 | 显示全部楼层

楼上分享的代码看着还是蛮复杂的
zhouhuanの 发表于 2017-10-30 22:31 | 显示全部楼层

不知道会不会是硬件哪里有问题而导致的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

142

主题

1494

帖子

6

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