SDHC卡初始化

[复制链接]
3089|26
 楼主| joyxysetu 发表于 2017-10-12 10:39 | 显示全部楼层 |阅读模式
我现在在弄读写TF卡,用的是MSP430F5342,我发CMD0、CMD55、ACMD41返回值没错;不过发CMD8时,V1.x的卡返回0xFF,V2.0的卡返回0x01;2.0的卡前几个命令没错,但发到CMD58时出错了,返回0xFF。我还有一个F149的开发板,SD卡能读写,但SDHC卡也一样,也是在CMD58那返回0xFF,请问我该怎么解决,求大神指教!
wengh2016 发表于 2017-10-12 21:38 | 显示全部楼层
使用是FATFS吗
suzhanhua 发表于 2017-10-12 21:38 | 显示全部楼层
以前使用stm32读写tf卡,太大了就报错。
wengh2016 发表于 2017-10-12 21:39 | 显示全部楼层
是不是没有识别出sd卡的存在?
suzhanhua 发表于 2017-10-12 21:39 | 显示全部楼层
 楼主| joyxysetu 发表于 2017-10-13 08:50 | 显示全部楼层

是FAT32的,FAT16的卡用F149的开发板能读写,FAT32的卡用F149和F5342的板都不行
 楼主| joyxysetu 发表于 2017-10-13 08:51 | 显示全部楼层
suzhanhua 发表于 2017-10-12 21:38
以前使用stm32读写tf卡,太大了就报错。

我的是用msp430的
 楼主| joyxysetu 发表于 2017-10-13 08:52 | 显示全部楼层
wengh2016 发表于 2017-10-12 21:39
是不是没有识别出sd卡的存在?

应该不是,要是没有识别出SD卡,那前几个命令的返回值应该都不对
 楼主| joyxysetu 发表于 2017-10-13 08:53 | 显示全部楼层
suzhanhua 发表于 2017-10-12 21:39
http://blog.sina.com.cn/s/blog_4f09c0b50101636h.html

这个的我看过了,程序也有参照这个
chenci2013 发表于 2017-10-13 21:57 | 显示全部楼层
不能判断类型?
mituzu 发表于 2017-10-13 21:58 | 显示全部楼层
好像D卡只响应CMD8。
51xlf 发表于 2017-10-13 21:59 | 显示全部楼层
CMD8返回第一字节是 判断是否为V2.0
chenci2013 发表于 2017-10-13 22:01 | 显示全部楼层
CMD8是在SD V2.0才出有的
mituzu 发表于 2017-10-13 22:01 | 显示全部楼层
没有必要判断sd卡类型吧。
51xlf 发表于 2017-10-13 22:02 | 显示全部楼层
楼主上传代码看看是什么原因
 楼主| joyxysetu 发表于 2017-10-14 10:11 | 显示全部楼层

对,前几个命令返回值都对,到cmd58就不对了
 楼主| joyxysetu 发表于 2017-10-14 10:12 | 显示全部楼层
mituzu 发表于 2017-10-13 22:01
没有必要判断sd卡类型吧。

跳过这个命令读写也不成功,所以我就想是不是初始化阶段哪里出了问题
 楼主| joyxysetu 发表于 2017-10-14 10:13 | 显示全部楼层
程序如下:
/***********************************************************************
函数功能: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;                                                 
                }
        }
  }
}
1223657347 发表于 2017-10-15 11:46 | 显示全部楼层
实际sd卡初始化的时候有的指令要多发几次才有响应,lz可以参考下我这个初始化代码
  1. /**
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url]  SDCard(SPI Mode) Initialization
  3.   * @param  None
  4.   * @retval Operation Result Depending on Response Token
  5.   */
  6. uint8_t SD_SPI_Init(void)
  7. {
  8.         uint8_t rs = SD_OK;
  9.         uint8_t sd_ver;
  10.         uint32_t i, tick_now;
  11.         SD_CMDTypeDef SD_CMD;
  12.         SD_R1TypeDef R1;
  13.         SD_R3TypeDef R3;
  14.         SD_R7TypeDef R7;
  15.        
  16.         if(SD_InitState != 0)
  17.         {
  18.                 goto DONE;
  19.         }
  20.        
  21.         //MSP Initialization
  22.         SD_SPI_MspInit();
  23.        
  24.         //Least then 400KHz
  25.         SD_NormalSpeed();
  26.        
  27.         //Delay for Power up
  28.         HAL_Delay(20);
  29.        
  30.         //In case of SPI mode, CS shall be held to high during 74 clock cycles
  31.         SD_CS_SET();
  32.        
  33.         for(i = 0; i < 8; i++)
  34.         {
  35.                 SD_WR_Byte(0xFF);
  36.         }
  37.        
  38.         //CMD0+, Goto idle State
  39.         tick_now = HAL_GetTick();
  40.        
  41.         do
  42.         {
  43.                 if((HAL_GetTick() - tick_now) > GOTO_IDLE_TIMEOUT)
  44.                 {
  45.                         //Timeout and Return
  46.                         rs = SD_TIMEOUT;
  47.                         goto DONE;
  48.                 }
  49.                
  50.                 SD_CMD.Cmd = GO_IDLE_STATE;
  51.                 SD_CMD.Arg = 0;
  52.                 SD_CMD.Crc = 0x95;
  53.                 rs = SD_W_CMD_R1(&SD_CMD, &R1);
  54.                
  55.                 if(rs == SD_OK)
  56.                 {
  57.                         if((R1 & R1_IDLE_STATE) == 0)
  58.                         {
  59.                                 rs = SD_ERROR;
  60.                         }
  61.                 }
  62.         }
  63.         while(rs != SD_OK);
  64.        
  65.         //CMD8, Sends SD Memory Card interface condition
  66.         SD_CMD.Cmd = SEND_IF_COND;
  67.         SD_CMD.Arg = 0x1AA;
  68.         SD_CMD.Crc = 0x87;
  69.         rs = SD_W_CMD_R7(&SD_CMD, &R7);
  70.        
  71.         if(rs != SD_OK)
  72.         {
  73.                 goto DONE;       
  74.         }
  75.        
  76.         if(R7.R1 & R1_IDLE_STATE)
  77.         {
  78.                 if(R7.R1 & R1_ILLEGAL_CMD)
  79.                 {
  80.                         //Ver1.X SD Menmory Card or Not SD Menmory Card
  81.                        
  82.                         sd_ver = SD_V1X_STANDARD_CAPACITY;
  83.                 }
  84.                 else
  85.                 {
  86.                         if((R7.VoltageAccepted != 0x01)||(R7.CheckPattern != 0xAA))
  87.                         {
  88.                                 rs = SD_ERROR;
  89.                                 goto DONE;
  90.                         }
  91.                        
  92.                         //Ver2.00 or later SD Memory Card
  93.                 }
  94.         }
  95.        
  96.         //Wait Card Ready
  97.         tick_now = HAL_GetTick();
  98.        
  99.         do
  100.         {
  101.                 if((HAL_GetTick() - tick_now) > CARD_READY_TIMEOUT)
  102.                 {
  103.                         rs = SD_TIMEOUT;
  104.                         goto DONE;
  105.                 }
  106.                
  107.                 //CMD55, Defines to the card that the next command is an application
  108.                 SD_CMD.Cmd = APP_CMD;
  109.                 SD_CMD.Arg = 0;
  110.                 SD_CMD.Crc = 0;
  111.                 rs = SD_W_CMD_R1(&SD_CMD, &R1);
  112.                
  113.                 if(rs != SD_OK)
  114.                 {
  115.                         goto DONE;
  116.                 }
  117.                
  118.                 if(R1 != R1_IDLE_STATE)
  119.                 {
  120.                         rs = SD_ERROR;
  121.                         goto DONE;
  122.                 }
  123.                
  124.                 //ACMD41, Sends host capacity support information and activates the card's initialization process.
  125.                 SD_CMD.Cmd = SD_SEND_OP_COND;
  126.                 if(sd_ver == SD_V1X_STANDARD_CAPACITY)
  127.                 {
  128.                         SD_CMD.Arg = 0<<30;
  129.                 }
  130.                 else
  131.                 {
  132.                         SD_CMD.Arg = 1<<30;
  133.                 }
  134.                 SD_CMD.Crc = 0;
  135.                 rs = SD_W_CMD_R1(&SD_CMD, &R1);
  136.                
  137.                 if(rs == SD_OK)
  138.                 {
  139.                         if(R1 & R1_IDLE_STATE)
  140.                         {
  141.                                 rs = SD_ERROR;
  142.                         }
  143.                 }
  144.         }
  145.         while(rs != SD_OK);
  146.        
  147.         //CMD58, Reads the OCR register
  148.         SD_CMD.Cmd = READ_OCR;
  149.         SD_CMD.Arg = 0;
  150.         SD_CMD.Crc = 0;
  151.         rs = SD_W_CMD_R3(&SD_CMD, &R3);
  152.        
  153.         if(rs != SD_OK)
  154.         {
  155.                 goto DONE;
  156.         }
  157.        
  158.         if(R3.R1 != 0)
  159.         {
  160.                 rs = SD_ERROR;
  161.                 goto DONE;
  162.         }
  163.        
  164.         if(R3.Ocr & 0x80000000ul)
  165.         {
  166.                 if(sd_ver != SD_V1X_STANDARD_CAPACITY)
  167.                 {
  168.                         if(R3.Ocr & (1<<30))
  169.                         {
  170.                                 sd_ver = SD_V2X_HIGH_CAPCITY;
  171.                         }
  172.                         else
  173.                         {
  174.                                 sd_ver = SD_V2X_STANDARD_CAPCITY;
  175.                         }
  176.                 }
  177.         }
  178.         else
  179.         {
  180.                 rs = SD_ERROR;
  181.                 goto DONE;
  182.         }
  183.        
  184.         SD_BurstSpeed();
  185.        
  186.         //CMD59, Turns the CRC option on or off.
  187.         SD_CMD.Cmd = CRC_ON_OFF;
  188.         SD_CMD.Arg = 0;
  189.         SD_CMD.Crc = 0;
  190.         rs = SD_W_CMD_R1(&SD_CMD, &R1);
  191.        
  192.         if(sd_ver < SD_V2X_HIGH_CAPCITY)
  193.         {
  194.                 //CMD16, In case of SDSC Card, block length is set by this command.
  195.                 SD_CMD.Cmd = SET_BLOCKLEN;
  196.                 SD_CMD.Arg = SD_BLOCK_SIZE;
  197.                 SD_CMD.Crc = 0;
  198.                 rs = SD_W_CMD_R1(&SD_CMD, &R1);
  199.         }
  200.        
  201.         SD_CardType = sd_ver;
  202.         SD_InitState = 1;
  203.        
  204. DONE:
  205.         return rs;       
  206. }

下面是类型定义
  1. #ifndef __SDCARD_SPI_HW_H
  2. #define __SDCARD_SPI_HW_H

  3. typedef struct _SD_CMDTypeDef
  4. {
  5.         uint8_t Cmd;
  6.         uint32_t Arg;
  7.         uint8_t Crc;
  8. }SD_CMDTypeDef;

  9. typedef uint8_t SD_R1TypeDef;

  10. typedef uint8_t SD_R1bTypeDef;

  11. typedef struct _SD_R2TypeDef
  12. {
  13.         SD_R1TypeDef R1;
  14.         uint8_t R2;
  15. }SD_R2TypeDef;

  16. typedef struct _SD_R3TypeDef
  17. {
  18.         SD_R1TypeDef R1;
  19.         uint32_t Ocr;
  20. }SD_R3TypeDef;

  21. typedef struct _SD_R7TypeDef
  22. {
  23.         SD_R1TypeDef R1;
  24.         uint8_t CommandVersion;
  25.         uint8_t Resv;
  26.         uint8_t VoltageAccepted;
  27.         uint8_t CheckPattern;
  28. }SD_R7TypeDef;

  29. /* CMD argumant mask */
  30. #define CMD_START                                                (1<<6)
  31. #define CMD_END                                                        (1<<0)

  32. /* Normal Command */
  33. #define GO_IDLE_STATE                                        0 //R1
  34. #define SEND_OP_COND                                        1 //R1
  35. #define SWITCH_FUNC                                                6 //R1
  36. #define SEND_IF_COND                                        8 //R7
  37. #define SEND_CSD                                                9 //R1
  38. #define SEND_CID                                                10 //R1
  39. #define STOP_TRANSMISSION                                12 //R1b
  40. #define SEND_STATUS                                                13 //R2
  41. #define SET_BLOCKLEN                                        16 //R1
  42. #define READ_SINGLE_BLOCK                                17 //R1
  43. #define READ_MULTIPLE_BLOCK                                18 //R1
  44. #define WRITE_BLOCK                                                24 //R1
  45. #define WRITE_MULTIPLE_BLOCK                        25 //R1
  46. #define PROGRAM_CSD                                                27 //R1
  47. #define SET_WRITE_PROT                                        28 //R1b
  48. #define CLR_WRITE_PROT                                        29 //R1b
  49. #define SEND_WRITE_PROT                                        30 //R1
  50. #define ERASE_WR_BLK_START_ADDR                        32 //R1
  51. #define ERASE_WR_BLK_END_ADDR                        33 //R1
  52. #define ERASE                                                        38 //R1b
  53. #define LOCK_UNLOCK                                                42 //R1
  54. #define APP_CMD                                                        55 //R1
  55. #define GEN_CMD                                                        56 //R1
  56. #define READ_OCR                                                58 //R3
  57. #define CRC_ON_OFF                                                59 //R1

  58. /* Application Command */
  59. #define SD_STATUS                                                13 //R2
  60. #define SEND_NUM_WR_BLOCKS                                22 //R1
  61. #define SET_WR_BLK_ERASE_COUNT                        23 //R1
  62. #define SD_SEND_OP_COND                                        41 //R1
  63. #define SET_CLR_CARD_DETECT                                42 //R1
  64. #define SEND_SCR                                                51 //R1

  65. /* R1 Response Bit Define */
  66. #define R1_IDLE_STATE                                        ((1)<<0)
  67. #define R1_ERASE_RESET                                        ((1)<<1)
  68. #define R1_ILLEGAL_CMD                                        ((1)<<2)
  69. #define R1_CRC_ERROR                                        ((1)<<3)
  70. #define R1_ERASE_ERROR                                        ((1)<<4)
  71. #define R1_ADDR_ERROR                                        ((1)<<5)
  72. #define R1_ARG_ERROR                                        ((1)<<6)

  73. /* Data Trans Token */
  74. #define TOKEN_START_WR_BLOCK                        ((uint8_t)0xFE)
  75. #define TOKEN_STATR_W_MULTI_BLOCK                ((uint8_t)0xFC)
  76. #define TOKEN_STOP_W_MULTI_BLOCK                ((uint8_t)0xFD)


  77. #endif

评分

参与人数 1威望 +4 收起 理由
dirtwillfly + 4 很给力!

查看全部评分

Lewisnx 发表于 2017-10-15 15:51 | 显示全部楼层
CMD8返回第一字节是 判断是否为V2.0
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

19

帖子

0

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