I have written a code for the init. of SD & SDHC card. The code is pretty much copied from the SD Library of Arduino. I am checking the code on Arduino but my target board is different. So, Can't use SD Library itself.
I have almost everything same but it didn't work with standard SD (256 MB). However it works with SDHC (8GB), it shows the following output:
Output of SDHC ( 8 GB):
Setup Done!
Card Init Called
SD Card in Idle State
IDLE State Achieved! Moving On
CMD8 Successful _ Moving On SD Card Type 2
Arg = 40000000
ACMD41 Successful _ Moving On
Card Init. successful so far
Card Type = 2 SDHC
Output of SD Standard (256 MB):
Setup Done!
Card Init Called
SD Card in Idle State
IDLE State Achieved! Moving On
CMD8 Successful _ Moving On SD Card Type 1
Arg = 0
SD Card Time Out: ACMD41 CMD
Response = 5
Card Init. Failed
And here is the code:
// Processor Clock = 16 MHz
#define NOP __asm__ __volatile__ ("nop\n\t")
#include <SPI.h>
// Comment out following 4 lines for Real SPI or vice versa
/*
const int CS = 3;
const int MSI = 4;
const int MSO = 5;
const int SLK = 6;
*/
unsigned int SDTimeOut = 100;
volatile boolean SDCardType1 = false;
volatile boolean SDCardType2 = false;
volatile boolean SDCardSDHC = false;
// Comment the following two lines for Fake SPI or vice versa
volatile int CS = SS;
volatile int MSI = MOSI;
void setup (void)
{
// Uncomment following 4 lines for Fake SPI
/*pinMode(CS,OUTPUT);
pinMode(MSI,OUTPUT); // MOSI
pinMode(MSO,INPUT); // MISO
pinMode(SLK, OUTPUT); */
pinMode(13,OUTPUT); // LED
Serial.begin(9600);
pinMode(CS, OUTPUT);
SPI.begin (); // Default: Master, MSB Ist, Low to High Transition
Serial.println("Setup Done! Bit Bang SPI");
// Default SPI Clock: 4 MHz
// SPI.setClockDivider(SPI_CLOCK_DIV8);
}
void loop (void)
{
boolean Status;
Status = CardInit();
if (Status)
{
Serial.println("Card Init. successful so far");
if (SDCardType1) Serial.print("Card Type = 1");
if (SDCardType2) Serial.print("Card Type = 2");
if (SDCardSDHC) Serial.println(" SDHC");
}
else
Serial.println("Card Init. Failed");
while(1); // Stay Here
}
// Real SPI Send
void SP_Send(byte data)
{
SPI.transfer(data);
}
// Fake SPI Send
/*
void SP_Send(byte data)
{
byte mask = 0x80;
digitalWrite(13,!digitalRead(13));
for (int i=0; i < 8; i++)
{
digitalWrite(SLK,LOW);
NOP;
//delay(10);
if (data & mask)
digitalWrite(MSI,HIGH);
else
digitalWrite(MSI,LOW);
NOP;NOP;NOP;NOP;
digitalWrite(SLK,HIGH);
NOP;
//delay(10);
mask = mask >> 1;
}
}*/
// Real SPI Read
byte SP_Read(void)
{
SPI.transfer(0xff);
return SPDR;
}
// Fake SPI Read
/*
byte SP_Read(void)
{
byte response = 0;
for (int i=0;i<8;i++)
{
response <<= 1;
digitalWrite(SLK,LOW); // set Clock bit
delay(10); // SPI Delay/2
if (digitalRead(MSO)) // Scan the input pin
response |= 1;
delay(10); // SPI Delay/2
digitalWrite(SLK,HIGH);// clear the Clock bit
}
return response;
}
*/
byte CardCommand(byte cmd, unsigned long arg)
{
byte response, retry =0;
digitalWrite(CS,LOW); // Card Select Low
SP_Send(cmd | 0x40); // Send command 1 byte _ first two bits must be (01)
for (int i=24; i>=0; i-=8) SP_Send(arg >> i); // Send Command Argument; 4 btyes
// Send CRC _ 1 Byte _ CRC is ignored in all other commands except CMD0 & CMD 8
// Last bit of CRC is always 1 _ the Stop Bit
byte crc = 0xFF;
if (cmd == 0x00) crc = 0x95; // crc for (CMD0 = 0x00)
if (cmd == 0x08) crc = 0x87; // crc for (CMD8 = 0x80)
SP_Send(crc);
// digitalWrite(SS,HIGH);
// Wait a little for the SD Card Response
while ((response = SP_Read()) == 0xff)
{
if (retry ++ > 0xfe) break;
}
// digitalWrite (CS,HIGH);
return response;
}
boolean CardInit()
{
byte InitStatus, retry = 0;
unsigned long arg;
Serial.println("Card Init Called");
// Must supply atleast 74 pulses, with CS pin High
digitalWrite(CS,HIGH);
digitalWrite(MSI,HIGH);
for (int i=0;i<10;i++) SP_Send(0xFF);
// Pull CS pin LOW (Active_Low) to enter the SPI_Mode
digitalWrite(CS,LOW);
// SD Card must reboot for SPI to start working
// Send IDLE Command (cmd = 0x00, arg = 0x00 , crc = 0x95) to reset the SD Card.
do
{
InitStatus = CardCommand(0x00,0);
if (retry++ > SDTimeOut)
{
Serial.println("SD Card not Initialized _ Time OUT!");
break;
}
}while(InitStatus != 0x01); // IDLE State Acknowlegement _ R1 response Token for IDLE state command with LSB bit (Idle State) set.
if (InitStatus == 0x01)
{
Serial.println("SD Card in Idle State");
// return true;
}
else
{
Serial.println("SD card idle state Error");
Serial.print(InitStatus);
return false;
}
Serial. println("IDLE State Achieved! Moving On");
InitStatus = 0; retry = 0;
// Check SD Card Type
if(CardCommand(0x08,0x1AA) & 0x04) // CMD8 = 0x08
{
SDCardType1 = true;
// return true;
}
else
{
for (int i=0;i < 4; i++) InitStatus = SP_Read(); // Only needs last byte of r7 response
if (InitStatus != 0xAA)
{
Serial.println("SD Card Error: CMD8 Failed ");
Serial.print("Response = ");
Serial.println(InitStatus);
return false;
}
SDCardType2 = true;
}
Serial.print("CMD8 Successful _ Moving On ");
if (SDCardType1){Serial.println("SD Card Type 1");}
if (SDCardType2){Serial.println("SD Card Type 2");}
arg = SDCardType2 ? 0x40000000 : 0;
Serial.print("Arg = ");
Serial.println(arg,HEX);
InitStatus = 1; retry = 0;
do
{
InitStatus = CardCommand(0x37,0); // CMD55 = 0x37 must be sent before any ACMD command
//if (InitStatus & 0x04) {Serial.println("Illegal Command CMD55");}
InitStatus = CardCommand(0x29,arg); // ACMD41 = 0x29
if (retry++ > 0xfe)
{
Serial.println("SD Card Time Out: ACMD41 CMD ");
Serial.print("Response = ");
Serial.println(InitStatus);
return false;
}
}while((InitStatus != 0x00) /*|| (InitStatus & 0x04)==1*/);
if (InitStatus == 0x00) Serial.println("ACMD41 Successful _ Moving On");
/*
retry = 0;
if (InitStatus & 0x04)
{
Serial.println("MMC Card detected");
do
{
InitStatus = CardCommand(1,0);
Serial.println("Sending CMD1");
if (retry++ > 0xFE)
{
Serial.println("SD1 Card TimeOut");
return false;
}
}while(InitStatus != 0x00);
if (InitStatus == 0x00)
{
Serial.println("SD1 Card Initialized!");}
else Serial.println("SD1 Card Init Failed");
}
*/
InitStatus = 0; retry = 0;
if (SDCardType2)
{
if (CardCommand(0x3A,0)) // CMD58
{
Serial.println("SD Card Error: CMD58");
return false;
}
if ((InitStatus = SP_Read() & 0xC0) == 0xC0) SDCardSDHC = true;
for (int i = 0;i < 3; i++) SP_Read();
}
digitalWrite(CS,HIGH);
return true;
}