发新帖我要提问
12
返回列表
打印

SDHC卡初始化

[复制链接]
楼主: joyxysetu
手机看帖
扫描二维码
随时随地手机跟帖
21
vivilzb1985| | 2017-10-15 20:42 | 只看该作者 回帖奖励 |倒序浏览
楼上分享的代码看着还是蛮复杂的

使用特权

评论回复
22
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。

使用特权

评论回复
23
joyxysetu|  楼主 | 2017-10-19 08:54 | 只看该作者
不知道会不会是硬件哪里有问题而导致的

使用特权

评论回复
24
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类指令的代码作为参考
/**
  * @brief  SDCard Send Command which uses Response 1 Token
  * @param  cmd:Pointer of Command Structure
                        r1:Pointer of Response 1 Token
  * @retval Operation Result Depending on Response Token
  */
static uint8_t SD_W_CMD_R1(SD_CMDTypeDef* cmd, SD_R1TypeDef* r1)
{
        uint32_t tick_now = HAL_GetTick();
        uint8_t rs = SD_OK;
       
        //Add Start and Transmission bit, Add End bit
        cmd->Cmd |= CMD_START;
        cmd->Crc |= CMD_END;
       
        //Card Select
        SD_CS_RESET();
       
        //Send Card Command
        SD_WR_Byte(cmd->Cmd);
        SD_W_Buff((uint8_t*)(&(cmd->Arg)), sizeof(cmd->Arg));
        SD_WR_Byte(cmd->Crc);
       
        do
        {
                if((HAL_GetTick() - tick_now) > CMD_TIMEOUT)
                {
                        //Timeout and Return
                        rs = SD_TIMEOUT;
                        goto DONE;
                }
               
                //Get R1 Response
                *r1 = SD_WR_Byte(0xFF);
        }
        while((*r1 & 0x80)); //wait for accurate R1 Response

DONE:       
        //Card Release
        SD_CS_SET();

        return rs;
}

具体指令返回啥值还是要翻specification,有一点要注意的是在发送完go_ilde指令后r1响应中ilde位的值很重要

使用特权

评论回复
25
1223657347| | 2017-10-19 12:22 | 只看该作者
joyxysetu 发表于 2017-10-18 17:12
if((HAL_GetTick() - tick_now) > GOTO_IDLE_TIMEOUT)
                {
                        //Time ...

继续说明,以go_ilde指令为例
do
        {
                if((HAL_GetTick() - tick_now) > GOTO_IDLE_TIMEOUT)
                {
                        //Timeout and Return
                        rs = SD_TIMEOUT;
                        goto DONE;
                }
               
                SD_CMD.Cmd = GO_IDLE_STATE;
                SD_CMD.Arg = 0;
                SD_CMD.Crc = 0x95;
                rs = SD_W_CMD_R1(&SD_CMD, &R1);
               
                if(rs == SD_OK)
                {
                        if((R1 & R1_IDLE_STATE) == 0)
                        {
                                rs = SD_ERROR;
                        }
                }
        }
        while(rs != SD_OK);

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

使用特权

评论回复
评分
参与人数 1威望 +10 收起 理由
dirtwillfly + 10 很给力!
26
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后,也一样能成功。不知道怎么回事,求大神指教!!!

使用特权

评论回复
27
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的返回值,而且我把改的这部分删了也一样,不知道哪出了问题,求大神指教!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则