Pages: [1]   Go Down
Author Topic: SPI EEPROM functions  (Read 480 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I had been trying to get a SPI EEPROM working over the weekend and for some reason it didn't work.... then I realized that my page size was 32 bytes whereas the arduino example (http://www.arduino.cc/en/Tutorial/SPIEEPROM) was 128 bytes.

I decided to turn my code (mostly derived from the example) into a couple of functions that can be used to write N bytes to a SPI eeprom.

Unfortunately I am not quite good enough at coding yet to make it into a library, sorry for that.

The function that I call from my sketches is :
void write_eeprom_page(char page[], int pagesize, unsigned int address);
which you pass an array which is to be written, and a pagesize, and the address to start writing. 

If the pagesize you give it is larger than the page size of the eeprom it will wrap over and start writing over the stuff it already wrote.

Don't pass it a page[] array that is smaller than pagesize. It's OK if it's larger... just not smaller.

If you don't want to write a whole page.... then pass a smaller pagesize.  For example if you want to write to address 60-69, you would call:
write_eeprom_page(page, 10, 60);

there are a bunch of defines in "extern_eeprom.h:" that determine stuff like what wires are what.  You may need to modify these to get the sketch to work.  There's also some timing delays defined there... the WRITEDELAY determines how long the arduino will wait after writing one page.  I think a typical eeprom write time is 5ms.  There's also WRENDELAY I set to 5ms also because I didn't know just how critical timing was on that. It could probably be decreased. 

Oh one more thing, before you call write_eeprom_page() or write_eeprom_byte() you have to call setup_extern_eeprom(); which will setup I/O pins and set up SPI.

extern_eeprom.h:

Code:
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss
#include "WProgram.h"

//opcodes AS SEEN BY EEPROM
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2

#define WRITEDELAY 5
#define WRENDELAY 5


char spi_transfer(volatile char data);

void write_eeprom_page(char page[], int pagesize, unsigned int address);

void write_eeprom_byte(char towrite, unsigned int address);

byte read_eeprom(int EEPROM_address);

void setup_extern_eeprom(void);

extern_eeprom.cpp:

Code:
#include "extern_eeprom.h"




void write_eeprom_page(char page[], int pagesize, unsigned int address)  //page[] is the array to write, pagesize in bytes.
{

  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(WREN); //write enable
  digitalWrite(SLAVESELECT,HIGH);
  delay(WRENDELAY);
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(WRITE); //write instruction

  spi_transfer((char)(address>>8));   //send MSByte address first
  spi_transfer((char)(address));      //send LSByte address

 for(int i=0; i<pagesize; i++)
  {
  spi_transfer(page[i]);
  }
  digitalWrite(SLAVESELECT,HIGH);
    delay(WRITEDELAY);  //give it a few millis to write
}

void write_eeprom_byte(char towrite, unsigned int address)  //towrite is the char to write
{

  
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(WREN); //write enable
  digitalWrite(SLAVESELECT,HIGH);
  delay(WRENDELAY);
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(WRITE); //write instruction

  spi_transfer((char)(address>>8));   //send MSByte address first
  spi_transfer((char)(address));      //send LSByte address
  spi_transfer(towrite);
  digitalWrite(SLAVESELECT,HIGH);
  delay(WRITEDELAY);  //give it a few millis to write
  
}

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

byte read_eeprom(int EEPROM_address)
{
  //READ EEPROM
  int data;
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(READ); //transmit read opcode
  spi_transfer((char)(EEPROM_address>>8));   //send MSByte address first
  spi_transfer((char)(EEPROM_address));      //send LSByte address
  data = spi_transfer(0xFF); //get data byte
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
  return data;
}


void setup_extern_eeprom(void)
{
  byte clr;
     pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  // SPCR = 01010000
  //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
  //sample on leading edge of clk,system clock/4 rate (fastest)
  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR;
  clr=SPDR;
  delay(10);
  
  
}

and here's an example of a sketch that uses these functions:

Code:

#include "extern_eeprom.h"
char buffer [32];

void fill_buffer()
{
  
  for (int I=0;I<32;I++)
  {
    buffer[I]=I;
  }
}

void setup()
{

  setup_extern_eeprom();
  char c = 32;
  int d;
  int pgsize = 32;
  int addr = 64;
  int i;
  fill_buffer();

   write_eeprom_page(buffer, pgsize, 0);

  for(i=0; i<32; i++)
  {
    d = read_eeprom(i);
  //  Serial.println(d, DEC);
  }
  
}
« Last Edit: April 26, 2011, 12:56:53 pm by stevethatsmyname » Logged

Pages: [1]   Go Up
Jump to: