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

📄 sdcard.c

📁 SD和mmc卡的读写程序
💻 C
字号:
//-------------------------------------------------------------------------
#include "SDCard.h"

BYTE response_R(BYTE);
BYTE send_cmd(BYTE *);

static unsigned short /*__attribute__ ((progmem))*/
crc_tab[256]={
0,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,0x1231,
0x210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,0x2462,
0x3443,0x420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,0x3653,0x2672,
0x1611,0x630,0x76d7,0x66f6,0x5695,0x46b4,0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,0x48c4,0x58e5,0x6886,
0x78a7,0x840,0x1861,0x2802,0x3823,0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,0x5af5,0x4ad4,0x7ab7,0x6a96,
0x1a71,0xa50,0x3a33,0x2a12,0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,
0x3c03,0xc60,0x1c41,0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,
0x1e51,0xe70,0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,
0xe16f,0x1080,0xa1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,0x34e2,
0x24c3,0x14a0,0x481,0x7466,0x6447,0x5424,0x4405,0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,0x26d3,0x36f2,
0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,0x5844,0x4865,0x7806,
0x6827,0x18c0,0x8e1,0x3882,0x28a3,0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,0x4a75,0x5a54,0x6a37,0x7a16,
0x0af1,0x1ad0,0x2ab3,0x3a92,0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,
0x2c83,0x1ce0,0xcc1,0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0xed1,0x1ef0
};


//-------------------------------------------------------------------------
BYTE response_buffer[20];
BYTE RCA[2];
BYTE cmd_buffer[5];

BYTE cmd0[5] = {0x40,0x00,0x00,0x00,0x00};//Reset SD Card
BYTE cmd55[5] = {0x77,0x00,0x00,0x00,0x00};//Next CMD is ASC
BYTE cmd2[5] = {0x42,0x00,0x00,0x00,0x00};//asks to send the CID numbers
BYTE cmd3[5] = {0x43,0x00,0x00,0x00,0x00};//Send RCA
BYTE cmd7[5] = {0x47,0x00,0x00,0x00,0x00};//Select one card,put it into Transfer State
BYTE cmd9[5] = {0x49,0x00,0x00,0x00,0x00};//Ask send CSD
BYTE cmd16[5] = {0x50,0x00,0x00,0x02,0x00};//Select a block length
BYTE cmd17[5] = {0x51,0x00,0x00,0x00,0x00};//Read a single block
BYTE acmd6[5] = {0x46,0x00,0x00,0x00,0x02};//SET BUS WIDTH
BYTE cmd24[5] = {0x58,0x00,0x00,0x00,0x00};//Write a single block

BYTE acmd41[5] = {0x69,0x0f,0xf0,0x00,0x00};//Active Card抯 ini process
BYTE acmd42[5] = {0x6A,0x0f,0xf0,0x00,0x00};//Disable pull up on Dat3
BYTE acmd51[5] = {0x73,0x00,0x00,0x00,0x00};//Read SCR(Configuration Reg)
//-------------------------------------------------------------------------

// SD Card Set I/O Direction
#define SD_CMD_IN 		DDRB &= ~(1<<2)
#define SD_CMD_OUT 		DDRB |=  (1<<2)
#define SD_DAT0_IN 		DDRB &= ~(1<<6)
#define SD_DAT0_OUT 	DDRB |=  (1<<6)
#define SD_DAT1_IN 		DDRB &= ~(1<<7)
#define SD_DAT1_OUT 	DDRB |=  (1<<7)
#define SD_DAT2_IN 		DDRB &= ~(1<<0)
#define SD_DAT2_OUT 	DDRB |=  (1<<0)
#define SD_DAT3_IN 		DDRB &= ~(1<<1)
#define SD_DAT3_OUT 	DDRB |=  (1<<1)
// SD Card Output High/Low
#define SD_CMD_LOW 		PORTB &= ~(1<<2)
#define SD_CMD_HIGH 	PORTB |=  (1<<2)
#define SD_DAT0_LOW 	PORTB &= ~(1<<6)
#define SD_DAT0_HIGH 	PORTB |=  (1<<6)
#define SD_DAT1_LOW 	PORTB &= ~(1<<7)
#define SD_DAT1_HIGH 	PORTB |=  (1<<7)
#define SD_DAT2_LOW 	PORTB &= ~(1<<0)
#define SD_DAT2_HIGH 	PORTB |=  (1<<0)
#define SD_DAT3_LOW 	PORTB &= ~(1<<1)
#define SD_DAT3_HIGH 	PORTB |=  (1<<1)

#define SD_CLK_LOW 		PORTB &= ~(1<<4)
#define SD_CLK_HIGH 	PORTB |=  (1<<4)
// SD Card Input Read
#define SD_TEST_CMD 	(PINB & (1<<2))
#define SD_TEST_DAT0 	(PINB & (1<<6))
#define SD_TEST_DAT1 	(PINB & (1<<7))
#define SD_TEST_DAT2 	(PINB & (1<<0))
#define SD_TEST_DAT3 	(PINB & (1<<1))


inline void Ncr(void)
{
    SD_CMD_IN;
    SD_CLK_LOW;
    SD_CLK_HIGH;
    SD_CLK_LOW;
    SD_CLK_HIGH;
}
//-------------------------------------------------------------------------
inline void Ncc(void)
{
  SD_CLK_LOW; SD_CLK_HIGH;
  SD_CLK_LOW; SD_CLK_HIGH;
  SD_CLK_LOW; SD_CLK_HIGH;
  SD_CLK_LOW; SD_CLK_HIGH;
  SD_CLK_LOW; SD_CLK_HIGH;
  SD_CLK_LOW; SD_CLK_HIGH;
  SD_CLK_LOW; SD_CLK_HIGH;
  SD_CLK_LOW; SD_CLK_HIGH;
}
//-------------------------------------------------------------------------

BYTE SdCardInit(void)
{
    BYTE x,y;
	DDRB |= (1<<4);  //Clock as input
	SD_CMD_IN; SD_CMD_LOW;
	SD_DAT0_IN; SD_DAT0_LOW;
	SD_DAT1_IN; SD_DAT1_LOW;
	SD_DAT2_IN; SD_DAT2_LOW;
	SD_DAT3_IN; SD_DAT3_LOW;

    SD_CMD_OUT;
	SD_CLK_HIGH; SD_CMD_HIGH;
	
	for(x=0;x<40;x++) Ncr();
    for(x=0;x<5;x++) cmd_buffer[x]=cmd0[x];
	y = send_cmd(cmd_buffer);//Reset SD Card
    do
      {
            for(x=0;x<40;x++) asm volatile ("nop");
            Ncc();
            for(x=0;x<5;x++) cmd_buffer[x]=cmd55[x];
            y = send_cmd(cmd_buffer);//Next CMD is ASC
            Ncr();
			if(response_R(1)>1)  return 1;//response too long or crc error
			Ncc();
            for(x=0;x<5;x++) cmd_buffer[x]=acmd41[x];
            y = send_cmd(cmd_buffer);//Active Card抯 ini process
            Ncr();
      } while(response_R(3)==1);

	Ncc();
    for(x=0;x<5;x++) cmd_buffer[x]=cmd2[x];//asks to send the CID numbers
    y = send_cmd(cmd_buffer);
    Ncr();
    if(response_R(2)>1) return 2;

    Ncc();
    for(x=0;x<5;x++) cmd_buffer[x]=cmd3[x];
    y = send_cmd(cmd_buffer);//Send RCA
    Ncr();
    if(response_R(6)>1) return 3;

    RCA[0]=response_buffer[1];
    RCA[1]=response_buffer[2];
    Ncc();
    for(x=0;x<5;x++) cmd_buffer[x]=cmd9[x];
    cmd_buffer[1] = RCA[0];
    cmd_buffer[2] = RCA[1];
    y = send_cmd(cmd_buffer);//Ask send CSD
    Ncr();
    if(response_R(2)>1) return 4;
	
	Ncc();
    for(x=0;x<5;x++) cmd_buffer[x]=cmd7[x];
    cmd_buffer[1] = RCA[0];
    cmd_buffer[2] = RCA[1];
    y = send_cmd(cmd_buffer);//Select one card, put it into Transfer State
    Ncr();
    if(response_R(1)>1) return 5;
	
	//change to 4bit bus width
	do
      {
            for(x=0;x<40;x++) asm volatile ("nop");
            Ncc();
            for(x=0;x<5;x++) cmd_buffer[x]=cmd55[x];
			cmd_buffer[1] = RCA[0];
    		cmd_buffer[2] = RCA[1];
            y = send_cmd(cmd_buffer);//Next CMD is ASC
            Ncr();
			if(response_R(1)>1) return 6;//response too long or crc error
               
            Ncc();
            for(x=0;x<5;x++) cmd_buffer[x]=acmd6[x];
            y = send_cmd(cmd_buffer);  
            Ncr();
      } while(response_R(1)==1);
	
	Ncc();
    for(x=0;x<5;x++) cmd_buffer[x]=cmd16[x];
    y = send_cmd(cmd_buffer);//Select a block length 512Byte
    Ncr();
	if (response_R(1)>1) return 7;

    return 0;
}
//-------------------------------------------------------------------------
BYTE SdReadBlock(UINT32 Block, BYTE *buff)
{	  
	  { //ReadBlock-Cmd
		Ncc();
        cmd_buffer[0] = cmd17[0];
        cmd_buffer[1] = (Block>>15)&0xff;
        cmd_buffer[2] = (Block>>7)&0xff;
        cmd_buffer[3] = (Block<<1)&0xff;
        cmd_buffer[4] = 0;
        send_cmd(cmd_buffer);
        Ncr();
      }
	unsigned int timeout = 0;
    while(1) //Wait until startbit comes
	  {
     		SD_CLK_LOW;
            SD_CLK_HIGH;
            if(!(SD_TEST_DAT0)) 
			 if(!(SD_TEST_DAT1))
			  if(!(SD_TEST_DAT2))
			   if(!(SD_TEST_DAT3)) break;
			if (timeout++ > 65534) return 1;
	   }
 	int i; for(i=0;i<512;i++) // Read 512 Bytes
       {
			register unsigned char c = 0;
			SD_CLK_LOW; SD_CLK_HIGH;
		    if(SD_TEST_DAT0) c |= 0x10;
            if(SD_TEST_DAT1) c |= 0x20;
            if(SD_TEST_DAT2) c |= 0x40;
            if(SD_TEST_DAT3) c |= 0x80;

			SD_CLK_LOW; SD_CLK_HIGH;
            if(SD_TEST_DAT0) c |= 0x01;
            if(SD_TEST_DAT1) c |= 0x02;
            if(SD_TEST_DAT2) c |= 0x04;
            if(SD_TEST_DAT3) c |= 0x08; 
            *buff++=c;
        }
	 for (i = 0; i < 4; i++) //Dummy read CRC
	   {
			SD_CLK_LOW; SD_CLK_HIGH;		
			SD_CLK_LOW; SD_CLK_HIGH;
			SD_CLK_LOW; SD_CLK_HIGH;
			SD_CLK_LOW; SD_CLK_HIGH;
	   }
    return 0;
}
//-------------------------------------------------------------------------

BYTE SdWriteBlock(UINT32 Block, BYTE *buff)
{
    UINT32 i,j;
    unsigned short crc[4] = {0};
      { // WriteBlock-Cmd
		Ncc();
        cmd_buffer[0] = cmd24[0];
        cmd_buffer[1] = (Block>>15)&0xff;
        cmd_buffer[2] = (Block>>7)&0xff;
        cmd_buffer[3] = (Block<<1)&0xff;
        cmd_buffer[4] = 0;
        send_cmd(cmd_buffer);
	  }
    for(i=0;i<100;i++)  { SD_CLK_LOW; SD_CLK_HIGH; } 
    SD_CLK_LOW; //send startbit
	SD_DAT0_OUT; SD_DAT0_LOW;
    SD_DAT1_OUT; SD_DAT1_LOW;
    SD_DAT2_OUT; SD_DAT2_LOW;
    SD_DAT3_OUT; SD_DAT3_LOW;
    SD_CLK_HIGH;
    unsigned char c;
	char* buff_adr  = buff;
	for(i = 0; i < 128; i++) // Computer 4 CRCs
	  {
			register unsigned char a = 0, b = 0, c = 0, d = 0;
			if (*buff & 0x10) a |= 0x80; if (*buff & 0x20) b |= 0x80;
			if (*buff & 0x40) c |= 0x80; if (*buff & 0x80) d |= 0x80;
			if (*buff & 0x01) a |= 0x40; if (*buff & 0x02) b |= 0x40;
			if (*buff & 0x04) c |= 0x40; if (*buff & 0x08) d |= 0x40;
			buff++;						
			if (*buff & 0x10) a |= 0x20; if (*buff & 0x20) b |= 0x20;
			if (*buff & 0x40) c |= 0x20; if (*buff & 0x80) d |= 0x20;			
			if (*buff & 0x01) a |= 0x10; if (*buff & 0x02) b |= 0x10;
			if (*buff & 0x04) c |= 0x10; if (*buff & 0x08) d |= 0x10;
			buff++;
			if (*buff & 0x10) a |= 0x08; if (*buff & 0x20) b |= 0x08;
			if (*buff & 0x40) c |= 0x08; if (*buff & 0x80) d |= 0x08;
			if (*buff & 0x01) a |= 0x04; if (*buff & 0x02) b |= 0x04;
			if (*buff & 0x04) c |= 0x04; if (*buff & 0x08) d |= 0x04;			
			buff++;						
			if (*buff & 0x10) a |= 0x02; if (*buff & 0x20) b |= 0x02;
			if (*buff & 0x40) c |= 0x02; if (*buff & 0x80) d |= 0x02;
			if (*buff & 0x01) a |= 0x01; if (*buff & 0x02) b |= 0x01;
			if (*buff & 0x04) c |= 0x01; if (*buff & 0x08) d |= 0x01;
			buff++;

			crc[0]=crc_tab[(crc[0]>>8)^a]^(crc[0]<<8);
			crc[1]=crc_tab[(crc[1]>>8)^b]^(crc[1]<<8);
			crc[2]=crc_tab[(crc[2]>>8)^c]^(crc[2]<<8);
			crc[3]=crc_tab[(crc[3]>>8)^d]^(crc[3]<<8);
	  }
	buff = buff_adr;
	for(i=0;i<512;i++)  //transfer 512 bytes
      {
        c=*buff;
        SD_CLK_LOW;
        if(c&0x10) SD_DAT0_HIGH; else SD_DAT0_LOW;
        if(c&0x20) SD_DAT1_HIGH; else SD_DAT1_LOW;
        if(c&0x40) SD_DAT2_HIGH; else SD_DAT2_LOW;
        if(c&0x80) SD_DAT3_HIGH; else SD_DAT3_LOW;
        SD_CLK_HIGH;
        asm volatile ("nop");
		SD_CLK_LOW;        
		if(c&0x01) SD_DAT0_HIGH; else SD_DAT0_LOW;
        if(c&0x02) SD_DAT1_HIGH; else SD_DAT1_LOW;
        if(c&0x04) SD_DAT2_HIGH; else SD_DAT2_LOW;
        if(c&0x08) SD_DAT3_HIGH; else SD_DAT3_LOW;
        SD_CLK_HIGH;
        buff++;
      }
 	for(j=0; j<16; j++) //write CRC
      {
     	SD_CLK_LOW;
        if(crc[0]&0x8000) SD_DAT0_HIGH; else SD_DAT0_LOW;
        if(crc[1]&0x8000) SD_DAT1_HIGH; else SD_DAT1_LOW;
        if(crc[2]&0x8000) SD_DAT2_HIGH; else SD_DAT2_LOW;
        if(crc[3]&0x8000) SD_DAT3_HIGH; else SD_DAT3_LOW;
        SD_CLK_HIGH;
        crc[0]<<=1; crc[1]<<=1; crc[2]<<=1; crc[3]<<=1;
      }
    c=0;
    SD_CLK_LOW;
    SD_DAT0_HIGH; SD_DAT1_HIGH; SD_DAT2_HIGH; SD_DAT3_HIGH; 
    SD_CLK_HIGH;
	SD_DAT0_IN; SD_DAT1_IN; SD_DAT2_IN; SD_DAT3_IN;
    for(i=0; i<7; i++) //wait for response
      {
    	SD_CLK_LOW;
        SD_CLK_HIGH;
        c=c<<1;
        if(SD_TEST_DAT0) c|=0x01;
      }
    Ncc();
	unsigned int timeout = 0;
    while(1) //wait until card is not busy
      {
      	SD_CLK_LOW;
        SD_CLK_HIGH;
        if(SD_TEST_DAT0)
		  if(SD_TEST_DAT1)
		    if(SD_TEST_DAT2)
		      if(SD_TEST_DAT3) break;
		if (timeout++ > 65534) return 1;
      }
    return c != 101; //101 means "all right"
}

//-------------------------------------------------------------------------
BYTE response_R(BYTE s)
{
    BYTE a=0,b=0,c=0,r=0,crc=0;
    BYTE i,j=6,k;
    while(1)
      {
            SD_CLK_LOW;
            SD_CLK_HIGH;
            if(!(SD_TEST_CMD)) break;
            if(crc++ >254) return 2;
      }
    crc =0;
    if(s == 2) j = 17;
    for(k=0; k<j; k++)
      {
            c = 0;
            if(k > 0) //for crc culcar
                b = response_buffer[k-1];
            for(i=0; i<8; i++)
              {
                    SD_CLK_LOW;
                    if(a > 0) c <<= 1;
                    else i++;
                    a++;
                    SD_CLK_HIGH;
                    if(SD_TEST_CMD) c |= 0x01;
                    if(k > 0)
                      {
                            crc <<= 1;
                            if((crc ^ b) & 0x80)
                            crc ^= 0x09;
                            b <<= 1;
                            crc &= 0x7f;
                      }
              }
            if(s==3)
              if( k==1 &&(!(c&0x80))) r=1;
            response_buffer[k] = c;
      }
    if(s==1 || s==6)
      if(c != ((crc<<1)+1)) r=2;

    return r;
}
//-------------------------------------------------------------------------

BYTE send_cmd(BYTE *in)
{
    int i,j;
    BYTE b,crc=0;
    SD_CMD_OUT;
    for(i=0; i < 5; i++)
      {
            b = in[i];
            for(j=0; j<8; j++)
              {
                    SD_CLK_LOW;
                    if(b&0x80) SD_CMD_HIGH;
                    else SD_CMD_LOW;
                    crc <<= 1;
                    SD_CLK_HIGH;
                    if((crc ^ b) & 0x80) crc ^= 0x09;
                    b<<=1;
              }
            crc &= 0x7f;
      }
    crc =((crc<<1)|0x01);
    b = crc;
    for(j=0; j<8; j++)
      {
            SD_CLK_LOW;
            if(crc&0x80) SD_CMD_HIGH;
            else SD_CMD_LOW;
            SD_CLK_HIGH;
            crc<<=1;
      }
    return b;
}
//--------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -