banner



How To Initialize A Camera Memory Card

Initializing an SD Menu

In this tutorial, we will get through the nuts of initializing an SD carte du jour using an ATmega328P in Serial Peripheral Iterface (SPI) fashion. If you are unfamiliar with SPI, please review my tutorial on the topic here. Although I am using an ATmega328P for this case, the concepts extend to any AVR microcontroller.

Much of the information I am presenting here comes directly from the SD Card Physical Specification, a re-create of which can be found here.

Connections

A simplified schematic is shown beneath for the connections betwixt an ATmega328P and an SD card. Note that the SD card requires 3.3V power, exercise not connect to 5V! Also, I am using PINB2 as the Chip Select. If you lot choose to utilise a dissimilar pin you volition need to modify the lawmaking presented in this tutorial.


Initializing SPI

In order to setup SPI, we need to setup a few things, namely the clock polarity, phase, and rate. Unfortunately, passenger vehicle timing diagrams are not available in the simplified (gratuitous) versions of the SD Concrete Layer specification. However, in this SanDisk SD Carte du jour product manual, a timing diagram is provided for i of their cards, shown below.

As can be seen, the clock idles low and the output is sampled on the leading edge, which corresponds to CPOL = 0 and CPHA = 0. We can assume that this mode of operation should work for other SD Cards.

CPOL and CPHA are default set to 00 in the SPCR (SPI Command Register), and then we practise not need to exercise anything with them in SPI initialization. Although modern SD Cards tin can operate at very high speeds, here we volition gear up SCK to the lowest value for debugging purposes, and increase it later when we have our code working.

To abstract the pins used in our code, it will be helpful to give them functional names. Additionally, all SPI commands to the SD card require our microcontroller to outset assert the Chip Select line, which means pulling it low. When we are done, we volition need to return the Fleck Select to a high state. Such unproblematic commands practise not necessarily warrant a office, only some simple preprocessor macros volition be very helpful.

Hither is our SPI initialization code, every bit well as our send/receive role, and some useful pin definitions and macros.

            // pivot definitions #define DDR_SPI         DDRB #define PORT_SPI        PORTB #define CS              PINB2 #define MOSI            PINB3 #define MISO            PINB4 #ascertain SCK             PINB5  // macros #ascertain CS_ENABLE()     PORT_SPI &= ~(1 << CS) #define CS_DISABLE()    PORT_SPI |= (1 << CS)  void SPI_init() {     // fix CS, MOSI and SCK to output     DDR_SPI |= (1 << CS) | (1 << MOSI) | (i << SCK);      // enable pull upwardly resistor in MISO     DDR_SPI |= (one << MISO);      // enable SPI, set as chief, and clock to fosc/128     SPCR = (1 << SPE) | (one << MSTR) | (1 << SPR1) | (1 << SPR0); }  uint8_t SPI_transfer(uint8_t data) {     // load data into register     SPDR = data;      // Wait for transmission complete     while(!(SPSR & (i << SPIF)));      // render SPDR     return SPDR; }                      

Power Upwardly Sequence

The power up sequence from the concrete spec is shown below.

Note that we need to provide at least 1 msec delay and 74 clock cycles earlier sending commands to an SD Card. Since nosotros get eight clock cycles with each byte, we can send 10 bytes for a full of 80 clock cycles. In the notes of this section, the spec likewise specifies that CS must be held loftier during this flow.

            #include<util/delay.h>  void SD_powerUpSeq() {     // make certain card is deselected     CS_DISABLE();      // give SD card fourth dimension to power up     _delay_ms(1);      // send 80 clock cycles to synchronize     for(uint8_t i = 0; i < 10; i++)         SPI_transfer(0xFF);      // deselect SD card     CS_DISABLE();     SPI_transfer(0xFF); }                      

Sending Commands

Below is the control format for SD carte du jour commands. All commands are 6 bytes long and contain a control index, arguments, and CRC. The command index field is used to tell the SD bill of fare which command you lot are sending. For example, if CMD0 is required, then the 6 $.25 in control index should be set to 000000b. The statement field is used in some commands and is ignored by the SD carte du jour in others. Whenever no arguments are needed, we will fill this field with all zeros. Finally, the Cyclic Redundancy Bank check (CRC) is used to ensure the contents of the command take been correctly received past the SD card. As nosotros will run across, in SPI mode, only a few commands actually crave a right CRC. In the cases where it is not needed, nosotros will set information technology to all zeros.

Here we will write a office to ship commands to an SD card. We volition laissez passer an 8-flake command index, a 32-bit argument, and an 8-bit CRC.

            void SD_command(uint8_t cmd, uint32_t arg, uint8_t crc) {     // transmit control to sd carte     SPI_transfer(cmd|0x40);      // transmit statement     SPI_transfer((uint8_t)(arg >> 24));     SPI_transfer((uint8_t)(arg >> xvi));     SPI_transfer((uint8_t)(arg >> eight));     SPI_transfer((uint8_t)(arg));      // transmit crc     SPI_transfer(crc|0x01); }          

We begin by transmitting the command alphabetize. Note notwithstanding in the command format table, that the control index is only 6 bits long. The 2 nigh significant bits of the control ever set to 01b. If we always pass command indices less than 128 (which we will see is the case), so bit 48 of our 'cmd' argument will always be zero. However, in order to set scrap 47 to 1, we need to bitwise OR our input 'cmd' with 0x40.

                          // transmit command to sd card     SPI_transfer(cmd|0x40);          

Next, we transmit our four byte argument, one byte at a time, past shifting it downwardly 8 bits at a time.

                          // transmit argument     SPI_transfer((uint8_t)(arg >> 24));     SPI_transfer((uint8_t)(arg >> sixteen));     SPI_transfer((uint8_t)(arg >> viii));     SPI_transfer((uint8_t)(arg));          

Finally, we transmit the CRC. Notation that the CRC is only seven bits long, and the final fleck of any command is e'er set up to one. To brand our lives easier, nosotros will bitwise OR the 'crc' argument with 0x01 so the final bit is always 1 and we don't take to worry nearly information technology when supplying arguments to the function.

                          // transmit crc     SPI_transfer(crc|0x01);          

Initialization Flow

The SPI fashion initialization catamenia for an SD card is shown in the diagram below

The beginning stride in the process is to send CMD0. Below is the description of CMD0 from the physical spec.

This command is used a software reset for the SD carte. Its argument is 'stuff bits', which means information technology will exist ignored by the SD card, and the response is of type R1 (more on that later).

SPI manner is a secondary mode of advice for SD cards - they power up in an "SD Bus protocol mode." Cards simply switch to SPI when the Chip Select line is driven low and CMD0 is sent. In SPI mode CRCs are ignored by default, but in SD Bus mode, which we are coming from at startup, they are required. So for the first command we must have a right checksum.

We specify CMD0 simply past setting 'command index' to 0 in our command, and since the argument is but stuff, nosotros volition set it to 0x00000000. Now we demand the CRC that corresponds to these bits. Luckily, the physical spec provides united states this seven fleck value on page 43 - 10010100b. To laissez passer this to our part, we need an 8-bit value. We can put a 0 on the terminate (0x94) or a 1 (0x95) only it does not matter as our function will always the final bit will always be set up to ane earlier nosotros transmit.

            #ascertain CMD0        0 #define CMD0_ARG    0x00000000 #ascertain CMD0_CRC    0x94  // send CMD0 SD_command(CMD0, CMD0_ARG, CMD0_CRC);          

Notation that CMD0 returns a response of format R1. The R1 format is shown below from the physical spec.

Notation that R1 is a single byte, where the offset bit is always 0, and every other bit represents an error condition.

Knowing this, we can write a function to retrieve a single byte response subsequently sending CMD0. Here it is below

            uint8_t SD_readRes1() {     uint8_t i = 0, res1;      // keep polling until actual information received     while((res1 = SPI_transfer(0xFF)) == 0xFF)     {         i++;          // if no information received for 8 bytes, pause         if(i > 8) break;     }      return res1; }                      

Since the MISO line is loftier past default, if the SD card does not reply, we will simply read 0xFF. The SD carte may require some time later our control is sent to process it, so we will keep polling until we receive data. However, the card should respond inside viii cycles. If it has not responded past then we interruption and return the response (which will be 0xFF).

Putting all of this together, the total sequence for sending CMD0, aka GO_IDLE_STATE, is shown beneath

            uint8_t SD_goIdleState() {     // affirm chip select     SPI_transfer(0xFF);     CS_ENABLE();     SPI_transfer(0xFF);      // ship CMD0     SD_command(CMD0, CMD0_ARG, CMD0_CRC);      // read response     uint8_t res1 = SD_readRes1();      // deassert chip select     SPI_transfer(0xFF);     CS_DISABLE();     SPI_transfer(0xFF);      return res1; }                      

Here, we provide 8 clocks before and afterwards pulling CS depression, and another 8 earlier sending the control. This is recommended to ensure the card recognizes the modify in CS. In addition, we provide and extra byte before and after transitioning CS high. These actress bytes are not always necessary but many people have had problems when multiple cards are on the bus.

Putting Information technology All Together

At present information technology is time to put all of this into a program. Below is a principal office using the functions defined previously in this tutorial. Here nosotros merely go through the ability up sequence and command the bill of fare to idle. Download the source code hither

            int main(void) {     // initialize SPI     SPI_init();      // start power upwardly sequence     SD_powerUpSeq();      // command card to idle     SD_goIdleState();      while(1); }          

Using a logic analyzer, here is what nosotros encounter when we run the program (click to go total screen).

We meet that the first byte transmitted is 0x40 (which is CMD0|0x40), our arguments are all 0, and our last byte is 0x95 (CMD0_CRC|0x01). Find that it takes the SD card 8 clock cycles after sending the command to answer. Once it does, it sends 0x01. Checking dorsum to our definition of R1, we see that that ways the card is in idle state (and has no errors), which is exactly what nosotros allowable information technology to practise!

Click here to go onto office 2.

Source: http://www.rjhcoding.com/avrc-sd-interface-1.php

Posted by: carpenterhanch1957.blogspot.com

0 Response to "How To Initialize A Camera Memory Card"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel