ay-2010-11-doc-07241a0488

39
MINI PROJECT DOCUMENTATION ON SD CARD INTERFACE USING SPI BATCH: 2007‐2011 By RAJKUMAR PEDDI (07241A0488) DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING GOKARAJU RANGARAJU INSTITUTE OF ENGINEERING AND TECHNOLOGY (Affiliated to Jawaharlal Nehru Technological University) HYDERABAD 500 072

Upload: diogo-oliveira

Post on 25-Sep-2015

213 views

Category:

Documents


1 download

DESCRIPTION

eletronica

TRANSCRIPT

  • 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