SparkFun Forums 

Where electronics enthusiasts find answers.

Discussions on the software and hardware for Atmel's STK standard.
By manojspam
#126886
Hi friends,

I am working on my final year project. I want to interface SD card to Atmega16 microcontroller using SPI protocol. I tried interfacing but it didnt work. I need your help. Its very urgent. Please guide me on how to interface SD card and how to read and write data. I want to write three values(data) to SD card and I want to read them and display on LEDs. Please help me with interfacing and code. Its really urgent.
Thanks a lot.
By MichaelN
#126910
Just a hint - if you want help, you need to provide more information, such as schematics and code that you've already tried, and the errors you're having.

If you're new to embedded electronics, I HIGHLY recommend you just get an Arduino and a suitable shield, since you'll then be working with proven hardware and software.
By manojspam
#127123
Dear friends,
I am working on interfacing SD card with Atmega16. But its not working. I ve done the following work. I dont know where i am going wrong. Please help me.

Hardware Interfacing: I ve interfaced Atmega16 to SD card using SPI protocol with voltage divider circuit.

Software Code: Following is the code which i ve written. I have written 0 to 511 in "buffer" array. I want this to be stored in sd card. Then I would like to read it back from sd card and display on lcd screen(I ve not written lcd module here).


/**********main.c file*************/



#include <avr/io.h>
#include "MMC_SD.h"
#include "MMC_SD.c"
#include<util/delay.h>

main()
{
unsigned int r1=1, capacity=0,i;
unsigned long sector = 10;
unsigned char buffer[512];

SPI_Init();
MMC_SD_Init();

do
{
r1 = MMC_SD_Reset(); // SD card reset and initialisation

}while(r1 != 0);


capacity = MMC_SD_ReadCapacity(); // Capacity of SD card

for( i=0 ; i<512 ; i++ )
buffer = i;



// writing block
// r1 = MMC_SD_WriteSingleBlock(sector, buffer);

r1 = 1;

do
{
r1 = MMC_SD_WriteSingleBlock(sector, buffer);

}while(r1 != 0);


// Reading Block
//r1 = MMC_SD_ReadSingleBlock(sector, buffer);
r1 = 1;
do
{
r1 = MMC_SD_ReadSingleBlock(sector, buffer);

}while(r1 != 0);

}


/***********MMC_SD.c file*********/


#include <avr/io.h>
#include "MMC_SD.h"




//spi low speed
void SPI_Low(void)
{
SPCR = _BV(SPE)|_BV(MSTR)|_BV(SPR1)|_BV(SPR0);
SPSR &= ~_BV(SPI2X);
}

//spi full speed
void SPI_High(void)
{
SPCR = _BV(SPE)|_BV(MSTR);
SPSR |= _BV(SPI2X);
}

//port initialize
void SPI_Init(void)
{
DDR_INI();
SPI_Low();
}

//read and write one byte
uint8 SPI_WriteByte(uint8 val)
{
SPDR = val;
while(!(SPSR & _BV(SPIF)));
return SPDR;
}

/*uint8 SPI_ReadByte(void)
{
SPDR = 0xff;
while(!(SPSR & _BV(SPIF)));
return SPDR;
}*/
//sd card initialize
void MMC_SD_Init(void)
{
SPI_Init();
SPI_CS_Deassert();
}

//sd send command
uint8 MMC_SD_SendCommand(uint8 cmd, uint32 arg)
{
uint8 r1;
uint8 retry=0;

SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);

SPI_CS_Assert();

SPI_WriteByte(cmd | 0x40); //send command
SPI_WriteByte(arg>>24);
SPI_WriteByte(arg>>16);
SPI_WriteByte(arg>>8);
SPI_WriteByte(arg);
SPI_WriteByte(0x95);

while((r1 = SPI_WriteByte(0xff)) == 0xff) //wait response
if(retry++ > 100) break; //time out error

SPI_CS_Deassert();

return r1; //return state
}

//reset sd card (software)
uint8 MMC_SD_Reset(void)
{
uint8 i;
uint8 retry;
uint8 r1=0;
retry = 0;
SPI_Low();

do
{
for(i=0;i<100;i++) SPI_WriteByte(0xff);
r1 = MMC_SD_SendCommand(0, 0); //send idle command
retry++;
if(retry>10) return 1; //time out
} while(r1 != 0x01);


retry = 0;
do
{
r1 = MMC_SD_SendCommand(1, 0); //send active command
retry++;
if(retry>100) return 1; //time out
} while(r1);
SPI_High();
r1 = MMC_SD_SendCommand(59, 0); //disable CRC

r1 = MMC_SD_SendCommand(16, 512); //set sector size to 512
return 0; //normal return
}

//read one sector
uint8 MMC_SD_ReadSingleBlock(uint32 sector, uint8 buffer[512])
{
uint8 r1;
uint16 i;
uint8 retry=0;

do
{
r1 = MMC_SD_SendCommand(17, sector<<9); //read command
retry++;
if(retry>10) return 1; //time out
} while(r1 != 0x00);


SPI_CS_Assert();
//wait to start recieve data
while(SPI_WriteByte(0xff) != 0xfe);//if(retry++ > 50){SPI_CS_Deassert();return 1;}

for(i=0; i<512; i++) //read 512 bytes
{
buffer = SPI_WriteByte(0xff);
}

SPI_WriteByte(0xff);//αcrc
SPI_WriteByte(0xff);

SPI_CS_Deassert();

return 0;
}


//wirite one sector //not used in this application
uint8 MMC_SD_WriteSingleBlock(uint32 sector, uint8 buffer[512])
{
uint8 r1;
uint16 i;
uint8 retry=0;

do
{
r1 = MMC_SD_SendCommand(24, sector<<9); //send command
retry++;
if(retry>10) return 1; //time out
} while(r1 != 0x00);



SPI_CS_Assert();

SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);

SPI_WriteByte(0xfe); //send start byte

for(i=0; i<512; i++) //send 512 bytes data
{
SPI_WriteByte(buffer);
}

SPI_WriteByte(0xff);
SPI_WriteByte(0xff);

r1 = SPI_WriteByte(0xff);

if( (r1&0x1f) != 0x05) //judge if it successful
{
SPI_CS_Deassert();
return r1;
}
//wait no busy
while(!SPI_WriteByte(0xff));//if(retry++ > 50){SPI_CS_Deassert();return 1;}

SPI_CS_Deassert();

return 0;
}

uint32 MMC_SD_ReadCapacity(void)
{
uint8 r1;
uint16 i;
uint16 temp;
uint8 buffer[16];
uint32 Capacity;
//uint8 retry=0;

r1 = MMC_SD_SendCommand(9, 0); //send command //READ CSD
if(r1 != 0x00)
return r1;

SPI_CS_Assert();
while(SPI_WriteByte(0xff) != 0xfe);

for(i=0;i<16;i++)
{
buffer=SPI_WriteByte(0xff);
}

SPI_WriteByte(0xff);
SPI_WriteByte(0xff);

SPI_WriteByte(0xff);

SPI_CS_Deassert();

/*********************************/
// C_SIZE
i = buffer[6]&0x03;
i<<=8;
i += buffer[7];
i<<=2;
i += ((buffer[8]&0xc0)>>6);

/**********************************/
// C_SIZE_MULT

r1 = buffer[9]&0x03;
r1<<=1;
r1 += ((buffer[10]&0x80)>>7);


/**********************************/
// BLOCKNR

r1+=2;

temp = 1;
while(r1)
{
temp*=2;
r1--;
}

Capacity = ((uint32)(i+1))*((uint32)temp);

/////////////////////////
// READ_BL_LEN

i = buffer[5]&0x0f;

/*************************/
//BLOCK_LEN

temp = 1;
while(i)
{
temp*=2;
i--;
}
/************************/



Capacity *= (uint32)temp;
return Capacity;
}



/****************MMC_DC.h File********* ****/


#ifndef __MMC_SD_h__
#define __MMC_SD_h__

#define uint8 unsigned char
#define int8 signed char
#define uint16 unsigned int
#define int16 signed int
#define uint32 unsigned long
#define int32 signed long



#define MMC_SD_PORT PORTB
//#define MMC_SD_CS_PIN 4
#define MMC_SD_CS_PIN 2 //mega8
//#define DDR_INI() DDRB |=_BV(4)|_BV(5)|_BV(7)
#define DDR_INI() DDRB |= _BV(2)|_BV(3)|_BV(5) //mega8
#define SPI_CS_Assert() MMC_SD_PORT &= ~_BV(MMC_SD_CS_PIN)
#define SPI_CS_Deassert() MMC_SD_PORT |= _BV(MMC_SD_CS_PIN)


extern void MMC_SD_Init(void);
extern uint8 MMC_SD_Reset(void);
extern uint8 MMC_SD_ReadSingleBlock(uint32 sector, uint8* buffer);
extern uint8 MMC_SD_WriteSingleBlock(uint32 sector, uint8* buffer);
extern void SPI_High(void);
extern uint8 MMC_SD_SendCommand(uint8 cmd, uint32 arg);
extern uint8 SPI_WriteByte(uint8 val);

extern uint32 MMC_SD_ReadCapacity(void);
#endif