📄 sd.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 *)§orN;
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 + -