I2C Code for Serial EEPROMs

Has anyone actually gotten the code in the Playground to work talking to a serial EEPROM like a 24LC256? I have a board setup with a DS1307 RTC and a 24LC256 sitting on the SDA/SCK lines. I have the DS1307 running, so I know the I2C hardware and Arduino Wire library is OK. I am 99% sure the 24LC256 is set up and connected OK. I have played with the code there trying to write random bytes to locations and reading them back, and no matter what I write I seem to only get 0x00 or 0xFF back.

Anyone have any luck yet? Anyone have a completed library for serial eeproms?

cheers ... BBR

brinnbr,

Here is code that I used to test the 24LC246. It's working fine and I also have a RTC on the buss. It's mainly a tweaked example from the Playground. Hope it helps.

/* Simple read & write to a 24LC256 256K EEPROM using the Wire library.
 * Addresses are ints - 0000-7FFF (32767) Data is bytes (8 bits x 32767 = 256K)
 * Functions for R/W of single byte or a page of bytes. Max page is 28 bytes.
 * SETUP:           _ _                                 
 * Arduino GND- A0-|oU |-Vcc  to Arduino Vcc
 * Arduino GND- A1-|   |-WP   to GND for now. Set to Vcc for write protection.
 * Arduino GND- A2-|   |-SCL  to Arduino 5
 * Arduino GND-Vss-|   |-SDA  to Arduino 4
 *                  ---       (A2, A1, A0 to GND for 1010000 (0x50) address.)
 *                            If set to Vcc adds to address (1010,A2,A1,A0)
 */

#include <Wire.h>
#define EEPROM_ADDR 0x50           // I2C Buss address of 24LC256 256K EEPROM


void setup(){
  Wire.begin();                        // join I2C bus (address optional for master)
  Serial.begin(9600);

  // TESTS FOR EACH FUNCTION BEGIN HERE
  Serial.println("Writing Test:");
  for (int i=0; i<20; i++){            // loop for first 20 slots
    i2c_eeprom_write_byte(EEPROM_ADDR,i,i+65);   // write address + 65 A or 97 a
    Serial.print(". ");
    delay(10);                         // NEED THIS DELAY!
  }
  Serial.println("");
  delay(500);
  Serial.println("Reading Test:");
  for (int i=0; i<20; i++){            // loop for first 20 slots
    Serial.print(i2c_eeprom_read_byte(EEPROM_ADDR, i),BYTE);
    Serial.print(" ");
  }
  // setup for page tests . . .
  byte PageData[30];                   // array that will hold test data for a page
  byte PageRead[30];                   // array that will hold result of data for a page
  for (int i=0; i<30; i++){            // zero both arrays for next test
    PageData[i] = 0;    
    PageRead[i] = 0;
  }
  Serial.println("");
  for (int i=0; i<30; i++) PageData[i] = i+33;  // fill up array for next test char 33 = !

  Serial.println("Writing Page Test:");
  i2c_eeprom_write_page(EEPROM_ADDR, 100, PageData, 28 ); // 28 bytes/page is max

  Serial.println("Reading Page Test:");
  i2c_eeprom_read_buffer( EEPROM_ADDR, 100, PageRead, 28);
  for (int i=0; i<28; i++){
    Serial.print(PageRead[i],BYTE);    // display the array read
    Serial.print(" ");
  }
}

void loop(){
}

void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
  int rdata = data;
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8));    // Address High Byte
  Wire.send((int)(eeaddress & 0xFF));  // Address Low Byte
  Wire.send(rdata);
  Wire.endTransmission();
}

// Address is a page address, 6-bit (63). More and end will wrap around
// But data can be maximum of 28 bytes, because the Wire library has a buffer of 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddresspage >> 8)); // Address High Byte
  Wire.send((int)(eeaddresspage & 0xFF)); // Address Low Byte
  byte c;
  for ( c = 0; c < length; c++)
    Wire.send(data[c]);
  Wire.endTransmission();
  delay(10);                           // need some delay
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8));    // Address High Byte
  Wire.send((int)(eeaddress & 0xFF));  // Address Low Byte
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}

// should not read more than 28 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8));    // Address High Byte
  Wire.send((int)(eeaddress & 0xFF));  // Address Low Byte
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,length);
  //int c = 0;
  for ( int c = 0; c < length; c++ )
    if (Wire.available()) buffer[c] = Wire.receive();
}

brianbr,

Here is code that I used to test the 24LC246. It's working fine and I also have a RTC on the buss. It's mainly a tweaked example from the Playground. Hope it helps.

/* Simple read & write to a 24LC256 256K EEPROM using the Wire library.
  • Addresses are ints - 0000-7FFF (32767) Data is bytes (8 bits x 32767 = 256K)
  • Functions for R/W of single byte or a page of bytes. Max page is 28 bytes.
  • SETUP:           _ _
  • Arduino GND- A0-|oU |-Vcc  to Arduino Vcc
  • Arduino GND- A1-|   |-WP   to GND for now. Set to Vcc for write protection.
  • Arduino GND- A2-|   |-SCL  to Arduino 5
  • Arduino GND-Vss-|   |-SDA  to Arduino 4
  • ---       (A2, A1, A0 to GND for 1010000 (0x50) address.)
  • If set to Vcc adds to address (1010,A2,A1,A0)
    */

oooppps, operator head space error. I had the 'sense' of WP backwards. I pulled WP up to Vcc. I need to cut the trace and ground it.

Thanks for the help. Will take your code and run it as soon as I fix the proto-board.

cheers ... BBR

BIG puff of dust off this thread... :o

Fast Forward to 5 July 2010 and I am using a Data Logger Shield from Adafruit.

It has a DS1307 RTC running on the i2c bus already, and I have a 24LC256 chip (ok, a few) :slight_smile: coming next week. I would like to put one in the prototype area and use it for two tasks- use some of the memory for trouble codes, and the rest for a buffer for the last few minutes of data recorded to the SD card and make it easily available to another 'roaming' datalogger. Using XBee and XBee PRO modules.

Looks like some good info here, feel free to chime in if you know of better.

Thanks!

@Brianbr- Boy do I have fond memories going through Underhill Ctr on my way home (to pleasant valley) from school. Stop for soda/chips at MarCon's (Now Well's General Store(?)..if L and C still are there..I know them long time!) but there was no stop sign in front of St T's church that caught me last visit. :wink:

Is that 24LC256 perhaps? I can't find 24LC246.

Ah I now caught the typo. Thanks for the code!

http://wulfden.org/downloads/datasheets/24LC256.pdf