/*******************************************************************************
* 函 数 名 : SD_WriteCmd
* 函数功能 : 向SD卡写入一个命令
* 输 入 : cmd:命令;
* * dat: 命令参数
* * crc: CRC效验
* 输 出 : r1:SD卡返回的数据
* * 0xFF:表示发送失败
* 备 注 :SD卡一个命令格式包括8位命令,32位命令参数和7位CRC效验位,最后一位为1
*******************************************************************************/
uchar SD_WriteCmd(uchar cmd, ulong dat, uchar crc)
{
uint i, r1 = 0;
//--复位SD卡--//
SD_CS = 1;
SD_SPI_Start();
SD_SPI_WriteData(0xFF); //额外提供8个时钟
SD_CS = 0;
while(SD_SPI_ReadData() != 0xFF) //等待卡是否准备好
{
i++;
if(i > 200)
{
return 0xFF; //等待失败返回
}
}
//--发送数据--//
SD_SPI_WriteData(cmd | 0x40);
SD_SPI_WriteData(dat >> 24); //发送Dat的最高8位
SD_SPI_WriteData(dat >> 16);
SD_SPI_WriteData(dat >> 8);
SD_SPI_WriteData(dat & 0x00FF);
SD_SPI_WriteData(crc);
if(cmd == SD_CMD12) //如果是停止数据传输命令,额外多发一个时钟
{
SD_SPI_WriteData(0xFF);
}
i = 0;
do
{
r1 = SD_SPI_ReadData();
i++;
if(i > 200)
{
return 0xFF;
}
}
while((r1 & 0x80) != 0); //发送成功的最高位是0
return r1;
}
/*******************************************************************************
* 函 数 名 : SD_Init
* 函数功能 : 初始化SD卡
* 输 入 : 无
* 输 出 : 0:初始化失败
* * 1:初始化成功
*******************************************************************************/
uchar SD_Init(void)
{
uchar i, r1;
uchar buf[4];
//--IO口初始化--//
SD_CS = 1;
TOUCH_CS = 1; //因为触摸和SD共用SPI接口,所以先将触摸的关闭掉
SPI_LOWMODE = 1; //使用低速模式
SD_SPI_Start();
//--将SD卡通信模式转换为SPI模式,上电默认是用DAT0作数据线--//
//--接到CMD0时,CS信号有效,SPI模式启动--//
for(i=0; i<0x0F; i++)//初始时,先发送至少74个时钟,这个是必须的。
{
SD_SPI_WriteData(0xFF); //发送120个
}
//当读取到0x01的时候表示初始化成功
i = 0;
while(SD_WriteCmd(SD_CMD0, 0, 0x95) != 0x01)
{
i++;
if(i > 500)
{
return 0; //初始化失败返回0
}
}
//--发送CMD8,检测是否SD V2.0--//
i = 0;
do
{
i++;
if(i > 500) //若是发送超过次数跳出循环管
{
break;
}
r1 = SD_WriteCmd(SD_CMD8, 0x01AA, 0x87);
}
while(r1 != 0x01); //发送CMD8
if(r1 == 0x01) //如果CMD8有回应说明是SD V2.0协议
{
//--读取CMD8的返回值,检测是否支持电压--//
//--读取CMD8的返回值,检测是否支持电压--//
for(i=0; i<4; i++)
{
buf = SD_SPI_ReadData();
}
//--卡电压不支持电压,返回错误--//
if((buf[2] != 0x01) || (buf[3] != 0xAA))
{
return 0;
}
//--初始化SD卡--//
i = 0;
do
{
i++;
if(i > 100)
{
return 0; //返回失败
}
SD_WriteCmd(SD_CMD55, 0, 0x01);
r1 = SD_WriteCmd(SD_CMD41, 0x40000000, 0x01);
}
while(r1 != 0);
//--检测是SDHC卡还是SD卡--//
i = 0;
while(SD_WriteCmd(SD_CMD58, 0, 0x01) != 0)
{
i++;
if(i > 100)
{
SD_TYPE = SD_TYPE_ERR;
break;
}
}
//--读取OCR--//
for(i=0; i<4; i++)
{
buf = SD_SPI_ReadData();
}
if(buf[0] & 0x40)
{
SD_TYPE = SD_TYPE_V2HC;
}
else
{
SD_TYPE = SD_TYPE_V2;
}
}
else //否则就是SD V1.0或者MMC V3
{
SD_WriteCmd(SD_CMD55, 0x00, 0x01);
r1 = SD_WriteCmd(SD_CMD41, 0x00, 0x01);
if(r1 <= 1) //对CMD41有回应说明是SD V1.0
{
SD_TYPE = SD_TYPE_V1; //是V1.0卡
i = 0;
do
{
if(i > 100)
{
return 0;
}
SD_WriteCmd(SD_CMD55, 0x00, 0x01);
r1 = SD_WriteCmd(SD_CMD41, 0x00, 0x01);
}
while(r1 != 0);
}
else //没有回应说明是MMC V3
{
SD_TYPE = SD_TYPE_MMC; //卡类型是MMC卡
i = 0;
while(SD_WriteCmd(SD_CMD1, 0, 0x01) != 0)
{
i++;
if(i > 100)
{
return 0;
}
}
}
}
SD_CS = 1; //取消片选
SD_SPI_WriteData(0xFF);
SPI_LOWMODE = 0; //使用高速模式
return 1;
}
|