u8 SD_Init(void)
{
u16 i;
u8 r1;
u16 retry;
u8 buff[6];
SPI_ControlLine();
//SD卡初始化时时钟不能超过400KHz
SPI_SetSpeed(SPI_SPEED_LOW);
//CS为低电平,片选置低,选中SD卡
SD_CS_ENABLE();
//纯延时,等待SD卡上电稳定
for(i=0;i<0xf00;i++);
//先产生至少74个脉冲,让SD卡初始化完成
for(i=0;i<10;i++)
{
//参数可随便写,经过10次循环,产生80个脉冲
SPI_ReadWriteByte(0xff);
}
//-----------------SD卡复位到idle状态----------------
//循环发送CMD0,直到SD卡返回0x01,进入idle状态
//超时则直接退出
retry=0;
do
{
//发送CMD0,CRC为0x95
r1=SD_SendCommand(CMD0,0,0x95);
retry++;
}
while((r1!=0x01)&&(retry<200));
//跳出循环后,检查跳出原因,
if(retry==200) //说明已超时
{
return 1;
}
//如果未超时,说明SD卡复位到idle结束
//发送CMD8命令,获取SD卡的版本信息
r1=SD_SendCommand(CMD8,0x1aa,0x87);
//下面是SD2.0卡的初始化
if(r1==0x01)
{
// V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令
buff[0] = SPI_ReadWriteByte(0xFF);
buff[1] = SPI_ReadWriteByte(0xFF);
buff[2] = SPI_ReadWriteByte(0xFF);
buff[3] = SPI_ReadWriteByte(0xFF);
SD_CS_DISABLE();
//多发8个时钟
SPI_ReadWriteByte(0xFF);
retry = 0;
//发卡初始化指令CMD55+ACMD41
do
{
r1 = SD_SendCommand(CMD55, 0, 0);
//应返回0x01
if(r1!=0x01)
return r1;
r1 = SD_SendCommand(ACMD41, 0x40000000, 1);
retry++;
if(retry>200)
return r1;
}
while(r1!=0);
//初始化指令发送完成,接下来获取OCR信息
//----------鉴别SD2.0卡版本开始-----------
//读OCR指令
r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
//如果命令没有返回正确应答,直接退出,返回应答
if(r1!=0x00)
return r1;
//应答正确后,会回传4字节OCR信息
buff[0] = SPI_ReadWriteByte(0xFF);
buff[1] = SPI_ReadWriteByte(0xFF);
buff[2] = SPI_ReadWriteByte(0xFF);
buff[3] = SPI_ReadWriteByte(0xFF);
//OCR接收完成,片选置高
SD_CS_DISABLE();
SPI_ReadWriteByte(0xFF);
//检查接收到的OCR中的bit30位(CSS),确定其为SD2.0还是SDHC
//CCS=1:SDHC CCS=0:SD2.0
if(buff[0]&0x40)
{
SD_Type = SD_TYPE_V2HC;
}
else
{
SD_Type = SD_TYPE_V2;
}
//-----------鉴别SD2.0卡版本结束-----------
SPI_SetSpeed(1); //设置SPI为高速模式
}
}
|