ATMEGA162 + SD/MMC card interface

Status
Not open for further replies.

NOORPURI

Junior Member level 3
Joined
Jun 29, 2006
Messages
25
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,549
ATMEGA162 + SD/MMC card interface


I have interfaced MMC card with mega8535 successfully. But when i tused ATMEGA162 then i found it read welll prewritten MMC card sector i.e. sector written by ATMEGA8535 easily but when i try to write and readback sectors by using ATMEGA162 then it send back corrupt data.

If any one have any suggestion aur observAtion then guide me,

THANX

MIAN AHMED JEHANZEB ANWER
 

will u kindly send me the complete code for mega8535. i will have a look at it and will let you know accordingly....
 

    NOORPURI

    Points: 2
    Helpful Answer Positive Rating
Dear respondent I am sending u the code of Atmega8535 which i have used successfull to read and write MMC .

/*******************************************************/
#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 = 11; //set baud rate lo @ 11.0592 MHZ
// UBRRL = 15; //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=0xFFF;
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>>8); 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>>8); 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);;
}

}
 

Have you check the clock is right? Remember the MEGA162 has a clock divide by eight inside.
 

    NOORPURI

    Points: 2
    Helpful Answer Positive Rating
i have tried your code and it is working fine.. though i have the following observations

a) when i replaced the two smileys with a value of 16, block read and write were ok.
b) when i replaced these smileys with a value of 8( which i guess is the right value), block read and write did not work.

what is the actual value in your code of these smileys?

waiting for response....
 

    NOORPURI

    Points: 2
    Helpful Answer Positive Rating
I am using Hi-Lo programmer. In it there is configuration menu there u can disbale clk/8.
 

Dear yousafzai,

Please send u r query to me in detail. i didnot under stand ur question .
thanx
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…