114 lines
2.6 KiB
Arduino
114 lines
2.6 KiB
Arduino
|
/**
|
||
|
* SPI SD-Card test sketch
|
||
|
* Reads the first 128 bytes from cf and prints it out as ascii characters in serial monitor at 9200 baud
|
||
|
*
|
||
|
* Implementation of the specification at http://elm-chan.org/docs/mmc/mmc_e.html
|
||
|
*/
|
||
|
|
||
|
#define CS 5 // aka CAT3
|
||
|
#define MOSI 4 // aka DI or CMD
|
||
|
#define SCK 3 // aka CAT3
|
||
|
#define MISO 2 // aka DAT0
|
||
|
|
||
|
void setup() {
|
||
|
pinMode(CS, OUTPUT);
|
||
|
pinMode(MOSI, OUTPUT);
|
||
|
pinMode(SCK, OUTPUT);
|
||
|
pinMode(MISO, INPUT);
|
||
|
|
||
|
Serial.begin(9600);
|
||
|
|
||
|
/***** Init sequence *******/
|
||
|
|
||
|
// Wait 1ms
|
||
|
delay(1);
|
||
|
|
||
|
Serial.println("Init card...");
|
||
|
|
||
|
|
||
|
// >= 75 clocks with CS and DI high
|
||
|
digitalWrite(CS, HIGH);
|
||
|
digitalWrite(MOSI, HIGH);
|
||
|
for (byte i=0; i<80; i++) {
|
||
|
clk();
|
||
|
}
|
||
|
|
||
|
// CMD0 with CS low (Software reset). Means "Leave native mode and enter SPI mode"
|
||
|
digitalWrite(CS, LOW);
|
||
|
sendCommand(B01000000); // First two bits are always 01. Command is 0 (000000).
|
||
|
byte resp = receiveResponse();
|
||
|
Serial.println("Card response:");
|
||
|
Serial.println(resp, HEX);
|
||
|
digitalWrite(CS, HIGH);
|
||
|
|
||
|
}
|
||
|
|
||
|
void loop() {}
|
||
|
|
||
|
/**
|
||
|
* Sends a clock cycle
|
||
|
*/
|
||
|
void clk() {
|
||
|
digitalWrite(SCK, HIGH);
|
||
|
//delayMicroseconds(1);
|
||
|
digitalWrite(SCK, LOW);
|
||
|
//delayMicroseconds(1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sends a command to card.
|
||
|
* The sent CRC field is valid for the CMD0 message.
|
||
|
* This is ok, since the CRC field will not be checked in SPI mode.
|
||
|
* @param index: the command index byte. First two bytes are the sync bytes "01".
|
||
|
*/
|
||
|
void sendCommand(byte index) {
|
||
|
// Send command index (2+6=8 bits)
|
||
|
sendByte(index);
|
||
|
// Send argument (32 bit)
|
||
|
for(byte i=0; i<4; i++) {
|
||
|
sendByte(0);
|
||
|
}
|
||
|
// Send CRC with final stop bit (7+1=8 bits)
|
||
|
sendByte(B10010101); // We send always the CMD0 CRC, because is not checked in SPI mode
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sends a byte to the card. The two MSB must be 01 as per specification.
|
||
|
* Byte is sent MSB first.
|
||
|
*/
|
||
|
void sendByte(byte b) {
|
||
|
for (byte i=0; i<8; i++) {
|
||
|
// If last bit is 1 set MOSI HIGH, else LOW
|
||
|
digitalWrite(MOSI, (b & B10000000) == B10000000 ? HIGH : LOW);
|
||
|
clk();
|
||
|
// Shift byte to have, in the next cycle, the next bit in last position
|
||
|
b = b << 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Receives the response from card
|
||
|
* MSB first.
|
||
|
*/
|
||
|
byte receiveResponse() {
|
||
|
digitalWrite(CS, LOW);
|
||
|
digitalWrite(MOSI, HIGH);
|
||
|
|
||
|
// continuously toggle the SD CLK signal and observe the MISO line for data:
|
||
|
// message response starts with 0
|
||
|
while (digitalRead(MISO)) {
|
||
|
clk();
|
||
|
} // Wait for first 0
|
||
|
|
||
|
byte resp = 0;
|
||
|
// Read 8 bits
|
||
|
for (byte i=0; i<8; i++) {
|
||
|
if (digitalRead(MISO)) {
|
||
|
resp = resp | B00000001;
|
||
|
}
|
||
|
resp = resp << 1;
|
||
|
clk();
|
||
|
}
|
||
|
|
||
|
}
|