.

INCLUDES RFID interfacing with avr GPS interfacing with avr RF Module interfacing with avr Stepper Motor With AVR

Tuesday, December 20, 2011

Reading and writing SD card using Atmega16

SD card

sdcard

Pin description of an SD card

Pin Name Function (SD Mode) Function (SPI Mode)
1 DAT3/CS Data Line 3 Chip Select/Slave (SS)
2 CMD/DI Command Line Mater Out Slave In (MOSI)
3 VSS1 Ground Ground
4 VDD Supply Voltage Supply Voltage
5 CLK Clock Clock (SCK)
6 VSS2 Ground Ground
7 DAT0/DO Data Line 0 Master In Slave Out (MISO)
8 DAT1/IRQ Data Line 1 Unused or IRQ
9 DAT2/NC Data Line 2 Unused

Important SD card commands

Command Argument Type Response Description
CMD0 None R1 Tell the card to reset and enter its idle state.
CMD16 32-bit Block Length R1 Select the block length.
CMD17 32-bit Block Address R1 Read a single block.
CMD24 32-bit Block Address R1 Write a single block.
CMD55 None
R1
Next command will be application-specific (ACMDXX).
CMD58 None R3 Read OCR (Operating Conditions Register).
ACMD41 None R1 Initialize 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<<SPIF)));
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 < 10; i++) 
SPI_sendchar(0xFF);                // Send 10 * 8 = 80 clock pulses 400 kHz
PORTB &= ~(_BV(CS));                 //enable CS
for(i=0; i < 2; 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 < 50000; 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 < 50000; 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 < 512; i++) {
while(!(SPSR & (1<<SPIF)));
chars[i] = SPDR;
SPDR = SPI_sendchar(0xFF);
}
SPI_sendchar(0xFF);
SPI_sendchar(0xFF);
return 0;
}
Adding all the codes:
#include <avr/io.h>
#include <avr/iom16.h>
#include <avr/interrupt.h>
#define FOSC 6400000
char chars[512];
int main(void) {
ini_SPI();
ini_SD();
sei();
write();
read();
return 0;
}

No comments:

Post a Comment