27,374
社区成员
发帖
与我相关
我的任务
分享
/*********************************************************
函数功能:向SD卡写入cnt个0xff
*********************************************************/
void SD_BYTE_NOP(BYTE cnt)
{
do{
SPI_RW(0xff);
}while(cnt --);
}
/********************************************************
函数功能:SD卡初始化
********************************************************/
BYTE SD_Init(void)
{
WORD i;
BYTE response=0x01;
SPI_Init();//SD_CLK = 1;
SET_SPI_LOW_MODE_FLAG();
DISABLE_SPI();//SD_CS=1;
for(i=0;i<=9;i++)
{
SPI_RW(0xff);//SdWrite(0xff);
}
//return SD_GoIdleState();//
ENABLE_SPI();//SD_CS=0;
//Send Command 0 to put MMC in SPI mode
SD_Command(sd_cmd0);//(0x00,0,0x95);
response=SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
if(response!=0x01)
{
DISABLE_SPI();
#if(__IS_DEBUG__)
printf("cmd0 should return 0x01 while it is %d\r\n",response);
#endif
return 0;
}
ENABLE_SPI();
/***************************不丢掉垃圾数据,后面命令响应可能会失败************************/
SD_BYTE_NOP(8);
/****************************************************************************************/
SD_Command(sd_cmd8);
response = SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
#if(__IS_DEBUG__)
printf("Response fo cmd8 is:0x%02x\r\n", (int)response);
#endif
switch(response)
{
case 0x05:
{//V1.x或者其他
/* SD1.0/MMC start initialize */
/* Send CMD55+ACMD41, No-response is a MMC card, otherwise is a SD1.0 card */
i = 0;
do{
ENABLE_SPI();
/***************************不丢掉垃圾数据,后面命令响应可能会失败************************/
SD_BYTE_NOP(8);
/****************************************************************************************/
SD_Command(sd_cmd55);
response = SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
if(0x01 != response)
{
#if(__IS_DEBUG__)
printf("Init SD Card Failed ! Send CMD55 should return 0x01, response=0x%02x\r\n",(int)response);
#endif
// DISABLE_SPI();
// return 0;
}
else
{
#if(__IS_DEBUG__)
printf("Response cmd55 OK, response=0x%02x\r\n",(int)response);
#endif
}
ENABLE_SPI();
/***************************不丢掉垃圾数据,后面命令响应可能会失败************************/
SD_BYTE_NOP(8);
/****************************************************************************************/
SD_Command(sd_cmd41);
response = SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
if(0x00 == response)
{
#if(__IS_DEBUG__)
printf("Response cmd41 OK, response=0x%02x\r\n",(int)response);
#endif
break;
}
i ++;
}while(i < 200);
if(i >= 200)
{
#if(__IS_DEBUG__)
printf("Response cmd41 should be 0x00, response=0x%02x\r\n",(int)response);
#endif
}
i = 0;
while(response==0x01)
{
ENABLE_SPI();//SD_CS=0;
/***************************不丢掉垃圾数据,后面命令响应可能会失败************************/
SD_BYTE_NOP(8);
/****************************************************************************************/
SD_Command(sd_cmd1);//0x01,0x00ffc000,0xff);
response=SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
if(i++ >= 200)
{//重试次数为200时会失败,会不会是因为速度太快
#if(__IS_DEBUG__)
printf("Init SD Card Failed ! try cmd1 for 4000 tick, response is:%d\r\n",(int)response);
#endif
DISABLE_SPI();
return 0;
}
}
#if(__IS_DEBUG__)
printf("try %d time fo cmd1 , response for cmd 1 ok! is:%d.\r\n",i,(int)response);
#endif
ENABLE_SPI();
/***************************不丢掉垃圾数据,后面命令响应可能会失败************************/
SD_BYTE_NOP(8);
/****************************************************************************************/
SD_Command(sd_cmd59); //禁止CRC校验
response = SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
if(0x00 != response)
{
#if(__IS_DEBUG__)
printf("response cmd59 error,response = %d !\r\n",(unsigned int)response);
#endif
DISABLE_SPI();
return 0;
}
ENABLE_SPI();
/***************************不丢掉垃圾数据,后面命令响应可能会失败************************/
SD_BYTE_NOP(8);
/****************************************************************************************/
SD_Command(sd_cmd16);//设置块大小
response = SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
if(0x00 != response)
{
DISABLE_SPI();
return 0;
}
RESET_SPI_LOW_MODE_FLAG(); //设置SPI为高速模式
return 1;
}
break;
case 0x01:
{//SD V2.x
/* SD1.0/MMC start initialize */
/* Send CMD55+ACMD41, No-response is a MMC card, otherwise is a SD1.0 card */
i = 0;
do{
ENABLE_SPI();
/***************************不丢掉垃圾数据,后面命令响应可能会失败************************/
SD_BYTE_NOP(8);
/****************************************************************************************/
SD_Command(sd_cmd55);
response = SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
if(0x01 != response)
{
DISABLE_SPI();
return 0;
}
ENABLE_SPI();
/***************************不丢掉垃圾数据,后面命令响应可能会失败************************/
SD_BYTE_NOP(8);
/****************************************************************************************/
SD_Command(sd_cmd41);
response = SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
if(0x00 == response)
{
break;
}
i ++;
}while(i < 200);
ENABLE_SPI();
/***************************不丢掉垃圾数据,后面命令响应可能会失败************************/
SD_BYTE_NOP(8);
/****************************************************************************************/
SD_Command(sd_cmd58);
response = SD_Response();
DISABLE_SPI();
SPI_RW(0xff);
if(0x00 != response)
{
DISABLE_SPI();
return 0;
}
RESET_SPI_LOW_MODE_FLAG(); //设置为高速模式
return 1;
}
break;
}
DISABLE_SPI();
return 0;
}
/*================================================================
入口参数:
出口参数:
返回参数:
0 ->失败
1 ->成功
函数功能:
1)从address开始出读取len个字节到buf;
2)最长可读取512字节;
3)支持跨扇区读数;
维护人
================================================================*/
BYTE SD_ReadBlock1(BYTE buf[],DWORD address,WORD len)
{
BYTE readRetryCnt = 100;
WORD count = 0x0000;
BYTE retryCnt = 0x00;
WORD offset = 0x00000;
BYTE response = 0x00;
offset = address - address / 512 * 512;
address /= 512;
address *= 512;
ENABLE_SPI();
g_B_sd_cmd_buf[0] = 0x11;
g_B_sd_cmd_buf[1] = (BYTE)(((BYTE *)&address)[0]);
g_B_sd_cmd_buf[2] = (BYTE)(((BYTE *)&address)[1]);
g_B_sd_cmd_buf[3] = (BYTE)(((BYTE *)&address)[2]);
g_B_sd_cmd_buf[4] = (BYTE)(((BYTE *)&address)[3]);
g_B_sd_cmd_buf[5] = 0xff;
SD_Command(g_B_sd_cmd_buf);
/*********************发送读扇区命令后,响应非0表示成功*********************/
retryCnt = 0;
do
{
response = SD_Response();
retryCnt ++;
if(retryCnt >= 100)
{
DISABLE_SPI();
SPI_RW(0xff);
return 0;
}
}while(response);//SD_Response());
/**************************************************************************/
//SET_SPI_LOW_MODE_FLAG();
/**********************等待SD卡响应0xfe,启动数据传输**********************/
retryCnt = 0;
do
{
response = SPI_RW(0xff);
if(0xfe == response){
{
break;
}
retryCnt ++;
if(retryCnt >= 10){
DISABLE_SPI();
SPI_RW(0xff);
return 0;
}
}while(retryCnt < 100);
/*************************************************************************/
if(len > 512 - offset)
{//读取的区域需要跨扇区
/********************丢弃该扇区offse前的数据*********************/
for(count = 0; count < offset; count ++)
{
SPI_RW(0xff);
}
/*************************************************************/
/********************从该扇区offset偏移处开始接收***************/
while(count < 512)
{
buf[count - offset] = SPI_RW(0xff);
count ++;
len --;//接收到一个字节,接收缓冲减1
}
/***************************************************************/
//data block sent - now send checksum
SPI_RW(0xff);//SdRead();
SPI_RW(0xff);//SdRead();
//Now read in the DATA RESPONSE token
DISABLE_SPI();//SD_CS=1;
SPI_RW(0xff);//SdRead();
//======================接收下一个扇区剩下的字节======================
ENABLE_SPI();
address += 512;
g_B_sd_cmd_buf[0] = 0x11;
g_B_sd_cmd_buf[1] = (BYTE)(((BYTE *)&address)[0]);
g_B_sd_cmd_buf[2] = (BYTE)(((BYTE *)&address)[1]);
g_B_sd_cmd_buf[3] = (BYTE)(((BYTE *)&address)[2]);
g_B_sd_cmd_buf[4] = (BYTE)(((BYTE *)&address)[3]);
g_B_sd_cmd_buf[5] = 0xff;
SD_Command(g_B_sd_cmd_buf);
retryCnt = 100;
do
{
retryCnt --;
if(!retryCnt)
{
DISABLE_SPI();
SPI_RW(0xff);
return 0;
}
}while(SD_Response());
retryCnt = 0;
do
{
if(0xfe == SPI_RW(0xff)){break;}
retryCnt ++;
if(retryCnt >= 100)
{
#if(__IS_DEBUG__)
printf("in SD_ReadBlock1,error 3, try %d times !\r\n",(unsigned int)retryCnt);
#endif
DISABLE_SPI();
SPI_RW(0xff);
return 0;
}
}while(retryCnt < 100);
for(count = 0; count < len; count ++)
{
buf[512 - offset + count] = SPI_RW(0xff);
}
while(count++ < 512){SPI_RW(0xff);}
//data block sent - now send checksum
SPI_RW(0xff);//SdRead();
SPI_RW(0xff);//SdRead();
//Now read in the DATA RESPONSE token
DISABLE_SPI();//SD_CS=1;
SPI_RW(0xff);//SdRead();
return 1;
}
else
{//读取的区域在一个扇区
for(count = 0; count < offset; count ++)
{
SPI_RW(0xff);
}
while(count < offset + len)
{
buf[count - offset] = SPI_RW(0xff);
count ++;
}
/***************************剩下的字节一定要读完,否则会导致下次读扇区是错误***************/
while(count ++ < 512){SPI_RW(0xff);}
/******************************************************************************************/
//data block sent - now send checksum
SPI_RW(0xff);//SdRead();
SPI_RW(0xff);//SdRead();
//Now read in the DATA RESPONSE token
DISABLE_SPI();//SD_CS=1;
SPI_RW(0xff);//SdRead();
return 1;
}