SD CARD INTERFACE WITH ATMEGA 168 OR 328 FOR FAT16

HI EVERY ONE

I WANT TO INTERFACE SD CARD WITH ATMEGA168 OR 328...I HAVE GONE THROUGH IN GOOGLE I HAVE'NT GAT AN IDEA OF FAT 16 FILE SYSTEM FIRST I WANT TO KNOW ABOUT FAT16 FILE SYSTEM PLS ANY ONE HELP ME OUT..I WANT A SIMPLE PROGRAM TO READ AND WRITE USING FAT 16 FILE SYSTEM

One tip would be to do something about your caps-lock. The arduino IDE (among other things) is case sensitive.

Good luck,

Jeroen

HMM... ANYONE GOT ANY IDEA? IT APPEARS HE IS SHOUTING AT ME SO I'M NOT GOING TO SAY ANYHTING.

HEY CHECK OUT THIS LINK ITS GREAT KTHX

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1206874649/8

hey ya i am working out the link above u have specified.... i could'nt inisizalise the card thats the error iam getting... iam struck in that for long while pls anyone help me out...

It is a bit hard to help if all the info we have available basically comes down to...

"It doesn't work, help!"

I hope you see our conundrum, we can't help if we don't know what you are doing, what you have and what you want to do. Details will be needed I'm afraid.

sorry for not giving the details…i am working on data logger… i want to store the sensor values in sd card using fat 16 file system this is my aim of ma project…

POROBLEM I AM FACING:
inizilation error

HARDWARE details:
microcontroller:ATMEGA 168
sd card:1GB TRANSCEND (9pins)

#include <Spi.h>
#include <sd-reader_config.h>
#include <sd_raw.h>
#include <sd_raw_config.h>

int print_disk_info();
int sample();
int readDisk();

byte incomingByte;
void printWelcome();
long int address;
byte tempBytes[2];


void setup()
{

  Serial.begin(115200);
  delay(1000);

  printWelcome();
  if(!sd_raw_init())
  {
     Serial.println("MMC/SD initialization failed");
  }
 print_disk_info();
 //sd_raw_init();
}



void loop()
{
    int i;

    if(Serial.available()>0)
    {
         incomingByte=Serial.read();

       switch(incomingByte)
       {
           case 114:
                     readDisk();
                     break;
           case 115:
                     sample();
                     break;
           default:
                     break;
       }
    }
}

int sample()
{
    int i,j;
    int temp;
    byte low;
    byte high;
    byte inByte;

    Serial.println();
    Serial.println();
    Serial.println("Sampling..");
    for(i=0;i<20;i=i+2)
    {
        if(Serial.available()>0)
        {
            inByte=Serial.read();
            if(inByte==113) return 0;
        }
        temp=analogRead(0);
        Serial.print(temp,DEC);
        Serial.print(" ");

        //Convert int to 2 bytes
        low=temp&0xFF;
        high=temp>>8;
       // Serial.print(temp,DEC);
        //Serial.print(low,DEC);
        //Serial.print(high,DEC);

        tempBytes[0]=low;
        tempBytes[1]=high;

        if(!sd_raw_write(i,tempBytes,2))
        {
          Serial.print("Write error");
        }
        //sd_raw_sync();
        delay(1000);

  Serial.println();

    }

    return 1;
}


int readDisk()
{
    byte low;
    byte high;
    byte info[2];
    int i;
    int  result;
    Serial.println();
    for(i=0;i<50;i=i+2)
    {
        sd_raw_read(i,info,2);

        //Serial.print(info[0],DEC);
        //Serial.print(" ");
        //Serial.print(info[1],DEC);
        low=info[0];
        high=info[1];
        result=high<<8;
        //result<<8;
        Serial.print(" ");
        Serial.print(result+low,DEC);
        Serial.print(" ");
    }

}

void printWelcome()
{
    Serial.println("------------------------");
    Serial.println("Data sampling system");
    Serial.println("send r to read disk");
    Serial.println("send s to start sampling");
    Serial.println("send q to stop sampling");
    Serial.println("Ready.....");
    Serial.println("-------------------------");
}


int print_disk_info()
{


    struct sd_raw_info disk_info;
    if(!sd_raw_get_info(&disk_info))
    {
        return 0;
    }


    Serial.println();
    Serial.print("rev:    ");
    Serial.print(disk_info.revision,HEX);
    Serial.println();
    Serial.print("serial: 0x");
    Serial.print(disk_info.serial,HEX);
    Serial.println();
    Serial.print("date:   ");
    Serial.print(disk_info.manufacturing_month,DEC);
    Serial.println();
    Serial.print(disk_info.manufacturing_year,DEC);
    Serial.println();
    Serial.print("size:   ");
    Serial.print(disk_info.capacity,DEC);
    Serial.println();
    Serial.print("copy:   ");
    Serial.print(disk_info.flag_copy,DEC);
    Serial.println();
    Serial.print("wr.pr.: ");
    Serial.print(disk_info.flag_write_protect_temp,DEC);
    Serial.print('/');
    Serial.print(disk_info.flag_write_protect,DEC);
    Serial.println();
    Serial.print("format: ");
    Serial.print(disk_info.format,DEC);
    Serial.println();
    Serial.print("free: ");

    return 1;
}

)

arduino = 5v sdcard = 3.3v

Have you added a logic level shifter in your circuit?

ya MR.orbitalair i have shifted 5v to sd card 3.3v level.... i have formatted ma card to FAT SYSTEM then to card inizilasition error... pls help me out

Hi

I’m trying to read and write data in FAT16 onto a 512 MB Nokia MMC card (that came with an old Nokia N72). The card initialises, and i’m able to read/write data. But i suspect the data is junk, as the data i read is not the same for successive read operations. I’ve modified code from klk64 - http://klk64.com/arduino-spi/

The circuit i’ve used is the top left section of the following schematic - http://www.ladyada.net/media/gpsshield/gpschemv11.png

// ATMega168-specific pins
#define SPIPORT PORTB
#define SPIDDR  DDRB
#define MOSI 3       // Arduino pin 11
#define MISO 4       // Arduino pin 12
#define SCLK 5       // Arduino pin 13
#define CS 1         // Arduino pin 9
#define SS 2         // Arduino pin 10 

#define BLOCKSIZE 512
#define MAX_RETRIES 0xFF  // max value for unsigned byte

#define SPI_TIMEOUT 16000
// you can play with this value, but make sure it is
// within range of your counter datatype

// macros for modifying register variables
#define SB(x,n) (x|=(1<<n))  // set bit
#define CB(x,n) (x&=~(1<<n)) // clear bit
// using SB on a DDR register sets the pin (from the
// argument) to output, CB sets it to input.
// Equivalent to Arduino's pinMode()
// using SB on a PORT register would set the output
// of that pin to high, CB sets it low.
// Equivalent to Arduino's digitalWrite()

byte sector[512];  // data buffer

byte clr;
// dummy variable used to clear some of the SPI registers

byte spi_err;
// SPI timeout flag, must be cleared manually

// one full-duplex cycle (write one byte and read one byte)
byte SPI(volatile char data)
{
  long c=0;
  SPDR = data;
  // start the transmission by loading the output
  // byte into the SPI data register
  // check status register for transfer finished flag
  while (!(SPSR & (1<<SPIF)))
  {
    if (++c==SPI_TIMEOUT)
    {
      spi_err=1;
      break;
    }
  }

  return SPDR;    //return the received byte
}

// Send a MMC/SD command, num is the actual index, not
// ORed with 0x40. arg is all four bytes of the argument
byte CMD(byte num, long arg)
{
  CB(SPIPORT,CS); // assert chip select for the card

  SPI(0xFF); // dummy byte
  SPI(0x40|num);  // command token

  // send argument in little endian form (MSB first)
  SPI(arg>>24);
  SPI(arg>>16);
  SPI(arg>>8);
  SPI(arg);

  SPI(0x95);  // checksum valid for CMD0, not needed
              // thereafter, so we can hardcode this value
SPI(0xFF); // dummy to give card time to process

  return SPI(0xFF); // query return value from card
}

void spi_init(void)
{
  // As Master, all SPI pins go out except MOSI which comes in
  SB(SPIDDR,MOSI);
  SB(SPIDDR,SCLK);
  SB(SPIDDR,CS);
  SB(SPIDDR,SS); 
  CB(SPIDDR,MISO);

  SB(SPIPORT,SS); 
  CB(SPIPORT,CS);  // Activate card

  // spi enabled, master mode, clock @ f/128 for init
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);

  // dummy read registers to clear previous results
  clr=SPSR;
  clr=SPDR;
delay(100);
  // you might choose to end this function with a delay
  // to ensure that the SPI hardware is ready before
  // attempting any SPI transmissions
}
byte mmc_init(void)
{
  byte i;
  // make absolute sure that the SPI clock is under 400MHz
  SB(SPCR,SPR1);
  SB(SPCR,SPR0);  
resend:
  SB(SPIPORT,CS);  // deactivate card for warmup
  SB(SPIPORT,MOSI);
  for(i=0;i<10;i++) SPI(0xFF); // send 80 pulses for a warmup

  CB(SPIPORT,CS);  // reactivate card

  // CMD0 sets card to idle mode, also selects SPI interface  
  int a=CMD(0,0);
   while (CMD(0,0)!=0xFF)
  {
      SPI(0xFF);
  SPI(0xFF);
  SPI(0xFF);
    if (spi_err!=0)
    {
      // a timeout occured, possibly because of no card in the
      // socket, so deselect, wait, and retry from beginning
      spi_err=0;
      SB(SPIPORT,CS);
      Serial.println("SPI TIMEOUT");
      delay(3000);
      goto resend;

    }
  }  

  // ACMD41 (55->41) is the preferred startup sequence
  // for SD cards, try it before trying CMD1
  for (i=0;i<MAX_RETRIES;i++)
  {
    CMD(55,0);
    if (CMD(41,0)!=0) 
    return 1;
 
  } 

  // CMD1 is the startup command for MMC cards
  for (i=0;i<MAX_RETRIES;i++)
  {
    if (CMD(1,0)==0) return 1;
  }  

  //CMD(16,512);  // set the read/write blocklength to 512 bytes

  // sets the SPI clock up to a higher speed.
  // check the datasheet p170 for complete table
  CB(SPCR,SPR1);
  CB(SPCR,SPR0);

  return 0;
}

void setup()
{
  spi_err=0;
  spi_init(); // *should* only need to do this once

  Serial.begin(9600);
  Serial.flush();
  delay(10);

  Serial.print("Ready.\n");
}

byte mmc_write(byte* data, long addr)
{
  byte c;
  short i;
  while(CMD(24,0x00)!=0x00);
  SPI(0xFF); SPI(0xFF); SPI(0xFE); // lead in to actual data
  for (i=0;i<BLOCKSIZE;i++) SPI(data[i]);
  SPI(0xFF); SPI(0xFF);// dummy before response recieved
  SPI(0xFF);
  
  while(c!=0x05)   
{
  c=SPI(0xFF);
};
  c=0x05;
  c&=0x1F; // bit mask for write error codes
  // see http://elm-chan.org/docs/mmc/mmc_e.html
  if (c!=0x05) return 0;
  while (SPI(0xFF)!=0xFF);  // block until write finished
  return 1;
}

byte mmc_read(byte* buf, long addr)
{
  int i;
  byte c;
  byte r1=CMD(17,addr);
  for (i=0;i<1000;i++)     // wait until the data is found
  {
    if (r1==0) break;
    r1 = SPI(0xFF);
  }
  if (r1!=0) return 0;  // timed out
  while (SPI(0xFF)!=0xFE);  // wait for the "data follows" code
  for (i=0;i<512;i++) *(buf++)=SPI(0xFF);
  SPI(0xFF); SPI(0xFF);  // dummy bytes to clear any queues
  return 1;
}

void clr_dbuf()
{
  for(int i=0;i<=512;i++)
  {
    sector[i]=0;
  }
}
void print_sector()
{
  int i,j;
  for (i=0;i<512;i++)
  {
    Serial.print(sector[i],HEX);
    Serial.print(' ');
    if (i%32==0&&i!=0) Serial.print('\n');
  }
}

void loop()
{
    // This uses the Serial library of the Arduino to provide an
    // interactive way of testing the MMC/SD functionality
    // If the return code isn't enough to help you debug, you'll
    // probably want to add extra print statements thoughout the
    // critical functions - I removed mine for style purposes

    while (Serial.available()>0)
    {
      int a;
      switch (Serial.read())
      {
        case 'i':
          Serial.print("mmc_init: ");
          Serial.println(mmc_init(),HEX);
          break;
        case 'w':  Serial.println("mmc_write: ");
        while(!Serial.available());
          switch(Serial.read())
          {
            case '1':a=1;break;
          case '2':a=2;break;
          case '3':a=3;break;
          case '4':a=4;break;
          case '5':a=5;break;
          case '6':a=6;break;
          case '7':a=7;break;
          case '8':a=8;break;
          case '9':a=9;break;
          case '10':a=10;break;
          default:a=0;
          }
        Serial.print("Entered Address:");
          Serial.println(a);
          Serial.println(mmc_write(sector,a),HEX);
          break;
        case 'r':         Serial.println("mmc_read: ");
        while(!Serial.available());
          switch(Serial.read())
          {
            case '1':a=1;break;
          case '2':a=2;break;
          case '3':a=3;break;
          case '4':a=4;break;
          case '5':a=5;break;
          case '6':a=6;break;
          case '7':a=7;break;
          case '8':a=8;break;
          case '9':a=9;break;
          case '10':a=10;break;
          default:a=0;
          }
        Serial.print("Entered Address:");
          Serial.println(a);       
          Serial.println(mmc_read(sector,a),HEX);
          break;
        case 's':
          Serial.println("spi_init");
          break;
        case 'p':
          print_sector();
          break;
        case 'c':
        Serial.println("Cleared data buffer");
          clr_dbuf();
          break;
        case ' ':
          delay(1000);
          break;
      }
      delay(1);
    }
    delay(100);
}

I’ll add the output in the next post.

Also, i’m not able to use a 1Gb transcend SD card with this code (it initialises, but read/write operations fail altogether).
A 2Gb transcend SD card does not even initialise… Can someone clarify this as well?

Forgot to mention a small change in the circuit, i added pull up resistors to DAT pins (pins 8 & 9 on my card) which i didn't use.

Here's the output I'm getting with the 512Mb Nokia MMC card.

Ready.
mmc_init: 1
mmc_read: 
Entered Address:3
1
5D 98 58 10 1 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4A F7 CF BF 7E FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FA FF 28 50 0 80 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 D0 A7 55 FB E7 DF BF 7E FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF Cleared data buffer
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 mmc_write: 
Entered Address:3
1
mmc_read: 
Entered Address:3
1
FF 81 90 80 10 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 90 FB EB FF FF 
FF FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 48 78 A3 10 1 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 80 10 9 1A 7D FD FF FF DF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

Steps (resulting in the above output): 1.Initialise 2.Read data in address 3 3.Print sector(now-data in address 3) 4.Clear data buffer 5.Print data buffer (to verify blank) 6.Write data (all zeros) to address 3 7.Read data in address 3 8.Print sector(now-data in address 3)

Step 8 should result in printing all zeros.. Can someone throw some light on this?

I'm trying to make this: (Arduino to micro SD card logger) http://www.youtube.com/watch?v=Hu0tokpsdrM