Upload
diogo-oliveira
View
213
Download
1
Tags:
Embed Size (px)
DESCRIPTION
eletronica
Citation preview
MINIPROJECTDOCUMENTATIONON
SDCARDINTERFACEUSINGSPI
BATCH:20072011
By
RAJKUMARPEDDI(07241A0488)
DEPARTMENTOFELECTRONICSANDCOMMUNICATIONENGINEERING
GOKARAJURANGARAJUINSTITUTEOFENGINEERINGANDTECHNOLOGY
(AffiliatedtoJawaharlalNehruTechnologicalUniversity)HYDERABAD500072
ABSTRACT:
Secure Digital (SD) cards are removable flash-based storage devices that are gaining in popularity in small consumer devices such as digital cameras, PDAs, and potable music devices. Their small size, relative simplicity, low power consumption, and low cost make them an ideal solution for many applications.
The diagram of an SD card is shown below
1. INTRODUCTION:
1.1 AIM OF THE PROJECT: To interface SD Card using Serial Peripheral Interface(SPI) protocol with the help of ATmega8515 microcontroller. i.e., To erase,write and read the data from SD Card.
1.2 BLOCKDIAGRAM
1.3 RESOURCES:
The SD CARD interface uses the following resources:
SD CARD adapter AVR Microcontroller(ATMEGA 8515) Resistive Network Power Supply unit RS232 Serial Communication.
In the above resources RS232 Serial Communication and Atmega8515 are placed on GRIET dual board remaining sources are placed outside of the board and the connections are given with cables
PORTB upper nibble 4,5,6,7 pins used as control lines for SD card.
PORTB connected to LEDs.
PORTC used for switches.
PORTD lower nibble 0,1 pins used for Serial Communication
2. ABOUT THE RESOURCES:
2.1 SD CARD ADAPTER: SD card adapter is used to connect the pins of SD card to microcontroller. It is soldered on a general purpose pcb.
2.2 AVR Microcontroller(ATMEGA 8515) ATmega8515
SPI allows high-speed synchronous data transfer between the Atmega8515 and peripheral devices or between several AVR devices. The Atmega8515 SPI includes the following features:-
Full Duplex,3-wire Synchronous Data Transfer Master or slave operation LSB First or MSB First Data Transfer Seven Programmable Bit Rates End of Transmission Interrupt Flag Write Collision Flag Protection Wake-up from Idle Mode Double Speed (CK/2) Master SPI mode
2.3 SPI PROTOCOL
The various registers available in SPI mode are as follows:-
SPI Control Register SPCR:
Bit 7 SPIE: SPI Interrupt Enable This bit causes the SPI interrupt to be executed if SPIF bit in the SPSR register is set and if the Global Interrupt Enable bit in SREG is set.
Bit 6 SPE: SPI Enable When the SPE bit is written to one, the SPI is enabled. This bit must be set to enable any SPI operations.
Bit 5 DORD: Data Order When the DORD bit is written to one, the LSB of the data word is transmitted first. When the DORD bit is written to zero, the MSB of the data word is transmitted first.
Bit 4 MSTR: Master/Slave Select This bit selects Master SPI mode when written to one, and Slave SPI mode when written Logic zero. If SS is configured as an input and is driven low while MSTR is set, MSTR will be cleared, and SPIF in SPSR will become set. The user will then have to set MSTR to re-enable SPI Master mode.
Bit 3 CPOL: Clock Polarity When this bit is written to one, SCK is high when idle. When CPOL is written to zero, SCK is low when idle. The CPOL functionality is summarized below:
Bit 2 CPHA: Clock Phase The settings of the Clock Phase bit (CPHA) determine if data is sampled on the
leading (first) or trailing (last) edge of SCK. The CPHA functionality is summarized below:
Bits 1,0 SPR1,SPR0: SPI Clock Rate Select 1 and 0 These two bits control the SCK rate of the device configured as a master. SPR1 and SPR0 have no effect on the Slave. The relationship between SCK and the Oscillator Clock frequency fosc is shown in the following table:
SPI Status Register SPSR
Bit 7 SPIF: SPI Interrupt Flag
When a serial transfer is complete, the SPIF flag is set. An interrupt is generated if SPIE in SPCR is set and global interrupts are enabled. If SS is an input and is driven low when the SPI is in Master mode, this will also set the SPIF flag. SPIF is cleared by hardware when executing the corresponding interrupt handling vector .Alternatively, the SPIF bit is cleared by first reading the SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR).
Bit 6 WCOL: Write Collision Flag The WCOL bit is set if the SPI Data Register (SPDR) is written during a data transfer. The WCOL bit (and the SPIF bit) are cleared by first reading the SPI Status Register with WCOL set, and then accessing the SPI Data Register.
Bits 5 to 1 Res: Reserved Bits These bits are reserved bits in the ATmega8515 and will always read as zero.
Bit 0 SPI2X: Double SPI Speed Bit When this bit is written logic one the SPI speed (SCK Frequency) will be doubled when the SPI is in Master mode. This means that the minimum SCK period will be two CPU clock periods. When the SPI is configured as Slave, the SPI is only guaranteed to work at fosc/4 or lower. The SPI interface on the ATmega8515 is also used for program memory and EEPROM downloading or uploading.
SPI Data Register SPDR
The SPI Data Register is a read/write register used for data transfer between the Register File and the SPI Shift Register. Writing to the register initiates data transmission. Reading the register causes the Shift Register Receive buffer to be read.
2.4 RESISTIVE NETWORK The operating voltage of SD card is 2.6v to 3.3v. But the voltage obtained from microcontroller is 5v. If this voltage is given directly to the SD card, it get damaged. To avoid this, we are using level translator cicruit i.e resistive network.
2.5 POWER SUPPLY TO SD CARD
SD card needs supply voltage in the range 2.6v to 3.3v.when the supply voltage given from resistive network when switching on the power supply due to loading effect this voltage falling to 0.6v.To avoid this we are giving the supply voltage seperately with power supply network.
we are using LM317 regulator
3 SPI PROTOCOL: The pindiagram of an SD card is shown below.
The table below lists the pin assignments for the SD Card.
The SD Card protocol described herein is the SPI mode of the SD Card Protocol. The SD protocol is a simple command-response protocol. All commands are initiated by the master. The SD card responds to the command with a response frame and then, depending on the command, may be followed by a data token indicating the beginning of a bulk data transfer or an error condition. Command Format
The SD card responds to each command frame with a response. Every command has an expected response type. The type of response used for a particular command depends only
on the command number, not on the content of the frame. Three response types are defined for SPI mode: R1, R2, and R3.
Bulk data transfers provide a mechanism to efficiently transfer large amounts of data to and from the SD Card. When a bulk data command is issued to the card, the card responds normally with one of the three standard response types. Then the bulk transfer starts with a data token, followed by the bulk data itself, and completes with a 16-bit CRC .
3.1 CARD INITIALIZATION:
Card initialization starts by setting the SPI clock to 400kHz . Next, at least 74 clocks must be issued by the master before any attempt is made to
communicate with the card
Next, the card is reset by issuing the command CMD0 while holding the SS pin low. This both resets the card and instructs it to enter SPI mode
The CRC byte for a CMD0 command with a zero argument is a constant 0x95 . Next, the command CMD58 is used to determine if the card supports the processor's
operating voltage. CMD58 returns a bitfield containing the allowed operating voltage ranges, typically
between 2.7V and 3.6V.. Finally, the SPI clock is set to the maximum rate allowed. 3.2 BLOCK READ:
Cmd 17 is block read command The block read command is a bulk data command. The command response is followed by
a delay, then followed by a start of block token, and then followed by the actual block itself.
3.3 BLOCK WRITE:
Cmd 24 is write block command After receiving the response for CMD24 A data token 0xFE is sent then block of data sent
PROGRAM:
/*microcontroller : atmega 8515
xtal: 8 Mhz
spi port: PORTB
ss bar -> PB.4; mosi ->PB5; miso -> PB6; sck -> PB.7
baud rate: 19200*/
#include
#include
#include
#define sbi(PORT,BIT) PORT |= (1
#define SEND_STATUS 13
#define SET_BLOCK_LEN 16
#define READ_SINGLE_BLOCK 17
#define WRITE_SINGLE_BLOCK 24
#define ERASE_BLOCK_START_ADDR 32
#define ERASE_BLOCK_END_ADDR 33
#define ERASE_SELECTED_BLOCKS 38
#define SD_SEND_OP_COND 41 //ACMD
#define APP_CMD 55
#define READ_OCR 58
#define CRC_ON_OFF 59
#define ON 1
#define OFF 0
unsigned char SD_init(void);
unsigned char SD_sendCommand(unsigned char cmd, unsigned long arg);
unsigned char SD_readSingleBlock(unsigned long startBlock);
unsigned char SD_writeSingleBlock(unsigned long startBlock);
unsigned char SD_erase (unsigned long startBlock, unsigned long totalBlocks);
unsigned char SD_sendCommand1(unsigned char cmd, unsigned long arg);
unsigned char SPI_transmit(unsigned char data);
void uart0_init(void);
unsigned char receiveByte(void);
void transmitByte(unsigned char);
void transmitString_F(char*);
void transmitString(unsigned char*);
void spi_init(void);
volatile unsigned long startBlock, totalBlocks;
volatile unsigned char SDHC_flag, cardType, buffer[256];
int main(void)
{
unsigned char error, data;
unsigned int i;
start:
_delay_ms(100); //delay for VCC stabilization
// port init
DDRB = 0XBF;// miso i/p, other o/p
sbi(PORTB,6);//internal pull up for miso on
//spi init spe en, master, sck fosc/ 32
// SPCR = 0X52;
spi_init();
uart0_init();
TX_NEWLINE;
TX_NEWLINE;
transmitString_F (PSTR("****************************************************"));
TX_NEWLINE;
transmitString_F (PSTR(" G.R.I.E.T 's microSD Card Testing.. "));
TX_NEWLINE;
transmitString_F (PSTR("****************************************************"));
TX_NEWLINE;
cardType = 0;
for (i=0; i
case 3:transmitString_F(PSTR("Standard Capacity Card (Ver 2.x) Detected!"));
break;
default:transmitString_F(PSTR("Unknown SD Card Detected!"));
break;
}
SPCR= 0X50; //SPI_HIGH_SPEED; //SCK - 4 MHz
SPSR = 0x01; // fosc /2
_delay_ms(1); //some delay
//get starting block address
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("Enter the Block number (0000-9999):"));
data = receiveByte(); transmitByte(data);
startBlock = (data & 0x0f) * 1000;
data = receiveByte(); transmitByte(data);
startBlock += (data & 0x0f) * 100;
data = receiveByte(); transmitByte(data);
startBlock += (data & 0x0f) * 10;
data = receiveByte(); transmitByte(data);
startBlock += (data & 0x0f);
TX_NEWLINE;
totalBlocks = 1;
//get total number of blocks for erase
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("How many blocks? (000-999):"));
data = receiveByte(); transmitByte(data);
totalBlocks = (data & 0x0f) * 100;
data = receiveByte(); transmitByte(data);
totalBlocks += (data & 0x0f) * 10;
data = receiveByte(); transmitByte(data);
totalBlocks += (data & 0x0f);
TX_NEWLINE;
//error = SD_erase (block, totalBlocks);
error = SD_erase (startBlock, totalBlocks);
TX_NEWLINE;
if(error)
transmitString_F(PSTR("Erase failed.."));
else
transmitString_F(PSTR("Erased!"));
//read single block
error = SD_readSingleBlock (startBlock);
TX_NEWLINE;
if(error)
{}
else
{
for(i=0;i
buffer[i++] = data;
if(data == 0x0d)
{
transmitByte(0x0a);
buffer[i++] = 0x0a;
}
if(i == 256) break;//by vhr
}while (data != '~');
//only first 256 bytes were filled
error = SD_writeSingleBlock (startBlock);
TX_NEWLINE;
TX_NEWLINE;
if(error)
{
transmitString_F(PSTR("Write failed.."));
transmitByte(error);//vhr
}//vhr
else
transmitString_F(PSTR("Write successful!"));
//read single block
error = SD_readSingleBlock (startBlock);
TX_NEWLINE;
if(error)
transmitString_F(PSTR("Read failed.."));
else
{
for(i=0;i
{
SPCR = 0x52; //setup SPI: Master mode, MSB first, SCK phase low, SCK idle low
SPSR = 0x00;
}
unsigned char SPI_transmit(unsigned char data)
{
// Start transmission
SPDR = data;
// Wait for transmission complete
while(!(SPSR & (1
return data;
}
// ***********************************************************
//sd card routines
// **********************************************************
//******************************************************************
//Function : to initialize the SD/SDHC card in SPI mode
//Arguments : none
//return : unsigned char; will be 0 if no error,
// otherwise the response byte will be sent
//******************************************************************
unsigned char SD_init(void)
{
unsigned char i, response, SD_version;
unsigned int retry=0 ;
SD_CS_DEASSERT;//by vhr
for(i=0;i
response = SD_sendCommand(GO_IDLE_STATE, 0); //send 'reset & go idle' command
retry++;
if(retry>0x20)
return 1; //time out, card not detected
} while(response != 0x01);
SD_CS_DEASSERT;
SPI_transmit (0xff);
SPI_transmit (0xff);
transmitString_F(PSTR("Idle OK"));
retry = 0;
SD_version = 2; //default set to SD compliance with ver2.x;
//this may change after checking the next command
do
{
response = SD_sendCommand(SEND_IF_COND,0x000001AA); //Check power supply status, mendatory for SDHC card
retry++;
if(retry>0xfe)
{
TX_NEWLINE;
SD_version = 1;
cardType = 1;
break;
} //time out
}while(response != 0x01);
retry = 0;
do
{
response = SD_sendCommand(APP_CMD,0); //CMD55, must be sent before sending any ACMD command
response = SD_sendCommand(SD_SEND_OP_COND,0x40000000); //ACMD41
retry++;
if(retry>0xfe)
{
TX_NEWLINE;
return 2; //time out, card initialization failed
}
}while(response != 0x00);
retry = 0;
SDHC_flag = 0;
if (SD_version == 2)
{
do
{
response = SD_sendCommand(READ_OCR,0);
retry++;
if(retry>0xfe)
{
TX_NEWLINE;
cardType = 0;
break;
} //time out
}while(response != 0x00);
if(SDHC_flag == 1)
cardType = 2;
else
cardType = 3;
}
//SD_sendCommand(CRC_ON_OFF, OFF); //disable CRC; deafault - CRC disabled in SPI mode
//SD_sendCommand(SET_BLOCK_LEN, 512); //set block size to 512; default size is 512
return 0; //successful return
}
//******************************************************************
//Function : to send a command to SD card
//Arguments : unsigned char (8-bit command value)
// & unsigned long (32-bit command argument)
//return : unsigned char; response byte
//******************************************************************
unsigned char SD_sendCommand(unsigned char cmd, unsigned long arg)
{
unsigned char response, retry=0, status;
//SD card accepts byte address while SDHC accepts block address in multiples of 512
//so, if it's SD card we need to convert block address into corresponding byte address by
//multipying it with 512. which is equivalent to shifting it left 9 times
//following 'if' loop does that
if(SDHC_flag == 0)
if(cmd == READ_SINGLE_BLOCK ||
cmd == WRITE_SINGLE_BLOCK ||
cmd == ERASE_BLOCK_START_ADDR||
cmd == ERASE_BLOCK_END_ADDR )
{
arg = arg >24);
SPI_transmit(arg>>16);
SPI_transmit(arg>>8);
SPI_transmit(arg);
if(cmd == SEND_IF_COND) //it is compulsory to send correct CRC for CMD8 (CRC=0x87) & CMD0 (CRC=0x95)
SPI_transmit(0x87); //for remaining commands, CRC is ignored in SPI mode
else
SPI_transmit(0x95);
while((response = SPI_receive()) == 0xff) //wait response
if(retry++ > 0xfe) break; //time out error
if(response == 0x00 && cmd == 58) //checking response of CMD58
{
status = SPI_receive() & 0x40; //first byte of the OCR register (bit 31:24)
if(status == 0x40)
SDHC_flag = 1; //we need it to verify SDHC card
else
SDHC_flag = 0;
SPI_receive(); //remaining 3 bytes of the OCR register are ignored here
SPI_receive(); //one can use these bytes to check power supply limits of SD
SPI_receive();
}
SPI_receive(); //extra 8 CLK
SD_CS_DEASSERT;
return response; //return state
}
//*****************************************************************
//Function : to erase specified no. of blocks of SD card
//Arguments : none
//return : unsigned char; will be 0 if no error,
// otherwise the response byte will be sent
//*****************************************************************
unsigned char SD_erase (unsigned long startBlock, unsigned long totalBlocks)
{
unsigned char response;
response = SD_sendCommand(ERASE_BLOCK_START_ADDR, startBlock); //send starting block address
if(response != 0x00) //check for SD status: 0x00 - OK (No flags set)
return response;
response = SD_sendCommand(ERASE_BLOCK_END_ADDR,(startBlock + totalBlocks - 1)); //send end block address
if(response != 0x00)
return response;
response = SD_sendCommand(ERASE_SELECTED_BLOCKS, 0); //erase all selected blocks
if(response != 0x00)
return response;
return 0; //normal return
}
//******************************************************************
//Function : to read a single block from SD card
//Arguments : none
//return : unsigned char; will be 0 if no error,
// otherwise the response byte will be sent
//******************************************************************
unsigned char SD_readSingleBlock(unsigned long startBlock)
{
unsigned char response;
unsigned int i,j, retry=0;
response = SD_sendCommand(READ_SINGLE_BLOCK, startBlock); //read a Block command
if(response != 0x00)
return response; //check for SD status: 0x00 - OK (No flags set)
SD_CS_ASSERT;
retry = 0;
while(SPI_receive() != 0xfe) //wait for start block token 0xfe (0x11111110)
if(retry++ > 0xfffe)
{
SD_CS_DEASSERT; return 1;
} //return if time-out
for(i=0; i
}
SPI_receive(); //receive incoming CRC (16-bit), CRC is ignored here
SPI_receive();
SPI_receive(); //extra 8 clock pulses
SD_CS_DEASSERT;
return 0;
}
//******************************************************************
//Function : to write to a single block of SD card
//Arguments : none
//return : unsigned char; will be 0 if no error,
// otherwise the response byte will be sent
//******************************************************************
unsigned char SD_writeSingleBlock(unsigned long startBlock)
{
unsigned char response;
unsigned int i, retry=0;
response = SD_sendCommand(WRITE_SINGLE_BLOCK,startBlock ); //write a Block command
if(response != 0x00)
{transmitString_F(PSTR("write cmd not accepted 11"));
return response;} //check for SD status: 0x00 - OK (No flags set)
//cking
SD_CS_ASSERT;
SPI_transmit(0xfe); //Send start block token 0xfe (0x11111110)
for(i=0; i
while(!SPI_receive()) //wait for SD card to complete writing and get idle
if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;}
SD_CS_DEASSERT;
SPI_transmit(0xff); //just spend 8 clock cycle delay before reasserting the CS line
SD_CS_ASSERT; //re-asserting the CS line to verify if card is still busy
while(!SPI_receive()) //wait for SD card to complete writing and get idle
if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;}
SD_CS_DEASSERT;
return 0;
}
// *********************************************************
//UART routines
// *********************************************************
void uart0_init()
{
UBRRL=25; // baud rate 19200 @ 8 mhz
UBRRH =0;
UCSRC= 0X86;//8 bit character length
UCSRB= 0X18;//rx and tx enable
}
//**************************************************
//Function to receive a single byte
//*************************************************
unsigned char receiveByte( void )
{
unsigned char data, status;
while(!(UCSRA & (1
//***************************************************
//Function to transmit a string in Flash
//***************************************************
void transmitString_F(char* string)
{
while (pgm_read_byte(&(*string)))
transmitByte(pgm_read_byte(&(*string++)));
}
//***************************************************
//Function to transmit a string in RAM
//***************************************************
void transmitString(unsigned char* string)
{
while (*string)
transmitByte(*string++);
}
CONCLUSION:
Thus we have successfully interfaced SD card with the ATMega 8515 microcontroller.ie the data in the SD card erased and then written the data and read the data successfully using SPI protocol.
OUTPUT