Problems with Microcontroller Projects? You may face many Problems, but do not worry we are ready to solve your Problems. All you need to do is just leave your Comments. We will assure you that you will find a solution to your project along with future tips. On Request we will Mail you the Codes for Registered Members of this site only, at free service...Follow Me.

Reading and writing SD card using Atmega16


This project explains how to read and write an SD card using an AVR microcontroller.

SD card

sdcard


Pin description of an SD card



PinNameFunction (SD Mode)Function (SPI Mode)
1DAT3/CSData Line 3Chip Select/Slave (SS)
2CMD/DICommand LineMater Out Slave In (MOSI)
3VSS1GroundGround
4VDDSupply VoltageSupply Voltage
5CLKClockClock (SCK)
6VSS2GroundGround
7DAT0/DOData Line 0Master In Slave Out (MISO)
8DAT1/IRQData Line 1Unused or IRQ
9DAT2/NCData Line 2Unused



Important SD card commands


CommandArgumentType ResponseDescription
CMD0NoneR1Tell the card to reset and enter its idle state.
CMD1632-bit Block LengthR1Select the block length.
CMD1732-bit Block AddressR1Read a single block.
CMD2432-bit Block AddressR1Write a single block.
CMD55NoneR1Next command will be application-specific (ACMDXX).
CMD58NoneR3Read OCR (Operating Conditions Register).
ACMD41NoneR1Initialize the card.


Initialize SD card


Initialization begins by setting the SPI control clock signal to 400kHz, which is required for compatibility of most SD and MCC memory cards. Then reset the tab order at CMD0 activated CS input card (CS at level L). CRC byte for the command CMD0 and zero argument command is 0x95. CMD55 followed orders and ACMD41. If after the idle bit in the level L handshake is completed and anticipates that further management framework. Command CMD58 For example, we check whether the card supports the same supply voltage as the MCU, which is typically in the range of 2.7 V to 3.6 V. SPI clock signal to set the maximum allowed value.

Program part


SD card connection to microcontroller


#define DI 6                         // Port B bit 6 (pin7): data in (data from MMC)
#define DT 5                        // Port B bit 5 (pin6): data out (data to MMC)
#define CLK 7                     // Port B bit 7 (pin8): clock
#define CS 4                        // Port B bit 4 (pin5): chip select for MMC


SPI Initialization:


void ini_SPI(void) {
DDRB &= ~(_BV(DI));                     //input
DDRB |= _BV(CLK);                     //outputs
DDRB |= _BV(DT);                     //outputs
DDRB |= _BV(CS);                     //outputs
SPCR |= _BV(SPE);                     //SPI enable
SPCR |= _BV(MSTR);                     //Master SPI mode
SPCR &= ~(_BV(SPR1));                    //fosc/16
SPCR |= _BV(SPR0);                    //fosc/16
SPSR &= ~(_BV(SPI2X));                    //speed is not doubled
PORTB &= ~(_BV(CS));                     //Enable CS pin for the SD card
}



Functions for sending and receiving one byte through SPI:
char SPI_sendchar(char chr) {
char receivedchar = 0;
SPDR = chr;
while(!(SPSR & (1< 
receivedchar = SPDR;
return (receivedchar);
}


Function to send a command frame Command:
char Command(char cmd, uint16_t ArgH, uint16_t ArgL, char crc ) {
SPI_sendchar(0xFF);
SPI_sendchar(cmd);
SPI_sendchar((uint8_t)(ArgH >> 8));
SPI_sendchar((uint8_t)ArgH);
SPI_sendchar((uint8_t)(ArgL >> 8));
SPI_sendchar((uint8_t)ArgL);
SPI_sendchar(crc);
SPI_sendchar(0xFF);
return SPI_sendchar(0xFF);                // Returns the last byte received
}


Initialization card:
void ini_SD(void) {
char i;
PORTB |= _BV(CS);                    //disable CS
for(i=0; i <> 
SPI_sendchar(0xFF);                // Send 10 * 8 = 80 clock pulses 400 kHz
PORTB &= ~(_BV(CS));                 //enable CS
for(i=0; i <> 
SPI_sendchar(0xFF);                // Send 2 * 8 = 16 clock pulses 400 kHz
Command(0x40,0,0,0x95);              // reset
idle_no:
if (Command(0x41,0,0,0xFF) !=0) 
goto idle_no;                        //idle = L?
SPCR &= ~(_BV(SPR0));                //fosc/4
}

Writing to the card:
The function returns 1 if an error occurs else returns 0 if successful
int write(void) { 
int i;
uint8_t wbr;
//Set write mode 512 bytes
if (Command(0x58,0,512,0xFF) !=0) {
//Determine value of the response byte 0 = no errors
return 1;
//return value 1 = error
}
SPI_sendchar(0xFF);
SPI_sendchar(0xFF);
SPI_sendchar(0xFE);
//recommended by posting a terminator sequence [2]
//write data from chars [512] tab
uint16_t ix;
char r1 =  Command(0x58,0,512,0xFF);
for (ix = 0; ix <> 
if (r1 == (char)0x00) break;
r1 = SPI_sendchar(0xFF);
}
if (r1 != (char)0x00) {
return 1;
//return value 1 = error
}
//recommended by the control loop [2]
SPI_sendchar(0xFF);
SPI_sendchar(0xFF);
wbr = SPI_sendchar(0xFF); 
//write block response and testing error
wbr &= 0x1F;     
//zeroing top three indeterminate bits 0b.0001.1111
if (wbr != 0x05) { // 0x05 = 0b.0000.0101
//write error or CRC error 
return 1;
}
while(SPI_sendchar(0xFF) != (char)0xFF);
//wait for the completion of a write operation to the card
return 0;
}


Reading from the card:
The function returns 1 if an error occurs else returns 0 if successful
int read(void) {
int i;
uint16_t ix;
char r1 =  Command(0x51,0,512,0xFF);
for (ix = 0; ix <> 
if (r1 == (char)0x00) break;
r1 = SPI_sendchar(0xFF);
}
if (r1 != (char)0x00) {
return 1;
}
//read from the card will start after the framework
while(SPI_sendchar(0xFF) != (char)0xFE);
for(i=0; i <> 
while(!(SPSR & (1< 
chars[i] = SPDR;
SPDR = SPI_sendchar(0xFF);
}
SPI_sendchar(0xFF);
SPI_sendchar(0xFF);
return 0;
}

Adding all the codes:
#include 
#include 
#include 
#define FOSC 6400000
char chars[512];
int main(void) {
ini_SPI();
ini_SD();
sei();
write();
read();
return 0;
}

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...

Recent Comments

Popular Projects

Give Support

Give Support
Encourage Me through Comments

Microcontroller Projects

Total Pageviews