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