SD 卡的初始化步骤就如上述,而程序实现如下:
int8_t SD_Init(void)
{
uint8_t r1, buf[4];
uint16_t i = 0;
SD_GPIO_Config();
SPI2_SetSpeed(SPI_BaudRatePrescaler_256);
/* 将 SD 卡通信模式转换为 SPI 模式,上电默认是用 DAT0 作数据线 */
/* 接到 CMD0 时,CS 信号有效,SPI 模式启动 */
for(i=0; i<0x0F; i++)//初始时,先发送至少 74 个时钟,这个是必须的。
{
SPI2_WriteReadData(0xFF); //发送 8*16 个
}
/* 当读取到 0x01 的时候表示初始化成功 */
i = 0;
while(SD_WriteCmd(SD_CMD0, 0, 0x95) != 0x01)
{
i++;
if(i > 100)
{
return 0xFF; //初始化失败返回 0
}
}
/* 发送 CMD8,检测是否 SD V2.0 */
i = 0;
do
{
i++;
if(i > 100) //若是发送超过次数跳出循环管
{
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[i] = SPI2_WriteReadData(0xFF);
}
/* 卡电压不支持电压,返回错误 */
if((buf[2] != 0x01) || (buf[3] != 0xAA))
{
return 0xFF;
}
/* 初始化 SD 卡 */
i = 0;
do
{
i++;
if(i > 100)
{
return 0xFF; //返回失败
}
SD_WriteCmd(SD_CMD55, 0, 0x01);
r1 = SD_WriteCmd(SD_CMD41, 0x40000000, 0x01);
}
while(r1 != 0); //写入 CMD41 成功了,这里省略读取 CMD41
是否设置成功。
/* 检测是 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[i] = SPI2_WriteReadData(0xFF);
}
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 0xFF;
}
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 0xFF;
}
}
}
}
SD_CS_SET; //取消片选
SPI2_WriteReadData(0xFF);
return 0;
}
在这个程序中,还添加了 MMC 卡的初始化。 |