Go Down

Topic: SPI EEPROM functions (Read 570 times) previous topic - next topic

Apr 26, 2011, 07:46 pm Last Edit: Apr 26, 2011, 07:56 pm by stevethatsmyname Reason: 1
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: [Select]
#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: [Select]

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


#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);
 }
 
}

Go Up