if(IOData&0x8000)//If the MSB of IOData is 1, then Do=1, else Do=0.
sd_dao=1;//Do High
else
sd_dao=0;//Do Low
sd_clk=1;//CLK High
Delay5us();
IOData=IOData<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
}
}
//********************************************
void SD_Write(unsigned int IOData)
{
unsigned char BitCounter;
IOData=IOData<<8;
for (BitCounter=0;BitCounter<8;BitCounter++)
{
sd_clk=0;//CLK Low
if(IOData&0x8000)//If the MSB of IOData is 1, then Do=1, else Do=0.
sd_dao=1;//Do High
else
sd_dao=0;//Do Low
sd_clk=1;//CLK High
Delay5us();
IOData=IOData<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
}
}
//********************************************
unsigned int SD_2Byte_Read()
{
unsigned int Buffer;
unsigned char BitCounter;
Buffer=0;
for (BitCounter=0;BitCounter<16;BitCounter++)
{
sd_clk=0;//CLK Low
Delay5us();
sd_clk=1;//CLK High
Buffer=Buffer<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
//Because the LSB will be damaged, we can not put this line under next line.
if(sd_dai)
Buffer++;//If SPI_Din=1 then the LSB_of_Buffer=1.
}
return Buffer;
}
//********************************************
unsigned int SD_Read()
{
unsigned int Buffer;
unsigned char BitCounter;
Buffer=0xffff;
for (BitCounter=0;BitCounter<8;BitCounter++)
{
sd_clk=0;//CLK Low
Delay5us();
sd_clk=1;//CLK High
Buffer=Buffer<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
//Because the LSB will be damaged, we can not put this line under next line.
if(sd_dai)
Buffer++;//If SPI_Din=1 then the LSB_of_Buffer=1.
}
return Buffer;
}
//********************************************
unsigned int SD_CMD_Write(unsigned int CMDIndex,unsigned long CMDArg,unsigned int ResType,unsigned int CSLowRSV)//ResType:Response Type, send 1 for R1; send 2 for R1b; send 3 for R2.
{ //There are 7 steps need to do.(marked by [1]-[7])
unsigned int temp,Response,Response2,CRC,MaximumTimes;
Response2=0;
MaximumTimes=10;
CRC=0x0095;//0x0095 is only valid for CMD0
if (CMDIndex!=0) CRC=0x00ff;
sd_cse=0;//[1] CS Low
SD_2Byte_Write(((CMDIndex|0x0040)<<8)+(CMDArg>>24));//[2] Transmit Command_Index & 1st Byte of Command_Argument.
SD_2Byte_Write((CMDArg&0x00ffff00)>>8); //[2] 2nd & 3rd Byte of Command_Argument
SD_2Byte_Write(((CMDArg&0x000000ff)<<8)+CRC); //[2] 4th Byte of Command_Argument & CRC only for CMD0
sd_dao=1;//[3] Do High
//[3] Restore Do to High Level
for (temp=0;temp<8;temp++)//[4] Provide 8 extra clock after CMD
{
sd_clk=0;//CLK Low
Delay5us();
sd_clk=1;//CLK High
Delay5us();
}
switch (ResType)//[5] wait response
{
case 1://R1
{
do
Response=SD_Read();
while (Response==0xffff);
break;
}
case 2://R1b
{
do
Response=SD_Read();
while (Response==0xffff);//Read R1 firstly
do
Response2=SD_Read()-0xff00;
while (Response2!=0);//Wait until the Busy_Signal_Token is non-zero
break;
}
case 3: Response=SD_2Byte_Read();break;//R2
}
if (CSLowRSV==0) sd_cse=1;//[6] CS High (if the CMD has data block response CS should be kept low)
for (temp=0;temp<8;temp++)//[7] Provide 8 extra clock after card response