OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10891|回复: 5

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

[复制链接]

16

主题

52

帖子

0

精华

初级会员

Rank: 2

积分
156
金钱
156
注册时间
2013-4-15
在线时间
7 小时
发表于 2013-6-22 09:33:00 | 显示全部楼层 |阅读模式

STM库里面的 SDIO驱动SD卡POWER ON 代码好怪异,在CMD8后为什么要发好几个CMD55才发CMD41?下图中红色的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 */

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

18

主题

41

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
424
金钱
424
注册时间
2016-9-2
在线时间
79 小时
发表于 2017-11-1 12:39:21 | 显示全部楼层
正点原子 发表于 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吗?
回复 支持 1 反对 0

使用道具 举报

164

主题

1230

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1477
金钱
1477
注册时间
2014-5-21
在线时间
342 小时
发表于 2015-4-3 11:32:25 | 显示全部楼层
 回复【2楼】 正点原子 :
---------------------------------
 那不能省了,省了可能出问题,一个是标准命令一个非标准命令,

彼高丽者,边夷贱类,不足待以仁义,不可责以常礼。古来以鱼鳖畜之,宜从阔略。若必欲绝其种类,恐兽穷则搏。
回复 支持 1 反对 0

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2013-6-22 18:43:25 | 显示全部楼层
纯属多此一举.
我的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);
}
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2015-4-3 23:07:36 | 显示全部楼层
回复【3楼】cornrn:
---------------------------------
哦,暂时还没遇到问题...
谢谢你的建议。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2019-7-2
在线时间
27 小时
发表于 2019-7-17 15:52:08 | 显示全部楼层
正点原子 发表于 2013-6-22 18:43
纯属多此一举.
我的SDIO例程就没有用到2次CMD55.
SD_Error&nbsp;SD_PowerON(void)
{
&nbsp;        u8&nbsp;i=0;
         ...

原子哥,你这段代码好像也发了两次CMD55吧?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 10:15

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表