SDHC卡初始化

[复制链接]
3101|26
vivilzb1985 发表于 2017-10-15 20:42 | 显示全部楼层
楼上分享的代码看着还是蛮复杂的
 楼主| joyxysetu 发表于 2017-10-18 17:12 | 显示全部楼层
本帖最后由 joyxysetu 于 2017-10-18 17:23 编辑
1223657347 发表于 2017-10-15 11:46
实际sd卡初始化的时候有的指令要多发几次才有响应,lz可以参考下我这个初始化代码

下面是类型定义

if((HAL_GetTick() - tick_now) > GOTO_IDLE_TIMEOUT)
                {
                        //Timeout and Return
                        rs = SD_TIMEOUT;
                        goto DONE;
                }
if((HAL_GetTick() - tick_now) > CARD_READY_TIMEOUT)
                {
                        rs = SD_TIMEOUT;
                        goto DONE;
                }
这两处看不懂是什么意思,麻烦大神解释一下还有SD_OK定义值是多少,CMD0、55的返回值应该为0x01,CMD8在V1.x卡时返回值为0x05、V2.0卡时为0x01,CMD58、ACMD41的返回值应该为0x00,SD_OK要定义为多少才能都满足。
另外之前我发CMD58返回值是0xFF,现在我重复发CMD58发现返回值一直不是0xFF就是0x01。
 楼主| joyxysetu 发表于 2017-10-19 08:54 | 显示全部楼层
不知道会不会是硬件哪里有问题而导致的
1223657347 发表于 2017-10-19 12:16 | 显示全部楼层
joyxysetu 发表于 2017-10-18 17:12
if((HAL_GetTick() - tick_now) > GOTO_IDLE_TIMEOUT)
                {
                        //Time ...

这两处都是超时中止操作。rs的值只有三个SD_OK,SD_TIMEOUT,SD_ERROR。rs不是指令的响应。这里以发送r1类指令的代码作为参考
  1. /**
  2.   * @brief  SDCard Send Command which uses Response 1 Token
  3.   * @param  cmd:Pointer of Command Structure
  4.                         r1:Pointer of Response 1 Token
  5.   * @retval Operation Result Depending on Response Token
  6.   */
  7. static uint8_t SD_W_CMD_R1(SD_CMDTypeDef* cmd, SD_R1TypeDef* r1)
  8. {
  9.         uint32_t tick_now = HAL_GetTick();
  10.         uint8_t rs = SD_OK;
  11.        
  12.         //Add Start and Transmission bit, Add End bit
  13.         cmd->Cmd |= CMD_START;
  14.         cmd->Crc |= CMD_END;
  15.        
  16.         //Card Select
  17.         SD_CS_RESET();
  18.        
  19.         //Send Card Command
  20.         SD_WR_Byte(cmd->Cmd);
  21.         SD_W_Buff((uint8_t*)(&(cmd->Arg)), sizeof(cmd->Arg));
  22.         SD_WR_Byte(cmd->Crc);
  23.        
  24.         do
  25.         {
  26.                 if((HAL_GetTick() - tick_now) > CMD_TIMEOUT)
  27.                 {
  28.                         //Timeout and Return
  29.                         rs = SD_TIMEOUT;
  30.                         goto DONE;
  31.                 }
  32.                
  33.                 //Get R1 Response
  34.                 *r1 = SD_WR_Byte(0xFF);
  35.         }
  36.         while((*r1 & 0x80)); //wait for accurate R1 Response

  37. DONE:       
  38.         //Card Release
  39.         SD_CS_SET();

  40.         return rs;
  41. }

具体指令返回啥值还是要翻specification,有一点要注意的是在发送完go_ilde指令后r1响应中ilde位的值很重要
1223657347 发表于 2017-10-19 12:22 | 显示全部楼层
joyxysetu 发表于 2017-10-18 17:12
if((HAL_GetTick() - tick_now) > GOTO_IDLE_TIMEOUT)
                {
                        //Time ...

继续说明,以go_ilde指令为例
  1. do
  2.         {
  3.                 if((HAL_GetTick() - tick_now) > GOTO_IDLE_TIMEOUT)
  4.                 {
  5.                         //Timeout and Return
  6.                         rs = SD_TIMEOUT;
  7.                         goto DONE;
  8.                 }
  9.                
  10.                 SD_CMD.Cmd = GO_IDLE_STATE;
  11.                 SD_CMD.Arg = 0;
  12.                 SD_CMD.Crc = 0x95;
  13.                 rs = SD_W_CMD_R1(&SD_CMD, &R1);
  14.                
  15.                 if(rs == SD_OK)
  16.                 {
  17.                         if((R1 & R1_IDLE_STATE) == 0)
  18.                         {
  19.                                 rs = SD_ERROR;
  20.                         }
  21.                 }
  22.         }
  23.         while(rs != SD_OK);

此处设置了一个rs的陷阱,只有当r1的ilde位置位时才能跳出陷阱,其他情况,如指令超时/卡未能进入空闲都会在此处循环,不断发送指令,直到空闲为止或是超时

评分

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

查看全部评分

 楼主| joyxysetu 发表于 2017-10-28 11:20 | 显示全部楼层
本帖最后由 joyxysetu 于 2017-10-28 11:22 编辑

现在我程序改用FatFs13里的ff.h、ff.c、diskio.h、diskio.c作底层函数,发命令CMD0、8、55、ACMD41、58返回值都没错了。不过用16G的卡时,用f_mount函数注册一个工作区会返回FR_NO_FILESYSTEM,但我用2G的FAT卡时却能成功,后面还能用f_open创建一个文件并用f_write写入数,我把这2G的FAT卡格式化为FAT32后,也一样能成功。不知道怎么回事,求大神指教!!!
 楼主| joyxysetu 发表于 2017-10-30 10:00 | 显示全部楼层
本帖最后由 joyxysetu 于 2017-10-30 10:04 编辑

上面的问题解决了,16G的卡不用转换为字节地址,用扇区地址。现在能创建文件并写入数据了,但又发现了新的问题,不知为什么发CMD8命令2G的卡会返回0x01,这不就说明这卡是2.0的吗,但文件系统是FAT16啊,我换成以前的程序,就不返回0x01了,字节地址转换成扇区地址不应该影响CMD8的。
CMD8的返回值作判断,判别1.0和2.0的卡,判断为2.0的卡后发CMD55、ACMD41、CMD58之后,读写数据时才会把地址换成扇区地址,这部分应该影响不到CMD8的返回值,而且我把改的这部分删了也一样,不知道哪出了问题,求大神指教!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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