http://blog.163.com/dreamatic_altezza/blog/static/119304542013112932216498/
大家在使用stm32 sdio口初始化sd卡的时候会遇到一个国内文章中都没有提到的问题
首先我来说说初始化sdhc卡(sdsc卡acmd41参数为0x00ff8000)的流程:
cmd0 无参数 返回0x00 0x00
cmd8 参数0x1aa 返回0x8 0x1aa
cmd55 无参数 返回0x37 0x120
acmd41 参数0x40ff8000 返回0x3f 0x40ff8000
cmd55 无参数 返回0x37 0x120
acmd41 参数0x40ff8000 返回0x3f 0xc0ff8000 (sd卡OCR bit[31] busy位置1 卡进入ready status)
但在实际使用stm32的过程中,我们会遇到发送完第一个acmd41后,返回就一直是0x3f 0x40ff8000。即使是再发送cmd55也是0x3f 0x40ff8000。这不是sd卡不响应,而是stm32的sdio监测到crc错误,不再发送命令了。
这是由于sd规范中,Acmd41返回的crc永远是11111,也就是应该忽略crc,但是Stm32的sdio却检查了crc,就出错了。
为了使crc错误后的sdio恢复正常我们可以使用sdio库函数来清除crc标志位,代码如下:
SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
SDIO_ClearITPendingBit(SDIO_IT_CCRCFAIL);
以下是我写的cmd55+acmd41循环:
测试用的,请勿就纠结代码的效率。
希望能够被sd初始化困扰的朋友带来曙光!
for(k=0;k<800;k++)
{
SDIO_CmdInitStructure.SDIO_Argument = 0x00;
SDIO_CmdInitStructure.SDIO_CmdIndex = 0x37;
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);
for(i=0;i<2000;i++)//发送完命令需要延时才能获取sd卡的反馈
{
}
d5=SDIO_GetCommandResponse();//等待返回 返回是63
d1=SDIO_GetResponse(SDIO_RESP1);//16gb卡返回0x40200000;16gb卡返回0x00ff8000
d2=SDIO_GetResponse(SDIO_RESP2);
d3=SDIO_GetResponse(SDIO_RESP3);
d4=SDIO_GetResponse(SDIO_RESP4);
d3=SDIO_GetITStatus(SDIO_IT_CCRCFAIL );
d4=SDIO_GetFlagStatus(SDIO_FLAG_CCRCFAIL);
SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
SDIO_ClearITPendingBit(SDIO_IT_CCRCFAIL);
d3=SDIO_GetITStatus(SDIO_IT_CCRCFAIL );
d4=SDIO_GetFlagStatus(SDIO_FLAG_CCRCFAIL);
//
SDIO_CmdInitStructure.SDIO_Argument = 0x40ff8000;//16gb卡用0x40000000;2gb用0x00000000
SDIO_CmdInitStructure.SDIO_CmdIndex = 0x29;
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);
for(i=0;i<2000;i++)//发送完命令需要延时才能获取sd卡的反馈
{
}
d5=SDIO_GetCommandResponse();//等待返回 返回是63
d1=SDIO_GetResponse(SDIO_RESP1);//16gb卡返回0x40ff8000;16gb卡返回0x00ff8000
d2=SDIO_GetResponse(SDIO_RESP2);
d3=SDIO_GetResponse(SDIO_RESP3);
d4=SDIO_GetResponse(SDIO_RESP4);
for(i=0;i<5000;i++)//发送完命令需要延时才能获取sd卡的反馈
{
}
d3=SDIO_GetITStatus(SDIO_IT_CCRCFAIL );
d4=SDIO_GetFlagStatus(SDIO_FLAG_CCRCFAIL);
SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
SDIO_ClearITPendingBit(SDIO_IT_CCRCFAIL);
d3=SDIO_GetITStatus(SDIO_IT_CCRCFAIL );
d4=SDIO_GetFlagStatus(SDIO_FLAG_CCRCFAIL);
}