⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd_driver.c

📁 SD卡在SD模式下的控制程序
💻 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 + -