here is the code for writing and reading a single sector
CODE for ATmega8535
#include <iom8535v.h>
#include <macros.h>
#define SPIDDR DDRB
#define SPIPORT PORTB
#define SPIPIN PINB
#define CS 0x10
#define BinToASCII(t)((t<=9) ? (t|0x30):(t+55))
#define ASCIIToBin(t) ((t>='A'&& t<='F')?t-55:((t>='0' && t<='9') ? t-'0':0))
#define BYTELOW(v) (*((unsigned char *) (&v)))
#define BYTEHIGH(v) (*(((unsigned char *) (&v) + 1)))
#define BLOCK_SIZE 512
const unsigned char CMD0_RST_IDLE[] ={0x40,0x00,0x00,0x00,0x00,0x95};
//command 0 reset all card to idle state
const unsigned char CMD1_SND_OPCND[]={0x41,0x00,0x00,0x00,0x00,0xFF};
//command 1 for read OPERATION CONDITION register const unsigned char CMD16_SET_BLOCKLEN[]={0x50,0x00,0x00,0x02,0x00,0xFF};
//command 16 TO SET BLOCK LENGHT=512 BYTE TO READ & WRITE
//0x000200=512 & 0x00000010=16
const unsigned char MSGF[] ={"\rMMC CARD INTERFACE \r"};
const unsigned char MSG0[] ={"\rMMC CARD COMMAND 0 \r"};
const unsigned char MSG1[] ={"\rMMC CARD COMMAND 1 \r"};
const unsigned char MSGB[] ={"\rMMC CARD COMMAND BLOCK=512 \r"};
const unsigned char MSGW[] ={"\rMMC CARD SECTOR WRITE \r"};
const unsigned char MSGR[] ={"\rMMC CARD SECTOR READ \r"};
const unsigned char MSG[] ={"\nMMC CARD IS INITIALIZED SPI MODE \n"};
const unsigned char CSD[] ={"\rCSD INFORMATION: \r"};
const unsigned char CID[] ={"\rCID INFORMATION: \r"};
const unsigned char WACK[] ={"\rWRITE ACKNOLEDGE: \r"};
const unsigned char WNFSH[] ={"\rWRITE NOT FINISH: \r"};
unsigned char TEMP;
unsigned int iSIZE;
unsigned int iSIZE1;
unsigned char BUFFER[128];
//ICC-AVR application builder : 29/09/2005 16:23:49
// Target : M32 Crystal: 11.0592Mhz
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0xFF;
DDRB = 0xFF;
PORTC = 0x00;
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x02;
}
//UART0 initialize
// desired baud rate: 57600
/* ************************************************************************ *\
In the ATmega32, the UBRRL & UBRRH registers must be written separately.
It is not possible to use the following construct:
UBRR = BAUD_RATE_REGISTER_VALUE;
as UBRRL & UBRRH are not in adjacent locations. See ATmega32 data sheet.
\* ************************************************************************ */
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = BIT(URSEL) | 0x06;
// UBRRL = 7; //set baud rate lo @ 11.0592 MHZ
UBRRL = 11; //set baud rate lo @ 14.7456 MHZ
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x18;
}
//call this routine to initialize all peripherals
void init_devices(void)
{
port_init();
uart0_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00;
}
/*
unsigned char ReceiveByte(void)
{
while(!(UCSRA & BIT(RXC))) ;
return UDR;
}*/
void SEND_CHAR_UART(char ch)
{
while(!(UCSRA & BIT(UDRE))) ;
UDR = ch;
}
void SendStr(const char *ch)
{ while(*ch != 0x00) SEND_CHAR_UART(*ch++);}
/*------------------------------------*/
void PRINT_ASCII (unsigned char PRNT)
{
unsigned char PRN=0;
PRN=PRNT>>4;
SEND_CHAR_UART(BinToASCII(PRN));
PRN=PRNT&0x0F;
SEND_CHAR_UART(BinToASCII(PRN));
}
void SpiInit()
{
DDRB |= 0xB0; // Set SCK, MOSI & SS as outputs
PORTB &= 0x5F; // clear bits MOSI, & SCK
SPCR = 0x53;
}
/*** SpiWriteByte() writes a byte to the SPI and waits until it has been transmitted.
This function doesn't return any value back.**/
unsigned char CHAR_SPI(unsigned char byte)
{
SPDR = byte;
while (!(SPSR & 0x80));
byte = SPDR;
return byte;
}
//**************************************
// void Delay_1ms(void)
//**************************************
void Delay_1ms(int Del)
{
int i;
while (Del--)
{ for (i=0;i<200;i++) WDR(); }
}
/*------------------------------------------------------------- */
//--------------------------------------------
// MMC GET RESPONSE
//--------------------------------------------
unsigned char MMC_RESPONCE(unsigned char RESPONSE )
{
unsigned int COUNT=0xFFFF;
unsigned char RESULT;
while(COUNT!=0)
{
RESULT = CHAR_SPI(0xFF);
// PRINT_ASCII (RESULT); SEND_CHAR_UART('\r'); //debug
if(RESULT==RESPONSE)
{ break;}
COUNT--;
}
if(COUNT==0)return 1;
else
return 0;
}
/**********************************/
unsigned char MMC_WAIT_FOR_WRITE_FINISH( void )
{
unsigned char LPCNT=0xFF;
unsigned char RESULT = 0;
/* The delay is set to maximum considering the longest data block length to handle */
while( (RESULT == 0) && LPCNT )
{ RESULT = CHAR_SPI( 0XFF);
LPCNT--;
}
if (LPCNT== 0 )
return 1; /* Failure, loop was exited due to timeout */
else return 0; /* Normal, loop was exited before timeout */
}
/*--------------------------------------------------------*/
unsigned char MMC_INIT()
{
//unsigned int i;
unsigned char LPCNT=0;
/* start off with 80 bits of high data with card deselected */
SPIPORT |=CS;
for(LPCNT=0;LPCNT<10; LPCNT++)
CHAR_SPI(0xff);
/*-----------------------------------------CMD 0------------------------------------------------*/
SPIPORT &= ~CS; /* select card */
CHAR_SPI( 0X40); CHAR_SPI( 0X00); CHAR_SPI( 0X00);
CHAR_SPI( 0X00); CHAR_SPI( 0X00); CHAR_SPI( 0X95);
if( (MMC_RESPONCE(0x01)) == 1 )
{
SPIPORT |=CS;
return 1;
}
SendStr( MSG0);
/*----------------------------------------------------------------------------------------------------*/
SPIPORT |= CS;
CHAR_SPI(0xFF);
/*-------------------------------------CMD1---------------------------------------------------------*/
SPIPORT &= ~CS;
LPCNT=0xFF;
do
{
CHAR_SPI( 0X41); CHAR_SPI( 0X00); CHAR_SPI( 0X00);
CHAR_SPI( 0X00); CHAR_SPI( 0X00); CHAR_SPI( 0XFF);
LPCNT--;
} while ( (MMC_RESPONCE(0x00) != 0) && (LPCNT>0) );
if(LPCNT==0)
{ SPIPORT |= CS; return 1; }
SendStr( MSG1);
/*--------------------------------------------------------------------*/
SPIPORT |= CS;
CHAR_SPI(0xFF);
/*---------------------------------------CMD16 SET BLOCK LENGTH--------------------------*/
SPIPORT &= ~CS; /* select card */
CHAR_SPI( 0X50); CHAR_SPI( 0X00); CHAR_SPI( 0X00);
CHAR_SPI( 0X02); CHAR_SPI( 0X00); CHAR_SPI( 0XFF);
if( (MMC_RESPONCE(0x00)) == 1 )
{
SPIPORT |=CS;
return 1;
}
SendStr( MSGB);
/*----------------------------------------------------------------------------------------------------*/
SPIPORT |= CS;
CHAR_SPI(0xFF);
return 0;
}
/*------------------------------------------------------------*/
//unsigned char MMC_WRITE_BLOCK( unsigned long SECTOR)
/*----------------------------------------------------------- */
void GET_CSD()
{
SPIPORT &= ~CS;
CHAR_SPI( 0x49); CHAR_SPI( 0x00); CHAR_SPI( 0X00);
CHAR_SPI( 0x00); CHAR_SPI( 0x00); CHAR_SPI( 0XFF);
while ((MMC_RESPONCE(0x00)) == 1);
while( (MMC_RESPONCE(0xFE)) == 1 );
for(TEMP=0;TEMP<=35;TEMP++)
BUFFER[TEMP]=CHAR_SPI(0xFF);
SendStr(CSD);
for(TEMP=0;TEMP<=15;TEMP++)
PRINT_ASCII(BUFFER[TEMP]);
SEND_CHAR_UART('\n');
SPIPORT |= CS; // Deselect card
}
/*------------------------------------------------------------*/
//void GET_CID()
/*----------------------------------------------------------- */
void GET_CID()
{
SPIPORT &= ~CS; // select card
CHAR_SPI( 0x4A); CHAR_SPI( 0x00); CHAR_SPI( 0X00);
CHAR_SPI( 0x00); CHAR_SPI( 0x00); CHAR_SPI( 0XFF);
while ((MMC_RESPONCE(0x00)) == 1);
while( (MMC_RESPONCE(0xFE)) == 1 );
for(TEMP=0;TEMP<=35;TEMP++)
BUFFER[TEMP]=CHAR_SPI(0xFF);
SendStr(CID);
for(TEMP=0;TEMP<=15;TEMP++)
PRINT_ASCII(BUFFER[TEMP]);
SEND_CHAR_UART('\n');
SPIPORT |= CS; // Deselect card
}
/*----------------------------------------------------*/
void INSULATOR()
{ CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);CHAR_SPI( 0xFF);
}
/*--------------------------------------------------------------------------------------*/
unsigned char MMC_READ_BLOCK( unsigned long SECTOR)
{
unsigned char LPCNT=0;
unsigned char LTMP=0;
unsigned long ADDRESS=0;
ADDRESS=SECTOR*BLOCK_SIZE;
/*-----------------------CMD17------------------------------------------------*/
SPIPORT &= ~CS;
CHAR_SPI( 0x51);
CHAR_SPI (ADDRESS>>24); CHAR_SPI (ADDRESS>>16);
CHAR_SPI (ADDRESS>>
; CHAR_SPI (ADDRESS>>0);
CHAR_SPI( 0xFF);
if( (MMC_RESPONCE(0x00)) == 1 )
{ SPIPORT |= CS;
return 1;
}
while( (MMC_RESPONCE(0xFE)) == 1 )
SEND_CHAR_UART('r');
for(LTMP=0;LTMP<4;LTMP++)
{
for(LPCNT=0;LPCNT<128; LPCNT++)
BUFFER[LPCNT]=CHAR_SPI(0xFF);
for(LPCNT=0;LPCNT<128; LPCNT++)
{
if((LPCNT%16)==0)SEND_CHAR_UART('\r');
//PRINT_ASCII(BUFFER[LPCNT]);
SEND_CHAR_UART(BUFFER[LPCNT]);
}
}
CHAR_SPI(0xFF); CHAR_SPI(0xFF); //rwad CHKSUM
SendStr( MSGR);
/*----------------------------------------------------------------------------*/
SPIPORT |= CS;
CHAR_SPI(0xFF);
return 0;
}
/*--------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------*/
unsigned char MMC_WRITE_BLOCK( unsigned int SECTOR,unsigned char WRT)
{
unsigned char LPCNT=0;
unsigned long ADDRESS=0;
ADDRESS=SECTOR*BLOCK_SIZE;
/*-----------------------CMD24------------------------------------------------*/
SPIPORT &= ~CS;
CHAR_SPI( 0x58);
CHAR_SPI (ADDRESS>>24); CHAR_SPI (ADDRESS>>16);
CHAR_SPI (ADDRESS>>
; CHAR_SPI (ADDRESS>>0);
CHAR_SPI( 0xFF);
if( (MMC_RESPONCE(0x00)) == 1 )
{
SPIPORT |=CS;
return 1;
}
CHAR_SPI(0xFF);
CHAR_SPI(0xFE); //start of DATABLOCK
for(LPCNT=0;LPCNT<128; LPCNT++)CHAR_SPI(WRT);
for(LPCNT=0;LPCNT<128; LPCNT++)CHAR_SPI(WRT+1);
for(LPCNT=0;LPCNT<128; LPCNT++)CHAR_SPI(WRT+2);
for(LPCNT=0;LPCNT<128; LPCNT++)CHAR_SPI(WRT+3);
CHAR_SPI(0xFF); CHAR_SPI(0xFF); // dummy chksum
LPCNT= CHAR_SPI(0xFF);
SendStr(WACK); PRINT_ASCII(LPCNT); PRINT_ASCII((LPCNT & 0x0F));
if ( (LPCNT & 0x0F) != 0x05 )
{
SPIPORT |=CS;
return 1;
}
if( MMC_WAIT_FOR_WRITE_FINISH()==1)
{
SendStr(WNFSH);
SPIPORT |=CS;
return 1;
}
SendStr( MSGW);
/*----------------------------------------------------------------------------------------------------*/
SPIPORT |= CS;
CHAR_SPI(0xFF);
return 0;
}
/* ************************************************************************ *\
Function: 'main()'.
\* ************************************************************************ */
void main(void)
{
init_devices(); // set the baudrate to 19,200 bps using a 14.7456MHz crystal.
SpiInit();
SendStr( MSGF); // Transmit welcome message.
while ( MMC_INIT() != 0)
SendStr( MSG);INSULATOR();
/*------------------------*/
SPCR = 0x50;SPSR |=0x01;
/*------------------------*/
GET_CSD(); INSULATOR();
GET_CID(); INSULATOR();
MMC_WRITE_BLOCK(101,0x45);INSULATOR();;
MMC_READ_BLOCK(101);INSULATOR();
MMC_WRITE_BLOCK(100,0x54);INSULATOR();
MMC_READ_BLOCK(100);INSULATOR();
/*-------------------------------------------------*/
while (1) // Now do this forever.
{
CHAR_SPI(0x55);;
}
}