Go Down

Topic: SD & SDHC Card Initilazation problem (Read 1 time) previous topic - next topic

w_bwr

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:
Code: [Select]

// 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;   
}
     


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy