📄 sd_driver.c
字号:
#include "SD_Driver.H"
/*通过CMD向SD卡写入一个字节数据*/
unsigned char RespBuf[6];
void SdCmdWrite(unsigned char n)
{
unsigned char i;
for(i=8;i>0;i--)
{
SD_CLK=0;
SD_CMD=(n&0x80);
n<<=1;
SD_CLK=1;
}
SD_CMD=1;
}
/*从CMD读入一个字节响应数据*/
unsigned char SdRespRead(void)
{
unsigned char n,i;
for(i=8;i>0;i--)
{
SD_CLK=0;
delay(20);
SD_CLK=1;
n<<=1;
if(SD_CMD) n|=1;
delay(20);
}
return n;
}
/*通过DAT3~DAT0读入一个字节数据*/
unsigned char SdDataRead(void)
{
unsigned char n;
SD_CLK=0;
SD_CLK=1;
n=P1;
n&=0x0f;
n<<=4;
SD_CLK=0;
SD_CLK=1;
n|=P1&0x0f;
return n;
}
/*向SD卡写入6个字节的命令*/
void SdCommand(unsigned char command, unsigned long argument)
{
unsigned char CRC;
CRC=SD_GetCmdCRC7(command,argument);
SdCmdWrite(command|0x40);
SdCmdWrite(((unsigned char *)&argument)[0]);
SdCmdWrite(((unsigned char *)&argument)[1]);
SdCmdWrite(((unsigned char *)&argument)[2]);
SdCmdWrite(((unsigned char *)&argument)[3]);
SdCmdWrite(CRC);
/*
UARTSend(command|0x40);
delay(10);
UARTSend(((unsigned char *)&argument)[0]);
delay(10);
UARTSend(((unsigned char *)&argument)[1]);
delay(10);
UARTSend(((unsigned char *)&argument)[2]);
delay(10);
UARTSend(((unsigned char *)&argument)[3]);
delay(10);
UARTSend(CRC);
*/
}
/*通过CMD读取响应数据*/
unsigned char SdResponse(void)
{
unsigned char i=0;
RespBuf[0]=SdRespRead();
RespBuf[1]=SdRespRead();
RespBuf[2]=SdRespRead();
RespBuf[3]=SdRespRead();
RespBuf[4]=SdRespRead();
RespBuf[5]=SdRespRead();
/*
UARTSend(RespBuf[0]);
delay(10);
UARTSend(RespBuf[1]);
delay(10);
UARTSend(RespBuf[2]);
delay(10);
UARTSend(RespBuf[3]);
delay(10);
UARTSend(RespBuf[4]);
delay(10);
UARTSend(RespBuf[5]);
*/
return RespBuf[1];
}
/*从SD卡读出一个数据块*/
unsigned char SdReadBlock(unsigned char *Block, unsigned long address)
{
unsigned char count;
//Block size is 512 bytes exactly
address+=0x1d200;
SdCommand(17,address);
// clock(11);
// SdResponse();
// clock(8);
do
{
count=SdDataRead();
}
while(count!=0xf0);
for(count=0;count<128;count++)
{
*Block++=SdDataRead();
*Block++=SdDataRead();
*Block++=SdDataRead();
*Block++=SdDataRead();
}
//Get Crc bytes
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
return 1;
}
unsigned char SdReadMultiBlock(unsigned char *Block, unsigned long address,unsigned char Len)
{
unsigned char count;
address+=0x1d200;
SdCommand(18,address);
for(;Len>0;Len--)
{
do
{
count=SdDataRead();
}
while(count!=0xf0);
for(count=0;count<128;count++)
{
*Block++=SdDataRead();
*Block++=SdDataRead();
*Block++=SdDataRead();
*Block++=SdDataRead();
}
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
SdDataRead();
}
clock(8);
SdCommand(12,0);
clock(11);
SdResponse();
clock(8);
return 1;
}
void clock(unsigned char i)
{
SD_CMD=1;
for(;i>0;i--)
{
SD_CLK=0;
delay(20);
_nop_();
_nop_();
SD_CLK=1;
delay(20);
_nop_();
_nop_();
}
}
/*SD卡初始化程序*/
unsigned char SdInit(void)
{
unsigned char i=8;
unsigned char response=0;
unsigned long temp=0;
clock(74);
SdCommand(0x00,0);
clock(8);
delay(100);
while(!(response&0x80)&&i--)
{
SdCommand(55,0);
clock(5);
SdResponse();
clock(8);
SdCommand(41,0x00ff8000); //通过ACMD41指令判断设备是否正确初始化
clock(5);
response=SdResponse();
clock(64);
if(response==0xff)
response=0;
}
if(i==0xff)
return 0;
SdCommand(2,0);
clock(5);
SdResponse();
SdResponse();
SdResponse();
clock(8);
SdCommand(3,0);//Get RCA
clock(11);
SdResponse();
clock(8);
temp=((unsigned long) RespBuf[2]<<16)+((unsigned long) RespBuf[1]<<24);
SdCommand(9,temp);//Addressed card sends its card-specific data (CSD) on the CMD line.
clock(11);
SdResponse();
SdResponse();
SdResponse();
clock(8);
SdCommand(7,temp);//Select the card
clock(11);
SdResponse();
clock(8);
SdCommand(16,0x200);//Set block length equal 512 bytes
clock(11); //只能小于512字节,否则会出错,卡认为数数据块长度有错
SdResponse();
clock(8);
SdCommand(55,temp);
clock(11);
SdResponse();
clock(8);
SdCommand(6,2); //Set Bus width to 4-bits
clock(11);
SdResponse();
clock(64);
return 1;
}
unsigned int LSwapINT16(unsigned short dData1,unsigned short dData2)
{
unsigned int xdata dData;
dData = ((dData2<<8)&0xff00)|(dData1&0x00ff);
return dData;
}
unsigned long LSwapINT32(unsigned char dData1,unsigned char dData2,unsigned char dData3,unsigned char dData4)
{
unsigned long xdata dData;
dData = ((dData4<<24)&0xff000000)|((dData3<<16)&0xff0000)|((dData2<<8)&0xff00)|(dData1&0xff);
return dData;
}
unsigned char SdReadSector(unsigned long sector,unsigned char len,unsigned char *pBuffer)
{
while(len--)
{
if(SdReadBlock(pBuffer,sector<<9)==0)
return 0;
pBuffer+=512;
}
return 1;
}
/********************
** 函数名称: INT8U SD_GetCmdByte6() Name: INT8U SD_GetCmdByte6()
** 功能描述: 获取SD卡命令的CRC7 Function: get the CRC7 of the command of SD card
** 输 入: INT8U cmd : 命令 Input: INT8U cmd : command
INT8U *param: 命令的参数,长度为4字节 INT8U *param: the param of command,length is 4 bytes
** 输 出: CRC7码 Output: CRC7 code
********************************************************************************************************************/
unsigned char SD_GetCmdCRC7(unsigned char cmd, unsigned long argument)
{
unsigned char i, j;
unsigned char reg = 0;
unsigned char array[5];
array[0] = cmd|0x40;
for (i = 1; i < 5; i++) /* 将参数的顺序重新排列 */
array[i] = ((unsigned char *)&argument)[i-1];
for (i = 0; i < 5; i++) /* 计算5个字节的CRC7 */
{
for (j = 0; j < 8; j++)
{
reg <<= 1;
reg ^= ((((array[i] << j) ^ reg) & 0x80) ? 0x9 : 0);
}
}
return ((reg << 1) + 0x01) ; /* 计算结果的CRC7左移一位,并将最低位置1 */
}
/***********************************************************/
void UARTSend(unsigned char i)
{
ES=0;
SBUF=i;
while(!TI);
TI=0;
ES=1;
}
void delay(unsigned int i)
{
while(i--);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -