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

📄 sd.c

📁 C51上实现SD卡程序,是FAT32文件系统
💻 C
字号:
//#define __SD
#include "sd.h"
//#undef __SD

unsigned char SDCommand( unsigned char c1, 
                         unsigned char c2, 
                         unsigned char c3, 
                         unsigned char c4, 
                         unsigned char c5)
{

    SD_XCS = SD_NOT_SELECTED; //put SD on-line.
 
    // Provide clock edges before and after asserting SD CS
    SPI8Clocks(8); 
    SD_XCS = SD_SELECTED;
    SPI8Clocks(8);
  
   // The bus should be stable high now
    if (SPI_RESULT_BYTE != 0xff)
	{
        SD_XCS = SD_NOT_SELECTED; 
        return LINE_BUSY; 
    }

    // Send the SD command
    SPIPutCharWithoutWaiting(c1);
    SPIPutChar(c2);
    SPIPutChar(c3);
    SPIPutChar(c4);
    SPIPutChar(c5);
    SPIPutChar(0x95);     /* Valid CRC for init, then don't care */
    SPIWait();
   /* Now ok to use c1..c5 as temporaries (dirty but kool) */
 
   // Wait for R1 style response (bit 7 low) from SD

    c1=100;
    while((c1--)&&((c2=SPIGetChar())&0x80)) //wait for R1 or timeout
    ;

    return c2; //return the R1 response
}


unsigned char SDWaitForData()
{
    unsigned char c;
     // Wait until something else than 0xff is read from the bus
    do 
	{
        c=SPIGetChar();
	} while ((c == 0xff));
 
   
   // desired 0xFE data start token? 
    if (c != 0xfe)
	{
		/*
        SPI8Clocks(200); 
        SPI8Clocks(200);
        SPI8Clocks(200);
		*/
	    SD_XCS = SD_NOT_SELECTED; //Drop SD offline now.
        return c;
	}
 	return DATA_COMING;
}
 
 
void SDGetData(unsigned int amountOctets)
{
    while (amountOctets--)
	{
        *dataBufPtr++=SPIGetChar();
    }
}

void PerformBlockRead()
{
    unsigned int i;
    for(i=0;i<512;i++)
	{
         SPIPutCharWithoutWaiting(0xff);
         SPIWait();
         *dataBufPtr++=SPI_RESULT_BYTE;
    }
}

unsigned char SeekSector(unsigned char cmd_sn,unsigned long sectorN)
{
    unsigned char c;
	unsigned char * address;
	address =(unsigned char *)&sectorN;
    do
	{
        c=SDCommand(cmd_sn,address[2],address[1],address[0], 0);
        address[1] = address[1] >> 1; //convert back to blocks
 
     //if SD returs "nothing" (0xff), toggle chip select and retry
        if (c==0xff)
		{
            RebootSD();
		}
        if (c==LINE_BUSY)
		{ //SD says "LINE_BUSY"
            c=0xff; //try again
		}
	}while(c==0xff); //repeat until we get signal from SD.
    SD_XCS = SD_NOT_SELECTED;
    return 0; //ok return
}


/* Wait for data start token and read 512 bytes to global buffer */
unsigned char ReadSector()
{
    SD_XCS = SD_SELECTED;
    if(SDWaitForData()==DATA_COMING)
	PerformBlockRead();
	else return ERR; 
   /* generate SPI clock edges to finish up the command */
 
    SPI8Clocks(4); //Send 8*4=32 clocks (4 ff's) to SD to be nice.
    SD_XCS = SD_NOT_SELECTED;
    SPI8Clocks(4); //Again, give the poor SD some clocks, it likes them.  
    return 0; //ok return
}

unsigned char ReadDiskSector  (  unsigned long  sectorN   )   
{
    if (SeekSector(CMD17,sectorN)) return ERR; //seek error
    if (ReadSector())
	{
        return ERR; //read error
    }
     return 0; /* All OK return */
}

 


unsigned char WriteSector()
{
	 unsigned c1;
	 unsigned short i;
	 SPIPutCharWithoutWaiting(START_BLOCK_TOKEN);
	 for(i=0;i<512;i++)
     {
		 SPIPutChar(dataBufPtr[i]);
   	 }
	 SPIWait();
     c1=SPIGetChar();
	 if(c1==DATA_REC_NO_ERR)
	 return 0;
	 else return c1;
}		 
    
unsigned char WriteDiskSector(unsigned long sectorN)
{
	if (SeekSector(CMD24,sectorN)) return ERR; //seek error
    if (WriteSector())
	{
        return ERR; //read error
    }
	SD_XCS = SD_NOT_SELECTED;
    SPI8Clocks(4);
     return 0; /* All OK return */
}

unsigned char GetCID()
{
    if (SDCommand(0x4a,0,0,0,0)&0xfe)
    return 4; /* no storage info */
    SDWaitForData();
    SDGetData(30);
}

unsigned char RebootSD()
{
    unsigned char c;
	if(SDCommand(0x40,0,0,0,0)==0x01)
	{
		SPI8Clocks(2);
		SDCommand(0x7B,0,0,0,0);
	}
    else return ERR;
 	c=255;
    while ((c--)&&(SDCommand(0x41,0,0,0,16)))
	{
        Delay(10);
        if (c==1)
        return TIMEOUT; /* Not able to power up SD */
    }
    return 0;
}

unsigned char InitSD()
{
    unsigned char c;
	SD_XCS = SD_NOT_SELECTED;
       /* Allow SD some time and clock cycles to reset */
    for (c=0; c<100; c++)
	{    
        SPIPutCharWithoutWaiting(0xff);
        SPIWait();
	}
	SD_XCS = SD_SELECTED;
    Delay(20);
    if (RebootSD()) return 1; //not able to powerup;
   //An existing SD card should be able to respond now.
 
    GetCID();
   
   /* Set Block Size of 512 bytes (2 == 512 << 8) */
    if ((c=SDCommand(0x50,0,0,2,0))) return c|0x80; 
   
    SD_XCS = SD_NOT_SELECTED;
    SPIPutCharWithoutWaiting(0xff);
    for (c=0; c<100; c++)
	{
        SPIPutChar(0xff);
    }
    SPIWait();  
}

void SPI8Clocks  (  unsigned char  nClocks   )   
{
    while (nClocks--)
	{
    SPIPutCharWithoutWaiting(0xff);
    SPIWait();
    }
}

unsigned char SPIGetChar  (void)   
{
    SPIPutCharWithoutWaiting(0xff); /* send 0xff */
    SPIWait(); /* wait for the byte to transfer */
    return SPI_RESULT_BYTE; /* Return the received byte */
}

void Delay(unsigned short i)
{
   while(--i) ;
}




⌨️ 快捷键说明

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