📄 mmc.c
字号:
/*
Copyright: Radig Ulrich mailto: mail@ulrichradig.de
Author: Radig Ulrich
Remarks:
known Problems: none
Version: 28.05.2004
Description: Ansteuerung einer MMC/SD-Memory-Card
*/
#define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
#define MMC_Read PINB
#define MMC_Direction_REG DDRB
#define SPI_DI 3 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
#define SPI_DO 2 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
#define SPI_Clock 1 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
#define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
#define SPI_SS 0
//Prototypes
char Read_Byte_MMC(void);
void Write_Byte_MMC(char);
char Init_MMC(void);
char Read_Block_MMC (unsigned long, char *Buffer);
char Write_Block_MMC (unsigned long, char *Buffer);
char Write_Command_MMC (char *CMD);
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
char Init_MMC ()
{
char tmp = 0;
char Timeout;
//Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
cbi(MMC_Direction_REG,SPI_DI); //Setzen von Pin MMC_DI auf Input
sbi(MMC_Direction_REG,SPI_Clock); //Setzen von Pin MMC_Clock auf Output
sbi(MMC_Direction_REG,SPI_DO); //Setzen von Pin MMC_DO auf Output
sbi(MMC_Direction_REG,MMC_Chip_Select); //Setzen von Pin MMC_Chip_Select auf Output
sbi(MMC_Direction_REG,SPI_SS);
sbi(MMC_Write,MMC_Chip_Select); //Setzt den Pin MMC_Chip_Select auf High Pegel
for(int a=0;a<2000;a++){}; //Wartet eine kurze Zeit
//Aktiviren des SPI - Bus, Clock = Idel High
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); //Enable SPI, SPI in Master Mode
//Initialisiere MMC/SD-Karte in den SPI-Mode
for (int b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte
{
Write_Byte_MMC(0x0f);
}
//Sendet Commando CMD0 an MMC/SD-Karte
Timeout = 0;
char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
while(tmp!=1)
{
tmp = Write_Command_MMC (CMD);
//printf ("Return Code from MMC/SD Init CMD0 %x\n",tmp);
Timeout++;
if (Timeout > 20)
{
return(1); //Abbruch bei Commando1 (Return Code1)
}
}
//Sendet Commando CMD1 an MMC/SD-Karte
Timeout = 0;
CMD[0] = 0x41;//Commando 1
CMD[5] = 0xFF;
while(tmp!=0)
{
tmp = Write_Command_MMC (CMD);
//printf ("Return Code from MMC/SD Init CMD1 %x\n",tmp);
Timeout++;
if (Timeout > 10)
{
return(2); //Abbruch bei Commando2 (Return Code2)
}
}
return(0);
}
//Sendet ein Commando an die MMC/SD-Karte
char Write_Command_MMC (char *CMD)
{
char tmp = 0xff;
unsigned int Timeout = 0;
//sendet 8 Clock Impulse
sbi(MMC_Write,MMC_Chip_Select);//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
Write_Byte_MMC(0x00);
//sendet 6 Byte Commando
cbi(MMC_Write,MMC_Chip_Select);//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
for (int a = 0;a<0x06;a++) //sendet 6 Byte Commando zur MMC/SD-Karte
{
Write_Byte_MMC(*CMD++);
}
while (tmp == 0xff) //Wartet auf ein g黮tige Antwort von der MMC/SD-Karte
{
tmp = Read_Byte_MMC();
Timeout++;
if (Timeout > 1000)
{
break; //Abbruch da die MMC/SD-Karte nicht Antwortet
}
}
return(tmp);
}
//Routine zum Empfangen eines Bytes von der MMC-Karte (Soft_SPI)
char Read_Byte_MMC (void)
{
char Byte = 0;
outb(SPDR,0xff);
while(!(SPSR & (1<<SPIF)))
{
}
Byte = inp(SPDR);
return (Byte);
}
//Routine zum Senden eines Bytes zur MMC-Karte (Soft_SPI)
void Write_Byte_MMC (char Byte)
{
outb(SPDR,Byte);
while(!(SPSR & (1<<SPIF)))
{
}
}
//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
char Read_Block_MMC (unsigned long addr,char *Buffer)
{
char tmp;
int Timeout;
char CMD17[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; //Commando 16 zum lesen eines Blocks
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingef黦t*/
addr = addr << 9; //addr = addr * 512
CMD17[1] = ((addr & 0xFF000000) >>24 );
CMD17[2] = ((addr & 0x00FF0000) >>16 );
CMD17[3] = ((addr & 0x0000FF00) >>8 );
//Sendet Commando CMD16 an MMC/SD-Karte (Read 1 Block/512 Bytes)
tmp = Write_Command_MMC (CMD17);
if (tmp != 0)
{
return(tmp);
}
//Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
Timeout = 0;
while (tmp != 0xfe)
{
tmp = Read_Byte_MMC();
Timeout++;
if (Timeout > 1000)
{
return(1);
}
}
//Lesen des Bolcks (512Bytes) von MMC/SD-Karte
for (int a=0;a<512;a++)
{
*Buffer++ = Read_Byte_MMC();
}
//CRC-Byte auslesen
tmp = Read_Byte_MMC();//CRC - Byte wird nicht ausgewertet
tmp = Read_Byte_MMC();
return(0);
}
//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
char Write_Block_MMC (unsigned long addr, char *Buffer)
{
char tmp;
char CMD24[] = {0x58,0x00,0x00,0x00,0x00,0xFF}; //Commando 24 zum schreiben eines Blocks
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingef黦t*/
addr = addr << 9; //addr = addr * 512
CMD24[1] = ((addr & 0xFF000000) >>24 );
CMD24[2] = ((addr & 0x00FF0000) >>16 );
CMD24[3] = ((addr & 0x0000FF00) >>8 );
//Sendet Commando CMD24 an MMC/SD-Karte (Write 1 Block/512 Bytes)
tmp = Write_Command_MMC (CMD24);
if (tmp != 0)
{
return(tmp);
}
//Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte
for (int a=0;a<100;a++)
{
tmp = Read_Byte_MMC();
}
//Sendet Start Byte an MMC/SD-Karte
Write_Byte_MMC(0xFE);
//Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
for (int a=0;a<512;a++)
{
Write_Byte_MMC(*Buffer++);
}
//CRC-Byte schreiben
Write_Byte_MMC(0xFF); //Schreibt Dummy CRC
Write_Byte_MMC(0xFF); //CRC Code wird nicht benutzt
//Wartet auf MMC/SD-Karte Bussy
tmp = 0;
while (tmp != 0xff)
{
tmp = Read_Byte_MMC();
}
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -