EEPROM addressing is a mystery to me.

Hi, I'm just starting to use an EEPROM. I have a Mircochip 24AA02 UID (I2C, 2k) it is very similar (perhaps identical) in addressing to the 24LCxxx series.

I'm at the point I am writing and reading bytes to learn the addressing structure and what can go wrong.

This device is:

  • 2048 bits 256 total bytes
  • 2 blocks @ 128 bytes / block I believe the 1st block is at 0x50 and the 2nd at 0x51. I'm currently only working with block 1
  • Page = 8 bytes

Now my issue is:
In a loop, I fill the first block with 0xAD (just a number to use)
then I write 0x00 to address 1 (should be the second location.
When I read the array back it shows all 0's

If i rerun but comment out the write to location 1, the array reports 0xAD for every location.

I'm guessing the whole array is not being reset to 0 and there is some basic addressing faux pas I'm making but I'm at a loss to identify it.


I'm using the example from Nick Gammon, modifying the writes and reads to show me what is going on.

Can anyone point me in the right direction.

One last thing, I'm using an STM32. However I've successfully used this setup to run the BME680 sensor and an OLED display so I'm confident the setup is capable.

My code:

// Original code Written by Nick Gammon -  February 2011
/*
Goal of this test:  To determine the effect of writing past location 127 in a single block.
Test 1;  Fill 0 to 127 with 0xAD
             Read 126 to 140 and compare

0xAD = 173 =  0b10101101  chosen because of almost alternate bits.
*/

#include <Wire.h>     

const byte rom = 0x50;    // Address of 24AA02 eeprom

void setup (void)
  {
  Serial.begin (9600);   // debugging
  Wire.begin ();   
  delay(5000);
  Serial.println(" Starting.......");
 
	  
	for (int i=0;i<127;i++)
		{	
		  writeEEPROM (rom, i,0xAD);
		}
	writeEEPROM (rom, 1,0);  // <<------------------------------leaving or commenting this line seems to change the whole array
	Serial.println("  Completed filling EEPROM addresses 0 - 126.......   ");
		
		
		// read back to confirm
	for (int i=0;i<127;i++)
		{	
			int a = readEEPROM (rom, i);
			Serial.print (i, DEC);  // display to confirm
			Serial.print("    ");
			Serial.println (a);  // display to confirm
		}

}	// --- end of setup ---------------


void loop() {
}   // --- end of main loop --------

//
// -----  EEPROM functions ---------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------------

byte writeEEPROM (byte device, unsigned int addr, byte * data, byte len ) 
  {
  byte err;
  byte counter;

  if (len > BUFFER_LENGTH)  // 32 (in Wire.h)
    return 0xFF;  // too long

  Wire.beginTransmission(device);
  Wire.write ((byte) (addr >> 8));    // high order byte
  Wire.write ((byte) (addr & 0xFF));  // low-order byte
  Wire.write (data, len);
  err = Wire.endTransmission ();
  
  if (err != 0)
    return err;  // cannot write to device
    
  // wait for write to finish by sending address again
  //  ... give up after 100 attempts (1/10 of a second)
  for (counter = 0; counter < 100; counter++)
    {
    delayMicroseconds (300);  // give it a moment
    Wire.beginTransmission (device);
    Wire.write ((byte) (addr >> 8));    // high order byte
    Wire.write ((byte) (addr & 0xFF));  // low-order byte
    err = Wire.endTransmission ();
    if (err == 0)
      break;
    }
   
  return err;
 
  } // end of writeEEPROM

// write one byte to device, returns non-zero on error
byte writeEEPROM (byte device, unsigned int addr, byte data ) 
  {
  return writeEEPROM (device, addr, &data, 1);
  } // end of writeEEPROM

// read len (max 8) bytes from device, returns non-zero on error
//  return code: 0xFF means buffer too long
//               0xFE means device did not return all requested bytes
//             other: other error (eg. device not present)

// Note that if reading multiple bytes the address plus
//  length must not cross a 8-byte boundary or it will "wrap"

byte readEEPROM (byte device, unsigned int addr, byte * data, byte len ) 
  {
  byte err;
  byte counter;

  if (len > BUFFER_LENGTH)  // 32 (in Wire.h)
    return 0xFF;  // too long

  Wire.beginTransmission (device);
  Wire.write ((byte) (addr >> 8));    // high order byte
  Wire.write ((byte) (addr & 0xFF));  // low-order byte
  err = Wire.endTransmission ();
  
  if (err != 0)
    return err;  // cannot read from device
  
  // initiate blocking read into internal buffer
  Wire.requestFrom (device, len);

  // pull data out of Wire buffer into our buffer
  for (counter = 0; counter < len; counter++)
    {
    data [counter] = Wire.read ();
    }
    
  return 0;  // OK
  }  // end of readEEPROM

// read one byte from device, returns 0xFF on error
byte readEEPROM (byte device, unsigned int addr ) 
  {
  byte temp;

  if (readEEPROM (device, addr, &temp, 1) == 0)
    return temp;

  return 0xFF;

  }  // end of readEEPROM

1. The EEPROM 24AA02UID contains 256 locations; where, each location can hold 8-bit data.

2. The chip supports 8-byte page which means one can write 8-byte data into the memory chip in one GO.

3. The chip address is: 1010000b ==> 0x50. The location addresses are: 0x00 - 0xFF.

4. The following sketch writes 8-byte data(1-page) (0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF3) into locations 0x00 - 0x7F. The sketch also performs read-after-write verification.

#include<Wire.h>
byte locAddress = 0x00;
byte wrData[] = {(0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF3}; 
byte rdData[8];

void setup()
{
  Serial.begin(9600);

  Wire.beginTransmission(0x50);
  for(int i=0; i<8; i++)
  {
     Wire.write(i, wrData[i]);      //queuing data in buffer
  }
  byte busStatus = Wire.endTransmission();
  if (busStatus !=0)
  { 
     Serial.print("Memory chip can't be detected...!");
     while(1);    //wait for ever
  }
  delay(5);      //write cycle delay time
  //----------read back and show on Serial Monitor-------
  Wire.beginTransmission(0x50);
  Wire.write(0x00);                     //pointing memory location
  Wire.endTransmission();

  Wire.requestFrom(0x50, 8);
  for (int i=0; i<8; i++)
  {
      rdData[i] = Wire.read();         //getting out data from buffer and save in user array
      Serial.print(rdData[i], HEX);   //should show: 0x12, ........, 0xF3
  }
}

void loop()
{

}

@GolamMostafa

Thanks for the post. However I wasn't able to reconcile the "Wire.write" statement you proposed.

I have however found the error in @nickgammon 's code (a least for my application).

  1. I had to comment out the high order byte statement as the 24AA02 has only one address byte.
  2. I have to remove the extra () around byte (shown in the high order byte code but removed in the low-order byte code.
  //Wire.write ((byte) (addr >> 8));    // high order byte
  Wire.write ( byte (addr & 0xFF));  // low-order byte

Now all I have to do is insure pages do not get written across page boundaries.

John

The following sketch writes just 1-byte data (0x12) at location with address 0x00. Read it back from the same address and shows it on Serial Monitor. I hope that the sketch will help you understanding the purpose Wire.write() method.

#include<Wire.h>
byte locAddress = 0x00;

void setup()
{
  Serial.begin(9600);

  Wire.beginTransmission(0x50);
  Wire.write(locAddress);      //EEPROM's address is queued in buffer
  Wire.write(0x12);               //0x12 is also queued; it will be written at location 0x00
  Wire.endTransmission();      //I2C bus STARTs, EEPROM is detected, ACK recved, data sent, ACK recvd, STOP
  delay(5);      //write cycle delay time
  //----------read back and show on Serial Monitor-------
  Wire.beginTransmission(0x50);
  Wire.write(0x00);                     //pointing memory location
  Wire.endTransmission();

  Wire.requestFrom(0x50, 1);      //request to read 1-byte data from EEPROM of location 0x00
  byte rdData = Wire.read();         //getting out data from buffer and save in user array
  Serial.print(rdData, HEX);           //should show: 0x12
}

void loop()
{

}