程序如下:
/***********************************************************************
函数功能:MMC/SD卡初始化
操作内容:1、拉高CS片选和MOSI至少74个时钟周期
2、SPI发送10个FF
***********************************************************************/
uchar initMMC (void)
{
int i;
initSPI();
CS_HIGH();
for(i=0;i<=9;i++)
spiSendByte(0xff);
return (mmc_GoIdle());
}
/***********************************************************************
函数功能:MMC/SD卡空闲模式及初始化
操作内容:1、初始化MMC/SD卡工作在SPI模式,无论MMC还是SD卡都发送CMD0
2、判断MMC卡还是SD卡
3、SD卡循环10次发送CMD55+ACMD41,MMC卡发送CMD1
***********************************************************************/
char mmc_GoIdle()
{
char response;
unsigned char i;
unsigned char sdcard=0x00; //SD卡标志位,为0表示SDV1.x卡,为1表示为MMC卡,为2表示为SDHC卡,为3表示为SDV2.x卡
CS_LOW(); //选中MMC/SD卡,片选有效,接下来发送命令
mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95); //发送CMD0,MMC/SD卡设置为SPI模式,0x95为CRC值
//Now wait for READY RESPONSE
if(mmcGetResponse()!=0x01)
return MMC_INIT_ERROR;
else //bitIDLE=1
{
mmcSendCmd(MMC_CID,0x1aa,0x87); //发送CMD8,判断SD卡版本
response=mmcGetResponse();
if(response != 0x01) //如果卡片版本信息是v1.0版本的,即response=0x05
{
CS_HIGH();
spiSendByte(0xff);
CS_LOW();
if(sdcard==0x00) //先识别是否为SD卡,发送SD卡命令CMD55+ACMD41
{
for(i=0;i<10;i++) //循环10次,如果为SD卡,一般2次即可正确返回0x00
{
mmcSendCmd(SD_APP_COND,0x00,0xff); //发送SD卡判断命令,如果成功返回0x00,则为SD卡
while(response=mmcGetResponse()!=0x01); //返回值为0x01,则表示处于空闲状态,再发ACMD41命令
mmcSendCmd(SD_APP_OP_COND,0x00,0xff); //发送ACMD41命令
if(response=mmcGetResponse()==0x00) //返回值为0x00,则初始化成功,否则使用MMC命令CMD1继续初始化
{
CS_HIGH();
spiSendByte(0xff);
return MMC_SUCCESS;
}
}
sdcard=0x01; //为1表示SD卡命令无效,卡为MMC卡,准备下面发送CMD1命令
}
i=0;
do //准备发送MMC卡命令CMD1
{
mmcSendCmd(MMC_SEND_OP_COND,0x00,0xff); //发送MMC卡CMD1命令,成功则返回0x00
response=mmcGetResponse(); //返回值为0x00,则表示MMC卡初始化成功
i++;
}while((response!=0x00)&& (i<10));
if(i==10)
return MMC_INIT_ERROR;
else
{
CS_HIGH(); //MMC/SD卡片选无效
spiSendByte(0xff);
return MMC_SUCCESS;
}
}
else
{ //V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令
buff[0] = spiSendByte(0xff); //should be 0x00
buff[1] = spiSendByte(0xff); //should be 0x00
buff[2] = spiSendByte(0xff); //should be 0x01
buff[3] = spiSendByte(0xff); //should be 0xAA
CS_HIGH();
spiSendByte(0xff);
if(buff[2]==0x01&&buff[3]==0xAA) //判断该卡是否支持2.7V-3.6V的电压范围
{
CS_LOW();
i=0;
while((response!=0x00)&& (i<10)) //循环10次,如果为SD卡,一般2次即可正确返回0x00
{ //发送SD卡判断命令,如果成功返回0x00,则为SD卡
mmcSendCmd(SD_APP_COND,0x00,0xff); //发送CMD55
while(response=mmcGetResponse()!=0x01); //返回值为0x01,则表示处于空闲状态,再发ACMD41命令
mmcSendCmd(SD_APP_OP_COND,0x40000000,0xff); //发送ACMD41命令
i++;
}
if(i==10)
return MMC_INIT_ERROR;
else
{
mmcSendCmd(0x7a,0,0); //发送CMD58,获取OCR信息
response=mmcGetResponse();
if(response!=0x00)
{
CS_HIGH();
return MMC_RESPONSE_ERROR;
}
else
{ //读OCR指令发出后,紧接着是4字节的OCR信息
buff[0] = spiSendByte(0xff);
buff[1] = spiSendByte(0xff);
buff[2] = spiSendByte(0xff);
buff[3] = spiSendByte(0xff);
CS_HIGH(); //OCR接收完成,片选置高
spiSendByte(0xff);
//检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC
//如果CCS=1:SDHC CCS=0:SD2.0SD
if(buff[0]&0x40)
{
sdcard=0x02;
return MMC_SUCCESS;
}
else
{
sdcard=0x03;
return MMC_RESPONSE_ERROR;
}
}
}
//else return MMC_SUCCESS;
}
}
}
}
|