SDIO驱动SD卡POWER ON时,在CMD8后为什么要发2个CMD55才发CMD41?

2019-07-20 22:19发布

STM库里面的 SDIO驱动SD卡POWER ON 代码好怪异,在CMD8后为什么要发好几个CMD55才发CMD41?下图中红 {MOD}的2个CMD55干什么用的?
还有ACMD41命令为什么要重复发送直到validvoltage==1(这个好像是检测多卡)??
                     CMD8--------------------------------------------------->CMD55
                        | OK                                 err                     |   
                SDType=SD_HIGH_CAPACITY                               |
                        | <------------------------------------------------------------
                   CMD55
                        |<----------------
                    CMD55             |
                       |                  |
                    CMD41             |
                       |------------------
                       |

  /* CMD8: SEND_IF_COND --------------------------------------------------------*/
  /* Send CMD8 to verify SD card interface operating condition */
  /* Argument: - [31:12]: Reserved (shall be set to '0')
               - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
               - [7:0]: Check Pattern (recommended 0xAA) */
  /* CMD Response: R7 */
  SDIO_CmdInitStructure.SDIO_Argument = SD_CHECK_PATTERN;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SEND_IF_COND;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);   errorstatus = CmdResp7Error();   if (errorstatus == SD_OK)
  {
    CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; /* SD Card 2.0 */
    SDType = SD_HIGH_CAPACITY;
  }
  else
  {
    /* CMD55 */
    SDIO_CmdInitStructure.SDIO_Argument = 0x00;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_CMD;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);
    errorstatus = CmdResp1Error(SDIO_APP_CMD);
  }
  /* CMD55 */
  SDIO_CmdInitStructure.SDIO_Argument = 0x00;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_CMD;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);
  errorstatus = CmdResp1Error(SDIO_APP_CMD);   /* If errorstatus is Command TimeOut, it is a MMC card */
  /* If errorstatus is SD_OK it is a SD card: SD card 2.0 (voltage range mismatch)
     or SD card 1.x */
  if (errorstatus == SD_OK)
  {
    /* SD CARD */
    /* Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */
    while ((!validvoltage) && (count < SD_MAX_VOLT_TRIAL))
    {       /* SEND CMD55 APP_CMD with RCA as 0 */
      SDIO_CmdInitStructure.SDIO_Argument = 0x00;
      SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_CMD;
      SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(&SDIO_CmdInitStructure);       errorstatus = CmdResp1Error(SDIO_APP_CMD);       if (errorstatus != SD_OK)
      {
        return(errorstatus);
      }
      SDIO_CmdInitStructure.SDIO_Argument = SD_VOLTAGE_WINDOW_SD | SDType;
      SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SD_APP_OP_COND;
      SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(&SDIO_CmdInitStructure);       errorstatus = CmdResp3Error();
      if (errorstatus != SD_OK)
      {
        return(errorstatus);
      }       response = SDIO_GetResponse(SDIO_RESP1);
      validvoltage = (bool) (((response >> 31) == 1) ? 1 : 0);
      count++;
    }
    if (count >= SD_MAX_VOLT_TRIAL)
    {
      errorstatus = SD_INVALID_VOLTRANGE;
      return(errorstatus);
    }     if (response &= SD_HIGH_CAPACITY)
    {
      CardType = SDIO_HIGH_CAPACITY_SD_CARD;
    }   }/* else MMC Card */

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
5条回答
熊大
1楼-- · 2019-07-21 03:57
正点原子 发表于 2013-6-22 18:43
纯属多此一举.
我的SDIO例程就没有用到2次CMD55.
SD_Error&nbsp;SD_PowerON(void)
{
&nbsp;        u8&nbsp;i=0;
         ...

if(errorstatus==SD_OK)break;
  }
  if(errorstatus)return errorstatus;//返回错误状态
SDIO_Send_Cmd(SDIO_SEND_IF_COND,1,SD_CHECK_PATTERN);//发送CMD8,短响应,检查SD卡接口特性.
  //arg[11:8]:01,支持电压范围,2.7~3.6V
//arg[7:0]:默认0XAA
//返回响应7
   errorstatus=CmdResp7Error(); //等待R7响应
  if(errorstatus==SD_OK)  //R7响应正常
{
CardType=SDIO_STD_CAPACITY_SD_CARD_V2_0; //SD 2.0卡
SDType=SD_HIGH_CAPACITY;     //高容量卡
}
SDIO_Send_Cmd(SD_CMD_APP_CMD,1,0); //发送CMD55,短响应  
errorstatus=CmdResp1Error(SD_CMD_APP_CMD);    //等待R1响应   
if(errorstatus==SD_OK)//SD2.0/SD 1.1,否则为MMC卡
{   
//SD卡,发送ACMD41 SD_APP_OP_COND,参数为:0x80100000
while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
{        
SDIO_Send_Cmd(SD_CMD_APP_CMD,1,0); //发送CMD55,短响应
errorstatus=CmdResp1Error(SD_CMD_APP_CMD);    //等待R1响应   
  if(errorstatus!=SD_OK)return errorstatus;    //响应错误
SDIO_Send_Cmd(SD_CMD_SD_APP_OP_COND,1,SD_VOLTAGE_WINDOW_SD|SDType);//发送ACMD41,短响应  
errorstatus=CmdResp3Error();  //等待R3响应   
  if(errorstatus!=SD_OK)return errorstatus;    //响应错误  
response=SDIO->RESP1;;     //得到响应
validvoltage=(((response>>31)==1)?1:0); //判断SD卡上电是否完成
count++;
}

原子哥,你这个代码里,不是在发送ACMP41其间,也有一次是发送了2个CMD55吗?
cornrn
2楼-- · 2019-07-21 06:19
 精彩回答 2  元偷偷看……
正点原子
3楼-- · 2019-07-21 07:13
纯属多此一举.
我的SDIO例程就没有用到2次CMD55.
SD_Error SD_PowerON(void)
{
  u8 i=0;
SD_Error errorstatus=SD_OK;
u32 response=0,count=0,validvoltage=0;
u32 SDType=SD_STD_CAPACITY;
//配置CLKCR寄存器 
SDIO->CLKCR=0; //清空CLKCR之前的设置
SDIO->CLKCR|=0<<9; //非省电模式
SDIO->CLKCR|=0<<10; //关闭旁路,CK根据分频设置输出
SDIO->CLKCR|=0<<11; //1位数据宽度
SDIO->CLKCR|=0<<13; //SDIOCLK上升沿产生SDIOCK
SDIO->CLKCR|=0<<14; //关闭硬件流控制    
SDIO_Clock_Set(SDIO_INIT_CLK_DIV);//设置时钟频率(初始化的时候,不能超过400Khz)  
  SDIO->OWER=0X03; //上电状态,开启卡时钟    
   SDIO->CLKCR|=1<<8; //SDIOCK使能   
    for(i=0;i<74;i++)
{
SDIO_Send_Cmd(SD_CMD_GO_IDLE_STATE,0,0);//发送CMD0进入IDLE STAGE模式命令.   
errorstatus=CmdError();
if(errorstatus==SD_OK)break;
  }
  if(errorstatus)return errorstatus;//返回错误状态
SDIO_Send_Cmd(SDIO_SEND_IF_COND,1,SD_CHECK_PATTERN);//发送CMD8,短响应,检查SD卡接口特性.
  //arg[11:8]:01,支持电压范围,2.7~3.6V
//arg[7:0]:默认0XAA
//返回响应7
   errorstatus=CmdResp7Error(); //等待R7响应
  if(errorstatus==SD_OK)  //R7响应正常
{
CardType=SDIO_STD_CAPACITY_SD_CARD_V2_0; //SD 2.0卡
SDType=SD_HIGH_CAPACITY;     //高容量卡
}
SDIO_Send_Cmd(SD_CMD_APP_CMD,1,0); //发送CMD55,短响应  
errorstatus=CmdResp1Error(SD_CMD_APP_CMD);    //等待R1响应   
if(errorstatus==SD_OK)//SD2.0/SD 1.1,否则为MMC卡
{   
//SD卡,发送ACMD41 SD_APP_OP_COND,参数为:0x80100000 
while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
{        
SDIO_Send_Cmd(SD_CMD_APP_CMD,1,0); //发送CMD55,短响应  
errorstatus=CmdResp1Error(SD_CMD_APP_CMD);    //等待R1响应   
  if(errorstatus!=SD_OK)return errorstatus;    //响应错误
SDIO_Send_Cmd(SD_CMD_SD_APP_OP_COND,1,SD_VOLTAGE_WINDOW_SD|SDType);//发送ACMD41,短响应  
errorstatus=CmdResp3Error();  //等待R3响应   
  if(errorstatus!=SD_OK)return errorstatus;    //响应错误  
response=SDIO->RESP1;;     //得到响应
validvoltage=(((response>>31)==1)?1:0); //判断SD卡上电是否完成
count++;
}
if(count>=SD_MAX_VOLT_TRIAL)
{
errorstatus=SD_INVALID_VOLTRANGE;
return errorstatus;
}  
if(response&=SD_HIGH_CAPACITY)
{
CardType=SDIO_HIGH_CAPACITY_SD_CARD;
}
  }else//MMC卡
{
//MMC卡,发送CMD1 SDIO_SEND_OP_COND,参数为:0x80FF8000 
while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
{            
SDIO_Send_Cmd(SD_CMD_SEND_OP_COND,1,SD_VOLTAGE_WINDOW_MMC);//发送CMD1,短响应  
errorstatus=CmdResp3Error();  //等待R3响应   
  if(errorstatus!=SD_OK)return errorstatus;    //响应错误  
response=SDIO->RESP1;;     //得到响应
validvoltage=(((response>>31)==1)?1:0);
count++;
}
if(count>=SD_MAX_VOLT_TRIAL)
{
errorstatus=SD_INVALID_VOLTRANGE;
return errorstatus;
}       
CardType=SDIO_MULTIMEDIA_CARD;   
   }  
   return(errorstatus);
}
正点原子
4楼-- · 2019-07-21 09:05
回复【3楼】cornrn:
---------------------------------
哦,暂时还没遇到问题...
谢谢你的建议。
leafhui
5楼-- · 2019-07-21 09:14
 精彩回答 2  元偷偷看……

一周热门 更多>