[SOLVED] Read & Write 24LC1025 with wire.h okay but problem after 65536 address

Hi everybody 8)

I'm trying to full 128Ko of data into a 24LC1025 i2c eeprom...

Here is the connection I made to an arduino 2009 and the eeprom:

Pin 1 -> GND
Pin 2 -> GND
Pin 3 -> VCC
Pin 4 -> GND
Pin 5 -> Analog4
Pin 6 -> Analog5
Pin 7 -> GND
Pin 8 -> VCC

Here I made this sketch based on a lot of samples I've see in through the web:

#include <Wire.h>    
 
#define disk1 0x50    //Address of 24LC256 eeprom chip
 
void setup(void)
{
  Serial.begin(9600);
  Wire.begin();  
  
  writeEEPROM(disk1, 2, 21);
  writeEEPROM(disk1, 32768, 145);
  writeEEPROM(disk1, 65538, 203);
  Serial.println(readEEPROM(disk1, 2), DEC);
  Serial.println(readEEPROM(disk1, 32768), DEC);
  Serial.println(readEEPROM(disk1, 65538), DEC);
}
 
void loop(){}
 
void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) 
{
  
  if( eeaddress > 65535 )
    eeaddress = eeaddress | B00001000;    
  
    
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
 
  delay(5);
}
 
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) 
{
  byte rdata = 0xFF;
  
   if( eeaddress > 65535 )
    eeaddress = eeaddress | B00001000;    
 
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
 
  Wire.requestFrom(deviceaddress,1);
 
  if (Wire.available()) rdata = Wire.read();
 
  return rdata;
}

And I get this result with the serial monitor :

203
145
203

Normally I have to get these values:

21
145
203

So there is a problem, I think the arduino goes to 0 after the 65535 value... I tried to change all the unsigned ints with longs but I have the same thing... I added this line of code but it doesn't work :drooling_face:

   if( eeaddress > 65535 )
    eeaddress = eeaddress | B00001000;

So I'm limited only to 64Ko instead of 128Ko... such a shame!!!

Please help :slight_smile:

Only one detail, I don't want to use any external library except the wire i2c library, because I will combine tlc5940 + DMX + LCD i I think the arduino will be limited with the internal timers... but I made some tests with wire and I didn't detected any problem...

Regards :slight_smile:

Hi Axel

  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB

Looks like the code only writes a 16 bit address. I think there is another (top) address bit encoded as part of the device address byte, but you would need to check the datasheet.

Also, I suspect you should be casting the addresses to (byte) rather than (int).

Regards

Ray

for addresses above 65535 you need unsigned long ....

..So

if( eeaddress > 65535 )

will never hit

And I think this is trying to set the 17th (top) address bit, but on the wrong variable.

eeaddress = eeaddress | B00001000;

From the datasheet, it looks like that bitmask would work if applied to deviceaddress, instead of eeaddress.

Hi everybody and thanks for your answers :slight_smile: :stuck_out_tongue:

I only changed the int for a long, and it looks to work!

What i don't understand is I tried this before but it doesn't worked... And now it's looks possible :slight_smile: COOL!!!

#include <Wire.h>    
 
#define disk1 0x50    //Address of 24LC1025 eeprom chip
 
void setup(void)
{
  Serial.begin(9600);
  Wire.begin();  
  
  writeEEPROM(disk1, 10, 21);
  writeEEPROM(disk1, 32768, 145);
  writeEEPROM(disk1, 65547, 203);
  Serial.println(readEEPROM(disk1, 0), DEC);
  Serial.println(readEEPROM(disk1, 32768), DEC);
  Serial.println(readEEPROM(disk1, 65547), DEC);
}
 
void loop(){}
 
void writeEEPROM(int deviceaddress, unsigned long eeaddress, byte data ) 
{
  
  if( eeaddress > 65535 )
    eeaddress = eeaddress | B00001000;    
  
    
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
 
  delay(5);
}
 
byte readEEPROM(int deviceaddress,unsigned long eeaddress)
{
  byte rdata = 0xFF;
  
   if( eeaddress > 65535 )
    eeaddress = eeaddress | B00001000;    
 
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
 
  Wire.requestFrom(deviceaddress,1);
 
  if (Wire.available()) rdata = Wire.read();
 
  return rdata;
}

Let's see in the future if this code don't have any problems, for now I have to write the content of the eeprom and I have to made a delphi .hex generator and test it :slight_smile:

But looks to work good :grin:

With respect, I don't think it IS working correctly. The code still only sends a 16 bit address to the EEPROM, so it cannot read or write at or above 65536.

Would you mind trying another test? Change the code to this:

  writeEEPROM(disk1, 10, 21);
  writeEEPROM(disk1, 11, 42);
  writeEEPROM(disk1, 32768, 145);
  writeEEPROM(disk1, 65547, 203);
  Serial.println(readEEPROM(disk1, 0), DEC);
  Serial.println(readEEPROM(disk1, 32768), DEC);
  Serial.println(readEEPROM(disk1, 65547), DEC);
  Serial.println(readEEPROM(disk1, 11), DEC);

What value do you get from that last read from address 11?

Regards

Ray

see http://picmania.garcia-cuervo.net/recursos/redpicdatasheets/eeprom_serie/24aa1025-24lc1025-24fc1025_21941c.pdf

address is 16 bits. Select upper/lower half in the controlbyte

Exactly :slight_smile: The OP's code is not selecting the top half. See reply #4.

Hi there ]:slight_smile:

Hackscribble:
With respect, I don’t think it IS working correctly.

Unfortunatly for me, you had all the reason : Doesn’t work =(

I tested with your part of code and I get an incoherent result.

Now, I checked the post #4, and during all the day I was thinking about resolving this problem and it’s logical, it’s like to have 2 eeproms with diffrent adresses so what I have to do is to change the adress when I access to the top of the 16bits, then I change to adress to “split” to the other part of the EEPROM (Sorry english isn’t my native language :~ )

So I tried this code:

#include <Wire.h>    
 
#define disk1 B10100000    //Address of 24LC1025 eeprom chip
 
void setup(void)
{
  Serial.begin(9600);
  Wire.begin();  
  
  writeEEPROM(disk1, 10, 21);
  writeEEPROM(disk1, 11, 42);
  writeEEPROM(disk1, 32768, 145);
  writeEEPROM(disk1, 80000, 203);
  Serial.println(readEEPROM(disk1, 10), DEC);
  Serial.println(readEEPROM(disk1, 32768), DEC);
  Serial.println(readEEPROM(disk1, 80000), DEC);
  Serial.println(readEEPROM(disk1, 11), DEC);
}
 
void loop(){}
 
void writeEEPROM(int deviceaddress, unsigned long eeaddress, byte data ) 
{
 
  
  if( eeaddress > 65535 )
    deviceaddress = deviceaddress | B00001000;    
    
  deviceaddress = deviceaddress >> 1;  
  
    
  Wire.beginTransmission(deviceaddress);
  Wire.write((byte)(eeaddress >> 8));   // MSB
  Wire.write((byte)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
 
  delay(5);
}
 
byte readEEPROM(int deviceaddress,unsigned long eeaddress)
{
  byte rdata = 0xFF;
  
   if( eeaddress > 65535 )
    deviceaddress = deviceaddress | B00001000;    
    
    deviceaddress = deviceaddress >> 1;  
 
  Wire.beginTransmission(deviceaddress);
  Wire.write((byte)(eeaddress >> 8));   // MSB
  Wire.write((byte)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
 
  Wire.requestFrom(deviceaddress,1);
 
  if (Wire.available()) rdata = Wire.read();
 
  return rdata;
}

And i get this result on the serial monitor terminal:

21
145
255 - Error here because adress > 65536
42

Now the problem is when I try to R/W to an adress > 65536, it dosen’t work :0

What do you think?

I saw the control Byte is 0101.

Regards and thanks a lot for the help ]:smiley:

Try deleting this line:

  deviceaddress = deviceaddress >> 1;

I don't think you need to shift the device address right by one bit.

If I quit this line of code, I only read 255 values.

On the code I posted abose I’m based me on this source (unfortunatly, dosen’t seems to work… and looks incomplete, the function write_eeprom is not used and I made tests to write and read a byte and it has not worked…)

// Arduino - MCP9700A
#include <Wire.h>

#define DEBUG

// constants
const byte apin = A0;
const byte tc = 10;        // mV/°C
const int t0 = 500;       // mV
const float res = 4.9;    // mV (5 V / 1024 units =~ 4.9 mV)

const byte ctrl_24fc1025 = B10100000;

// variables
int val = 0;
int vout = 0;
int i = 0;
float temp = 0;

// eeprom
unsigned int curr_addr = 0x0000;
byte ee_out = 0;

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
  
  // enable pull-ups on SDA & SCL pins
  pinMode(SDA, INPUT);
  pinMode(SCL, INPUT);
  digitalWrite(SDA, HIGH);
  digitalWrite(SCL, HIGH);
  
  // init I2C
  Wire.begin();
  
  // display welcome
  Serial.println("Arduino Uno Board");
}

int read_eeprom(unsigned int eeprom_addr) {
  
  int i2c_addr = ctrl_24fc1025;
  
  if( eeprom_addr > 65535 )
    i2c_addr = i2c_addr | B00001000;    
 
  // seven-bit address
  i2c_addr = i2c_addr >> 1;
  
  Wire.beginTransmission(i2c_addr);
  Wire.write( (byte) eeprom_addr >> 8 );
  Wire.write( (byte) (eeprom_addr && 0x00FF) );
  
  byte i2c_status = Wire.endTransmission();
  
  if( i2c_status == 0 ) {
    
    Wire.requestFrom(i2c_addr, 1);
    
    while( Wire.available() ) {
      ee_out = Wire.read();    
    }
    
    return ee_out;
    
  } else {
    
    #ifdef DEBUG
    Serial.print("read_eeprom error: ");
    Serial.print(i2c_addr, BIN);
    Serial.print(" (address) + ");
    Serial.print(i2c_status, DEC);
    Serial.println(" (status)");
    #endif
    
    return -1;
  } 
}

int write_eeprom(unsigned int eeprom_addr, byte data) {
  int i2c_addr = ctrl_24fc1025;
  
  if( eeprom_addr > 65535 )
    i2c_addr = i2c_addr | B00001000;    
 
  // seven-bit address
  i2c_addr = i2c_addr >> 1;
  
  Wire.beginTransmission(i2c_addr);
  Wire.write( (byte) eeprom_addr >> 8 );
  Wire.write( (byte) (eeprom_addr && 0x00FF) );
  Wire.write( data );
  
  return Wire.endTransmission();  
}

void loop() {
  // read the analog in value:
  val = analogRead(apin);
  vout = map(val, 0, 1023, 0, 5000);

  // voltage-temperature conversion
  temp = (float) (vout - t0) / tc;    

  // print the results to the serial monitor:
  Serial.print("sensor = ");                       
  Serial.println(vout, DEC);
  
  // print the temperature
  Serial.print("temp = ");
  Serial.println(temp);
  
  // clear
  Serial.println(' ');
  
  
  Serial.print("eeprom[");
  Serial.print(curr_addr, HEX);
  Serial.println("]:");
  
  // eeprom loop
  for(i = 0; i < 26; i++) {
    byte re = (byte) read_eeprom(curr_addr);
    
    Serial.print(re, HEX);
    Serial.print(' ');
  
    curr_addr = (curr_addr + 1);   
  }
  
  Serial.println(' ');

  // wait 2000 milliseconds before the next loop
  // for the analog-to-digital converter to settle
  delay(2000);                     
}

http://decabyte.it/projects/arduino-24xx1025-eeprom-library/

Yes, forget what I said about the '>>' statements. I did not notice that you had changed the #define for disk1.

I'll have a look at your code in detail.

Hi axxel

In your program in post #9, in the writeEEPROM function, can you replace the statement 'Wire.endTransmission();' with this:

Serial.print("writeEEPROM: return from endTransmission: ");
Serial.println(Wire.endTransmission());

What return values does it display for the addresses below and above 65, 535?

You could do the same in readEEPROM.

Ray

Hi!

I modified the code of the Reply #9 and I get this result :

writeEEPROM: return from endTransmission: 0
writeEEPROM: return from endTransmission: 0
writeEEPROM: return from endTransmission: 0
writeEEPROM: return from endTransmission: 2
writeEEPROM: return from endTransmission: 0
21
writeEEPROM: return from endTransmission: 0
145
writeEEPROM: return from endTransmission: 2
255
writeEEPROM: return from endTransmission: 0
42

I should interpretate this :

0:success
1:data too long to fit in transmit buffer
2:received NACK on transmit of address
3:received NACK on transmit of data
4:other error

Address error?

Yes, sounds like address not recognised by the EEPROM.

I don't have that EEPROM but I will see if I can trace the I2C data with a logic analyser.

Logic analyser is playing up, so I have marked up oscilloscope traces of two tests.

I modified your code from post #9 to add a writeEEPROM call in loop() with a 100ms delay. I ran it twice. First time, writing to address 32,768. Second time, to address 80,000. The traces are of the device address byte output by the Arduino in loop().

Traces are in the attached PDF. Comparing them to the 24LC1025 datasheet (section 5.0), both have ‘1010’ as the control code, A0 and A1 = ‘0’, and R/W is low for a write. Only difference is the block select bit is set for address 80,000, which is what I would expect.

So, not sure what to suggest next.

How do you have these pins connected on the EEPROM: A0, A1, A2 and WP?

Regards

Ray

i2c.pdf (154 KB)

On the definitive board, it will be connected like this:

A0 -> GND
A1 -> GND
A2 -> GND
WP -> GND

Try connecting A2 to +5V. There is a note in the datasheet saying:

A2: Non-Configurable Chip Select.
This pin must be hard-wired to logical 1 state (VCC). Operation will be undefined with this pin left floating or held to logical 0 (VSS).

Long shot - since why would this only affect the high-order half of the address space?!

It must be A2 needs to be Vcc.

I have a 24FC1025 with A2 wired to +5V.

I ran your code unmodified and got this output:

21
145
203
42