发 帖  

[经验] stm32f769 寄存器配置SD卡驱动--SD_InitializeCards函数

2018-3-23 11:37:06  1080 寄存器 配置 驱动
分享
0
本帖最后由 lee_st 于 2018-3-24 10:35 编辑

下面是实现SD_InitializeCards的初始化函数
SD_Error SD_InitializeCards(void)
{
         SD_Error errorstatus=SD_OK;
        u16 rca = 0x01;
         if((SDMMC2->POWER&0X03)==0)return SD_REQUEST_NOT_APPLICABLE;//检查电源状态,确保为上电状态
         if(SECURE_DIGITAL_IO_CARD!=CardType)                                //非SECURE_DIGITAL_IO_CARD
        {
                SDMMC_Send_Cmd(SD_CMD_ALL_SEND_CID,3,0);                        //发送CMD2,取得CID,长响应         
                errorstatus=CmdResp2Error();                                         //等待R2响应   
                if(errorstatus!=SD_OK)return errorstatus;           //响应错误                    
                 CID_Tab[0]=SDMMC2->RESP1;
                CID_Tab[1]=SDMMC2->RESP2;
                CID_Tab[2]=SDMMC2->RESP3;
                CID_Tab[3]=SDMMC2->RESP4;
        }
        if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(SECURE_DIGITAL_IO_COMBO_CARD==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))//判断卡类型
        {
                SDMMC_Send_Cmd(SD_CMD_SET_REL_ADDR,1,0);                        //发送CMD3,短响应
                errorstatus=CmdResp6Error(SD_CMD_SET_REL_ADDR,&rca);//等待R6响应
                if(errorstatus!=SD_OK)return errorstatus;           //响应错误                    
        }   
    if (MULTIMEDIA_CARD==CardType)
    {
                 SDMMC_Send_Cmd(SD_CMD_SET_REL_ADDR,1,(u32)(rca<<16));//发送CMD3,短响应            
                errorstatus=CmdResp2Error();                                         //等待R2响应   
                if(errorstatus!=SD_OK)return errorstatus;           //响应错误         
    }
        if (SECURE_DIGITAL_IO_CARD!=CardType)                        //非SECURE_DIGITAL_IO_CARD
        {
                RCA = rca;
                SDMMC_Send_Cmd(SD_CMD_SEND_CSD,3,(u32)(rca<<16));//发送CMD9+卡RCA,取得CSD,长响应            
                errorstatus=CmdResp2Error();                                         //等待R2响应   
                if(errorstatus!=SD_OK)return errorstatus;           //响应错误                    
                  CSD_Tab[0]=SDMMC2->RESP1;
                CSD_Tab[1]=SDMMC2->RESP2;
                CSD_Tab[2]=SDMMC2->RESP3;                                                
                CSD_Tab[3]=SDMMC2->RESP4;                                            
        }
        return SD_OK;//卡初始化成功
}

里面的调用的函数CmdResp2Error()
SD_Error CmdResp2Error(void)
{
        SD_Error errorstatus=SD_OK;
        u32 status;
        u32 timeout=SDMMC_CMD0TIMEOUT;
         while(timeout--)
        {
                status=SDMMC2->STA;
                if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)        
        }
          if((timeout==0)||(status&(1<<2)))        //响应超时
        {                                                                                                                                                                    
                errorstatus=SD_CMD_RSP_TIMEOUT;
                SDMMC2->ICR|=1<<2;                                //清除命令响应超时标志
                return errorstatus;
        }         
        if(status&1<<0)                                                //CRC错误
        {                                                                  
                errorstatus=SD_CMD_CRC_FAIL;
                SDMMC2->ICR|=1<<0;                                //清除响应标志
         }
        SDMMC2->ICR=0X5FF;                                         //清除标记
         return errorstatus;                                                                                    
}

SD_Error CmdResp6Error(u8 cmd,u16*prca)
{
        SD_Error errorstatus=SD_OK;
        u32 status;                                            
        u32 rspr1;
         while(1)
        {
                status=SDMMC2->STA;
                if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)        
        }
        if(status&(1<<2))                                        //响应超时
        {                                                                                                                                                                    
                 SDMMC2->ICR|=1<<2;                                //清除命令响应超时标志
                return SD_CMD_RSP_TIMEOUT;
        }                  
        if(status&1<<0)                                                //CRC错误
        {                                                                  
                SDMMC2->ICR|=1<<0;                                //清除响应标志
                 return SD_CMD_CRC_FAIL;
        }
        if(SDMMC2->RESPCMD!=cmd)                        //判断是否响应cmd命令
        {
                 return SD_ILLEGAL_CMD;                 
        }            
        SDMMC2->ICR=0X5FF;                                         //清除所有标记
        rspr1=SDMMC2->RESP1;                                //得到响应         
        if(SD_ALLZERO==(rspr1&(SD_R6_GENERAL_UNKNOWN_ERROR|SD_R6_ILLEGAL_CMD|SD_R6_COM_CRC_FAILED)))
        {
                *prca=(u16)(rspr1>>16);                        //右移16位得到,rca
                return errorstatus;
        }
           if(rspr1&SD_R6_GENERAL_UNKNOWN_ERROR)return SD_GENERAL_UNKNOWN_ERROR;
           if(rspr1&SD_R6_ILLEGAL_CMD)return SD_ILLEGAL_CMD;
           if(rspr1&SD_R6_COM_CRC_FAILED)return SD_COM_CRC_FAILED;
        return errorstatus;
}














评分

参与人数 2积分 +10 收起 理由
ElecFans王岑 + 5
star_66666 + 5 资源分享达人,加分鼓励!

查看全部评分

相关经验

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

发经验
关闭

站长推荐 上一条 /7 下一条

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