Microchip 24xxnnn i2c EEPROM

Has anyone tried using Microchip i2c eeprom code in the playground? I’ve tried this code with both the 24AA515 and 24LC256, the later being the chip that the code was written for (although all 24xxnnn chips are supposed to be interchangeable). However all I get when ‘reading’ is the wire output buffer, interestingly this continues when the chip is removed, so it’s not even reaching the eeprom. The chip is wired correctly (Vcc +5, Vss gnd, SCL to 4, SDA to 5, everything else gnd).
Has anyone got these chips working? or have other ideas? if all else fails I might resort to bit-bashing, but a wire lib solution would be better.

There's some undocumented funny business with the Wire library and I2C addresses. The Wire lib will take care of the I2C least significant address bit (the read or write bit) for you, so if you pass in the full 8-bits including read and write, this ends up getting shifted, and your address is invalid. This problem happened a lot to me when I was working with an I/O expander and an RTC. Suffice to say, the answer was nowhere on the Arduino or Wiring sites.

I have the 24C02C version of this chip, and its address is: 1010(A0)(A1)(A2)(W/R). If I had all my A pins tied to ground, the address I would pass the Wire calls would be: 101 0000, or 0x50.

Checked this, and it isn't the problem. More info if it helps: when reading I get : 0,page address, write buffer 1,..., write buffer n

Going through the datasheet, the code seems to be doing it right, but I don't have any experience with the wire lib, so I couldn't really tell.

MysteriousAges could you post your code? The datasheet stated that 1010 was the prefix and 0000 was the read code and 0001 was the write code. This would be 0xA0 and 0xA1 in hex. Does the wire code handle the read/write bit?

This is for the atmel AT25C01A

If the wire library you're using is the same as the one in the Arduino environment, then yes, the Wire library will handle the read/write bit. I don't currently have any code for this EEPROM, but I can show you the idea using code from a sketch that interfaces with a TWI RTC.

....

#define WIRE_RTC_ADDR 0x51

....

  // Set control registers, and nab the voltage low warning bit out of the seconds register.
  Wire.beginTransmission(WIRE_RTC_ADDR);
  Wire.send(0x00);
  Wire.send(0x00);
  Wire.send(0x1C);
  Wire.endTransmission();
  Wire.requestFrom(WIRE_RTC_ADDR, 4);
  byte temp = Wire.receive();
  cur_time.seconds = temp & 0x7F;
  cur_time.minutes = Wire.receive();
  cur_time.hours = Wire.receive();
  cur_date.days = Wire.receive();
  cur_date.weekday = Wire.receive();

....

Wire.beginTransmission is starting a write, while Wire.requestFrom is starting a read. Notice they still use the same address.

This is my heavily stolen code:

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


  // 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],DEC);    // display the array read
    Serial.print(" ");
  }
}

void loop(){
}

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
}

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

and this is what I get out (should be numbers 33:61):

Writing Page Test:
Reading Page Test:
0 64 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30

problem solved: a user error again! (one of the breadboard contacts was stuffed and somehow made the A2 pin think that it was high... weird)

Thank you for the code examples!