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

📄 sd.c

📁 51环境下的FAT及FAT32文件系统源码
💻 C
字号:
// sd.c
// SD/MMC access routines
// modified from holger.klabunde from AVR to C8051
//#########################################################################
#include "common.h"
#include "sd.h"
#include "fat.h"
#include "rbccmd.h"

#define BYTE_PER_SEC 512
extern SYS_INFO_BLOCK xdata DeviceInfo;

extern UINT8 xdata DBUF[512];  // defined in the main program
extern UINT8 xdata FATBUF[512];
extern UINT8 xdata RDIRBUF[512];
extern UINT8 xdata respBuf[16];

unsigned int c_size, c_size_mult, read_bl_len;
unsigned long drive_size, maxsect;

unsigned char GetDevInfo( )
{
	unsigned long FATSz;
	unsigned long TotSec;
	unsigned long RootDirSectors;
	unsigned long DataSec;
	unsigned long CountofClusters;

	pMBR_BLOCK pMBR;
	pBPB_BLOCK pBPB;
    pBPB_BLOCK32 pBPB32;

	pMBR=(pMBR_BLOCK)FATBUF;

	DeviceInfo.BPB_BytesPerSec=512; //暂假设为512

// Read sector 0 (Partition table)
	if(!SDReadFat(0x0))
		return 0;
	//////////////////////////////////
    SendUart(FATBUF, 512);  // debug

	if(FATBUF[0]==0xeb||FATBUF[0]==0xe9)
		{
		DeviceInfo.StartSector=0;
		}
	else
		{
	//////////////////////////////////
		DeviceInfo.StartSector=SwapINT32(pMBR->StartSector);
		}
	///////////////////////////////////////////////////////
	DelayUs(5);
    pBPB=(pBPB_BLOCK)FATBUF;
	if(!SDReadFat(DeviceInfo.StartSector))
		return 0;

    SendUart(FATBUF, 512);  // debug

	DeviceInfo.BPB_BytesPerSec=WordSwap(pBPB->BPB_BytesPerSec);
	DeviceInfo.BPB_SecPerClus=pBPB->BPB_SecPerClus;
	DeviceInfo.BPB_NumFATs=pBPB->BPB_NumFATs;
	DeviceInfo.BPB_RootEntCnt=WordSwap(pBPB->BPB_RootEntCnt);
	DeviceInfo.BPB_TotSec16=WordSwap(pBPB->BPB_TotSec16);
	DeviceInfo.BPB_FATSz16=WordSwap(pBPB->BPB_FATSz16);
	DeviceInfo.BPB_FATSz32=WordSwap(pBPB32->BPB_FATSz32);
	DeviceInfo.BPB_TotSec32=SwapINT32(pBPB->BPB_TotSec32);
	DeviceInfo.FatStartSector=DeviceInfo.StartSector+WordSwap(pBPB->BPB_RsvdSecCnt);
	DeviceInfo.RootStartSector=DeviceInfo.FatStartSector+2*DeviceInfo.BPB_FATSz16;
	DeviceInfo.FirstDataSector=DeviceInfo.RootStartSector+0x20;
	///////////////////////////////////////////////////////
//	ThisFile.bFileOpen=0;

	//Judge the FAT type
	if(DeviceInfo.BPB_FATSz16 != 0)
	    FATSz = DeviceInfo.BPB_FATSz16;
	else
	    FATSz = DeviceInfo.BPB_FATSz32;  
	
	if(DeviceInfo.BPB_TotSec16 != 0)
	    TotSec = DeviceInfo.BPB_TotSec16;
	else
	    TotSec = DeviceInfo.BPB_TotSec32;
	
	RootDirSectors = ((DeviceInfo.BPB_RootEntCnt * 32) + (DeviceInfo.BPB_BytesPerSec - 1)) / DeviceInfo.BPB_BytesPerSec;
	DataSec = TotSec - (WordSwap(pBPB->BPB_RsvdSecCnt) + (DeviceInfo.BPB_NumFATs * FATSz) + RootDirSectors);
	CountofClusters = DataSec / DeviceInfo.BPB_SecPerClus;

	if(CountofClusters < 4085) 
	{
		DeviceInfo.bFatType = 1; //fat12
	} 
	else if(CountofClusters < 65525) 
	{
	    DeviceInfo.bFatType = 2; //fat16

	} 
	else 
	{
	    DeviceInfo.bFatType = 3; //fat32
		DeviceInfo.TotCluster =
		(DeviceInfo.BPB_TotSec32-DeviceInfo.FirstDataSector+1)/DeviceInfo.BPB_SecPerClus+1;

	}
	//End Judge the FAT type
}
//######################################################
unsigned char SDCommand(unsigned char command, unsigned char *pAddr)
//######################################################
{
  unsigned char i, addr[4];
  
  for (i=0;i<4;i++)
  {
  	addr[i] = *pAddr;
	pAddr++;
  }

  SPI_WRITE(0xFF);     //Dummy write
  SPI_WRITE(command);
  SPI_WRITE(addr[0]);   //MSB of address
  SPI_WRITE(addr[1]);
  SPI_WRITE(addr[2]);
  SPI_WRITE(addr[3]);   //LSB of address
  SPI_WRITE(0xFF);     //dummy checksum
  
 // SPI_WRITE(0xFF);

  return (1);
}
//
unsigned char SDMp3Read(unsigned long sector)
//######################################################
{
 unsigned int i;
 unsigned long startadr;

//  SPI_CTL1 = SPI_3M; // set high speed

// if(sector>=maxsect) return 0; //sectornumber too big
  BufRst = 0x3;             // reset peripheral fifo
  BufRst = 0x0;

//calculate startadress of the sector

  startadr=sector * (unsigned long)BYTE_PER_SEC;
  
  SDCommand(SD_READ_BLOCK, (unsigned char *)&startadr);
  do
  {
   SPI_WRITE(0xFF);
  }while(!(SPI_STA0 & SPI_RRDY)); // wait for card response
  
   do
  {
   SPI_WRITE(0xFF);
  }while (SPI_DATA != 0x0); // wait for response token

  do
  {
   SPI_WRITE(0xFF);
  }while (SPI_DATA & 0x1); // wait for data start
 
  for(i=0; i<BYTE_PER_SEC; i++)
  {
    SPI_WRITE(0xFF);     // shift out a byte into SPI_DATA
    BufAddr=SPI_DATA;  // store byte in buffer
  } 

  SPI_WRITE(0xFF);  // 16 bit crc follows data
  SPI_WRITE(0xFF);
//  SPI_CTL1 = SPI_1P5M; // set high speed
  return 1;
}
//######################################################
unsigned char SDReadSector(unsigned long sector)
//######################################################
{
 unsigned int i;
 unsigned long startadr;

 if(sector>=maxsect) return 1; //sectornumber too big

//calculate startadress of the sector
 startadr=sector * (unsigned long)BYTE_PER_SEC;

 //SendUart((unsigned char *)&startadr, 4);
 SDCommand(SD_READ_BLOCK, (unsigned char *)&startadr);

  do
  {
   SPI_WRITE(0xFF);
  }while(!(SPI_STA0 & SPI_RRDY)); // wait for card response

  do
  {
   SPI_WRITE(0xFF);
  }while (SPI_DATA != 0x0); // wait for response token

  do
  {
   SPI_WRITE(0xFF);
  }while (SPI_DATA & 0x1); // wait for data start
 
  for(i=0; i<BYTE_PER_SEC; i++)
  {
    SPI_WRITE(0xFF);     // shift out a byte into SPI_DATA
    DBUF[i]=SPI_DATA;  // store byte in buffer
  } 

  SPI_WRITE(0xFF);  // 16 bit crc follows data
  SPI_WRITE(0xFF);

  return 1;
}

//######################################################
unsigned char SDReadFat(unsigned long sector)
//######################################################
{
 unsigned int i;
 unsigned long startadr;

 if(sector>=maxsect) return 1; //sectornumber too big

//calculate startadress of the sector
 startadr=sector * (unsigned long)BYTE_PER_SEC;

 //SendUart((unsigned char *)&startadr, 4);
 SDCommand(SD_READ_BLOCK, (unsigned char *)&startadr);

  do
  {
   SPI_WRITE(0xFF);
  }while(!(SPI_STA0 & SPI_RRDY)); // wait for card response

  do
  {
   SPI_WRITE(0xFF);
  }while (SPI_DATA != 0x0); // wait for response token

  do
  {
   SPI_WRITE(0xFF);
  }while (SPI_DATA & 0x1); // wait for data start
 
  for(i=0; i<BYTE_PER_SEC; i++)
  {
    SPI_WRITE(0xFF);     // shift out a byte into SPI_DATA
    FATBUF[i]=SPI_DATA;  // store byte in buffer
  } 

  SPI_WRITE(0xFF);  // 16 bit crc follows data
  SPI_WRITE(0xFF);

  return 1;
}

unsigned char SDReadRdir(unsigned long sector)
//######################################################
{
 unsigned int i;
 unsigned long startadr;

 if(sector>=maxsect) return 1; //sectornumber too big

//calculate startadress of the sector
 startadr=sector * (unsigned long)BYTE_PER_SEC;

 //SendUart((unsigned char *)&startadr, 4);
 SDCommand(SD_READ_BLOCK, (unsigned char *)&startadr);

  do
  {
   SPI_WRITE(0xFF);
  }while(!(SPI_STA0 & SPI_RRDY)); // wait for card response

  do
  {
   SPI_WRITE(0xFF);
  }while (SPI_DATA != 0x0); // wait for response token

  do
  {
   SPI_WRITE(0xFF);
  }while (SPI_DATA & 0x1); // wait for data start
 
  for(i=0; i<BYTE_PER_SEC; i++)
  {
    SPI_WRITE(0xFF);     // shift out a byte into SPI_DATA
    RDIRBUF[i]=SPI_DATA;  // store byte in buffer
  } 

  SPI_WRITE(0xFF);  // 16 bit crc follows data
  SPI_WRITE(0xFF);

  return 1;
}
//######################################################
unsigned char SDWriteSector(unsigned long sector, unsigned char *pDBUF)
//######################################################
{
 unsigned int i;
 unsigned char by;
 unsigned long startadr;

 if(sector>=maxsect) return 1; //sectornumber too big

//calculate startadress
// startadr=sector * (unsigned long)BYTE_PER_SEC;
 startadr=sector<<9;

 SDCommand(SD_WRITE_BLOCK,(unsigned char *)&startadr);

 SPI_WRITE(0xFF); // do we need this TWO dummy writes ?
 SPI_WRITE(0xFF);

 SPI_WRITE(0xFE); // start block token

 for(i=0; i<BYTE_PER_SEC; i++)
  {
   SPI_WRITE(*pDBUF++);
  }

 SPI_WRITE(0xFF); // 16 bit crc follows data
 SPI_WRITE(0xFF);

 SPI_WRITE(0xFF); // read response
 by=SPI_DATA & 0x1F;
 if(by != 0x05)   // data block accepted ?
  {
   return 1;
  }

 do
  {
   SPI_WRITE(0xFF);
  }while(SPI_DATA !=0xFF); // wait til busy is gone

 return 0;
}

//######################################################
unsigned char SDIdentify(void)
//######################################################
{
 unsigned char by;
 unsigned int i;
 unsigned long addr;

// pCSD_BLOCK pCSD;

// SPI_CTL0
// SPI_LSB=0   Send MSB first
// SPI_CPOL=1  SCK high if IDLE
// SPI_CPHA=1  SPI Mode 1
// SPI_MST=1   I am the master
// SPI_TIE=0   No SPI TX Interrupt
// SPI_RIE=0   No SPI RX Interrupt
// SPI_EN=1    SPI Enable
// SPI_SSOEN=0 Output enable for select
  SPI_CTL0 = 0x4E;
 
// SPI_CTL1
  SPI_CTL1 = SPI_750K;  // set speed
 
 for(i=0; i<10; i++) SPI_WRITE(0xFF); // give min 74 clock pulses before
                                      // sending commands

//send CMD0 for RESET
 SPI_WRITE(SD_RESET); //command code CMD0
 SPI_WRITE(0x00);
 SPI_WRITE(0x00);
 SPI_WRITE(0x00);
 SPI_WRITE(0x00);
 SPI_WRITE(0x95); // CMD0 needs a checksum !
 SPI_WRITE(0xFF); // get 16 bit response high

 while(!(SPI_STA0&SPI_RRDY)); 
 respBuf[0]=SPI_DATA; 
 SPI_WRITE(0xFF);
 while(!(SPI_STA0&SPI_RRDY)); 
 respBuf[1]=SPI_DATA; 
 SPI_WRITE(0xFF);
 while(!(SPI_STA0&SPI_RRDY)); 
 respBuf[2]=SPI_DATA; 
 SPI_WRITE(0xFF);
 while(!(SPI_STA0&SPI_RRDY)); 
 respBuf[3]=SPI_DATA; 
 SPI_WRITE(0xFF);
 while(!(SPI_STA0&SPI_RRDY)); 
 respBuf[4]=SPI_DATA; 
 SPI_WRITE(0xFF);
 while(!(SPI_STA0&SPI_RRDY)); 
 respBuf[5]=SPI_DATA; 
 SPI_WRITE(0xFF);
 while(!(SPI_STA0&SPI_RRDY)); 
 respBuf[6]=SPI_DATA; 
 SPI_WRITE(0xFF);
 while(!(SPI_STA0&SPI_RRDY)); 
 respBuf[7]=SPI_DATA; 
 SPI_WRITE(0xFF);

 SendUart(respBuf, 8);
 DelayUs(100);

 addr = 0;
//repeat CMD1 til result=0
 do
  {
   SDCommand(SD_INIT,(unsigned char *) &addr);
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY));   //wait last byte rcv
   respBuf[0]=SPI_DATA; 
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY)); 
   respBuf[1]=SPI_DATA; 
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY)); 
   respBuf[2]=SPI_DATA; 
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY)); 
   respBuf[3]=SPI_DATA; 
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY)); 
   respBuf[4]=SPI_DATA; 
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY)); 
   respBuf[5]=SPI_DATA; 
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY)); 
   respBuf[6]=SPI_DATA; 
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY)); 
   respBuf[7]=SPI_DATA; 
   SPI_WRITE(0xFF);

   SendUart(respBuf, 8);
// DelayUs(50);

 //  SendUart(respBuf, 8);        // send back response
  }while(respBuf[2]!=0);

  // flush out any garbage
 // for(i=0; i<10; i++) SPI_WRITE(0xFF); 
  DelayUs(100);  
//read CID
// SDCommand(SD_READ_CID,0); // nothing really interesting here

//read CSD Card Specific Data
  SDCommand(SD_READ_CSD,(unsigned char *) &addr);
//  SPI_WRITE(0xFF); // ignore response 0xFE
  
  do
  {
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY));   //wait last byte rcv
  }while (SPI_DATA != 0); // wait for response token

  do
  {
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY));   //wait last byte rcv
  }while (SPI_DATA & 0x1); // wait for data start

  SDResp(18);
  SendUart(respBuf,18);
 
  //pCSD = (pCSD_BLOCK) respBuf;
  // FIXME: lets test if this data structure is OK
  
  //c_size=pCSD->CSD_DevSize;
  //read_bl_len=pCSD->CSD_RdBlkLen;
  //c_size_mult=pCSD->CSD_DevSizeMult;
// 
 c_size=respBuf[6] & 0x03; //bits 1..0
 c_size<<=10;
 c_size+=(unsigned int)respBuf[7]<<2;
 c_size+=respBuf[8]>>6;

 by= respBuf[5] & 0x0F;
 read_bl_len=1;
 read_bl_len<<=by;

 by=respBuf[9] & 0x03;
 by<<=1;
 by+=respBuf[10] >> 7;
 
 c_size_mult=1;
 c_size_mult<<=(2+by);
//
  drive_size=(unsigned long)(c_size+1) * (unsigned long)c_size_mult * (unsigned long)read_bl_len;
  maxsect= drive_size / BYTE_PER_SEC;

  SendUart((unsigned char *)&drive_size,4);
  SendUart((unsigned char *)&maxsect,4);

  DelayUs(50);
  addr = 512;
  SDCommand(SD_SET_BLOCKLEN,(unsigned char *) &addr);
  do
  {
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY));   //wait last byte rcv
  }while (SPI_DATA != 0); // wait for response token
  
  addr = 0;
  SDCommand(SD_SEND_STATUS,(unsigned char *) &addr);
  do
  {
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY));   //wait last byte rcv
  }while (SPI_DATA != 0); // wait for response token

  do
  {
   SPI_WRITE(0xFF);
   while(!(SPI_STA0&SPI_RRDY));   //wait last byte rcv
  }while (SPI_DATA & 0x1); // wait for data start

  SDResp(2);
  SendUart(respBuf,2);
 
 return 0;
}

unsigned char SDResp(unsigned char respLen)
{
  unsigned char i;
  
  for (i=0;i<respLen;i++)
  {
  	SPI_DATA = 0xff;
  	while(!(SPI_STA0&SPI_RRDY));   //wait last byte rcv
    respBuf[i] = SPI_DATA;
  }

  return(1);	
}

unsigned char UartWaitCmd()
{
  unsigned char uCmd;
  unsigned char uArg;
  unsigned char skipSong;

  while (!(SCON & SCON_RXINT));
  SCON = SCON_FAST;
  uCmd = SBUF;
  
  while (!(SCON & SCON_RXINT));
  SCON = SCON_FAST;
  uArg = SBUF;

 // SendUart(&uCmd,1);
 // SendUart(&uArg,1);

  if (!(uCmd ^ 0x1))
  {
	Volume = uArg;
	uCmd = Volume;
	SendUart(&uCmd, 1);
  }
  else if (!(uCmd ^ 0x2))
  {
	Mode = uArg;
	uCmd = Mode;
	SendUart(&uCmd, 1);
  }
  else if (!(uCmd ^ 0x3))
  {
    skipSong = uArg;
    uCmd = skipSong;
	SendUart(&uCmd, 1);
  }
  else 
  {
    uCmd = 0xAA;
    SendUart(&uCmd, 1);
    return (0);
  }
  return (1);
}

⌨️ 快捷键说明

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