📄 mmc.c
字号:
SPIPORT |= CS;
//SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1) | (1<<SPR0); /* enable SPI as master, set clk divider */
SPCR = (1<<SPE) | (1<<MSTR) | (0<<SPR1) | (0<<SPR0); /* enable SPI as master, set clk divider */
Delay_1ms(250);
/* start off with 80 bits of high data with card deselected */
for(i=0;i<10;i++)
SpiByte(0xff);
SPIPORT &= ~CS; /* select card */
/* now send CMD0 - go to idle state */
MMCCommand(0,0,0);
if (MMCGet() != 1)
{
SPIPORT |= CS;
return -1; // MMC Not detected
}
/* send CMD1 until we get a 0 back, indicating card is done initializing */
i = 0xffff;
while ((SpiByte(0xff) != 0) && (--i))
{
MMCCommand(1,0,0);
// WDR();
}
if (i == 0)
{
SPIPORT |= CS;
return -2; // Init Fail
}
SPIPORT |= CS;
return 0;
}
/************************************************************
* void MMCInfo(void)
*
* - gets and prints formatted CID and CSD info from card
************************************************************/
void MMCInfo(void)
{
int i;
MMCCommand(10,0,0);
if (MMCDataToken() != 0xfe) puts("MMC: error");
else puts("MMC: CID read\n\r\0");
// Skip 3 byte Manufacturer ID
//SpiByte(0xff);
//SpiByte(0xff);
//SpiByte(0xff);
putchar(SpiByte(0xff));
putchar(SpiByte(0xff));
putchar(SpiByte(0xff));
puts("MMC: Product Name : ");
for (i=0;i<7;i++) putchar(SpiByte(0xff));
puts("\n\r\0");
for (i=0;i<9;i++) SpiByte(0xff); // Read 9 left byte
SPIPORT |= CS;
}
/************************************************************
* int MMCReadSector(unsigned long lba, unsigned char * s)
*
* - reads a sector from the card (512 bytes)
* - takes sector # as param
************************************************************/
int MMCReadSector(unsigned long lba, char *s)
{
unsigned int i;
MMCCommand(17,(lba>>7) & 0xffff, (lba<<9) & 0xffff);
if (MMCDataToken() != 0xfe)
{
SEI();
return -1;
}
for (i=0;i<512;i++) /* read the sector */
{
*s++ = SpiByte(0xff);
}
SpiByte(0xff); /* checksum -> don't care about it for now */
SpiByte(0xff); /* checksum -> don't care about it for now */
SPIPORT |= CS;
return 0;
}
/************************************************************
* int MMCWriteSector(unsigned long lba, unsigned char * s)
*
* - reads a sector from the card (512 bytes)
* - takes sector # as param
************************************************************/
int MMCWriteSector(unsigned long lba, char *s)
{
unsigned int i;
MMCCommand(24, (lba>>7)& 0xffff, (lba<<9)& 0xffff);
if (MMCGet() == 0xff) return -1;
SpiByte(0xfe); // Send Start Byte
for (i=0;i<512;i++) /* read the sector */
{
SpiByte(*s++);
}
SpiByte(0xff); /* checksum -> don't care about it for now */
SpiByte(0xff); /* checksum -> don't care about it for now */
SpiByte(0xff); /* Read "data response byte" */
i = 0xffff;
while ((SpiByte(0xff) == 0x00) && (--i)); /* wait for write finish */
if (i == 0) return -1; // Error
SPIPORT |= CS;
return 0;
}
/************************************************************
* unsigned char MMCGet(void)
*
* - pings the card until it gets a non-0xff value
* - returns one byte of read info
************************************************************/
unsigned char MMCGet(void)
{
unsigned int i = 0xffff;
unsigned char Byte = 0xff;
while((Byte == 0xff) && (--i)) Byte = SpiByte(0xff);
return Byte;
}
/************************************************************
* int MMCDataToken(void)
*
* - pings the card until it gets data token
* - returns one byte of read info (data token)
************************************************************/
unsigned char MMCDataToken(void)
{
unsigned int i = 0xffff;
unsigned char Byte = 0xff;
while((Byte != 0xfe) && (--i)) Byte = SpiByte(0xff);
return Byte;
}
/************************************************************
* void MMCCommand(unsigned char command, unsigned int px, unsigned int py)
*
* - send one byte of 0xff, then issue command + params + (fake) crc
* - eat up the one command of nothing after the CRC
************************************************************/
void MMCCommand(unsigned char command, unsigned int px, unsigned int py)
{
SPIPORT &= ~CS;
SpiByte(0xff);
SpiByte(command | 0x40);
SpiByte((unsigned char)((px >> 8)&0x0ff)); /* high byte of param y */
SpiByte((unsigned char)(px & 0x00ff)); /* low byte of param y */
SpiByte((unsigned char)((py >> 8)&0x0ff)); /* high byte of param x */
SpiByte((unsigned char)(py & 0x00ff)); /* low byte of param x */
SpiByte(0x95); /* correct CRC for first command in SPI */
/* after that CRC is ignored, so no problem with */
/* always sending 0x95 */
SpiByte(0xff);
}
/*****************************************************
* Main SPI routine
* - transmits a byte and receives a byte simultaneously
* - received byte is returned
* - if you only want to read a byte, put a dummy
* (say 0xff) in the transmit slot
****************************************************/
unsigned char SpiByte(unsigned char byte)
{
//WDR();
SPDR = byte; /* put byte to send in SPDR, which initiates xmit */
while(!(SPSR & (1<<SPIF)));/* wait for completion */
return SPDR; /* return with byte shifted in from slave */
}
/*****************************************************/
unsigned char read_VFAT_info(void)
{
unsigned long sec;
unsigned int bpb;
unsigned int n;
// printf("Type of FAT: FAT%c\n",FATtype);
MMCReadSector(0,&DataBuff[0]);
Delay_1ms(1);
//read_32(446); // MBR
bpb = (unsigned int)DataBuff[8+446] + ((unsigned int)DataBuff[9+446]<<8); // BPB
//printf("bpb: %u\n",bpb);
MMCReadSector(bpb,&DataBuff[0]);
Delay_1ms(1);
n = (unsigned int)DataBuff[11] + ((unsigned int)DataBuff[12] << 8);
//printf("N: %u\n",n);
if (n != 512){
return 2;
}
SectorsPerCluster = DataBuff[13];
// printf("SPCluster: %u\n",SectorsPerCluster);
FATstart = bpb + (unsigned int)DataBuff[14] + ((unsigned int)DataBuff[15] << 8);
Delay_1ms(1);
// printf("FATstart: %u\n",FATstart);
RootDirEntriesCount = (unsigned int)DataBuff[17] + ((unsigned int)DataBuff[18] << 8);
// printf("RootDirEntriesCount: %u\n",RootDirEntriesCount);
Delay_1ms(1);
n = (unsigned int)DataBuff[22] + ((unsigned int)DataBuff[23] << 8);
if (n == 0){
return 1; // FAT32
}
DIRstart =(unsigned int) FATstart + (unsigned int)DataBuff[16] * (unsigned int)n; // FAT
Delay_1ms(1);
// printf("DIRstart: %u\n",DIRstart);
// printf("FATstart: %u\n",FATstart);
// printf("Buff: %x\n",DataBuff[16]);
// printf("N: %u\n",n);
n = RootDirEntriesCount / 16;
if (RootDirEntriesCount % 16){
n++;
}
// printf("N: %u\n",n);
DataStart =(unsigned long)DIRstart + (unsigned long)n;
// printf("DataStart: %u\n",DataStart);
sec = (unsigned long)DataBuff[19] + ((unsigned long)DataBuff[20] << 8);
if (sec == 0){
// read_32((unsigned long)bpb * 512 + 32);
MMCReadSector((unsigned long)bpb,&DataBuff[0]);
sec = (unsigned long)DataBuff[0+ 32] + ((unsigned long)DataBuff[1+ 32] << 8)
+ ((unsigned long)DataBuff[2+ 32] << 16) + ((unsigned long)DataBuff[3+ 32] << 24);
}
sec -= FATstart;
sec /= SectorsPerCluster;
if (sec >= 0x1000){
FATtype = 1;
// printf("FAT16"); // FAT16
} else {
FATtype = 0; // FAT12
// printf("FAT12");
}
return 0;
}
unsigned int Search_File(unsigned int num)
{
unsigned int ent;
unsigned long sec;
unsigned char i, j;
unsigned int n;
n = 0;
MMCReadSector((unsigned long)DIRstart,&DataBuff[0]);
// sec = (unsigned long)DIRstart * 512;
for (ent = 0; ent < RootDirEntriesCount/16; )
{
for (i = 0; i < 16; i++)
{
if (DataBuff[0+i*32] == 0) break;
if (((DataBuff[26+i*32] != 0)||(DataBuff[27+i*32] != 0))&&
(DataBuff[0+i*32] != 0xE5)&&
(!(DataBuff[11+i*32] & 0x18))&&
(DataBuff[8+i*32]=='T')&&(DataBuff[9+i*32]=='X')&&(DataBuff[10+i*32]=='T'))
{
n++;
if (--num == 0) break;
}
}
ent++;
if (DataBuff[0] == 0) break;
if (num == 0) break;
// sec += 512;
MMCReadSector((unsigned long)DIRstart+(unsigned long)ent,&DataBuff[0]);
}
return n;
}
unsigned int read_word(unsigned int addr)
{
unsigned int w;
unsigned int l;
unsigned int h;
l = addr & 511;
h &= addr>>8;
MMCReadSector((unsigned long)h,&DataBuff[0]);
w = (unsigned int)DataBuff[l++];
w |= ((unsigned int)DataBuff[l] << 8);
return w;
}
/////////////////////////////////////////////////////////////////////////////////////
// NextCluster = next_cluster(Cluster, 0, 0);
unsigned int next_cluster(unsigned int c, unsigned long sec, unsigned int remain)
{
unsigned long addr;
unsigned int data;
unsigned long fatadr;
unsigned int i;
unsigned int l,h;
if (FATtype == 0)
{} // FAT12
else
{ // FAT16
MMCReadSector(FATstart,&DataBuff[0]);
if ((sec != 0)&&(fatadr != FatCacheAddr))
{
for (i = remain; i < 512; i++) SpiByte(0xff);
c = (unsigned int)DataBuff[l++];
c |= ((unsigned int)DataBuff[l] << 8);
for (i = 0; i < remain; i++) SpiByte(0xff);
}
else
{
c = (unsigned int)DataBuff[l++];
c |= ((unsigned int)DataBuff[l] << 8);
}
if (c >= 0xFFF8) c = 0xFFFF;
}
return c;
}
/////////r = play_music(PlayMusic);
/////////r = play_music(1);
char play_music(unsigned int fn)
{
unsigned long sec;
unsigned int remain;
unsigned int cn;
unsigned int i,j;
// printf("DataStart: %u\n",DataStart);
if (fn != Search_File(fn))
{
return -1;
}
FileSize = (unsigned long)DataBuff[28+64] + ((unsigned long)DataBuff[29+64]<<8)
+ ((unsigned long)DataBuff[30+64]<<16) + ((unsigned long)DataBuff[31+64]<<24);
Cluster = (unsigned int)DataBuff[26] + ((unsigned int)DataBuff[27] << 8);
RemainSec = FileSize / 512;//文件占用的扇区数
remain = FileSize % 512;
sec = DataStart;
for (j = 0; j<RemainSec; j++)
{
MMCReadSector(sec+j,&DataBuff[0]);
// DisPlay();
for (i = 0; i < 512; i++)
{
putchar(DataBuff[i]);
}
}
if ((remain > 0)&&(remain < 512))
{
MMCReadSector(sec+RemainSec,&DataBuff[0]);
// DisPlay();
for (i = 0; i < remain; i++)
{
putchar(DataBuff[i]);
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -