# Can't read written data out of 24AA1025

I've got a PIC18F with MSSP that I'm interfacing with a 24AA1025. I'm using MPLAB 8 and the functions from C18 to make my life easier. The only problem is that I've (supposedly) written a byte to the 24AA1025, but when I read it back, I get 0xFF instead of the byte I wrote.

Here's how I have the EEPROM wired up:

A0 - GND
A1 - GND
A2 - Vcc
Vss - GND
SDA - pulled up to +5 via 2.2k resistor, and connected to SDA on PIC
SCL - pulled up to +5 via 2.2k resistor, and connected to SCL on PIC
WP - Vss
Vcc - 5V


Here's my write function (now edited with working code):

bool I2CWriteByte( long address, unsigned char data)
{
unsigned char ret;
unsigned char control_byte;

control_byte = (address >= 65536) ? 0b10101000 : 0b10100000;

IdleI2C();

// perform ack polling around control byte sending every time
ret = SendControlByte( control_byte);
if( ret == -1)
return false;

if( ret == -1)
return false;
if( ret == -1)
return false;
ret = WriteI2C( data);
if( ret == -1)
return false;

StopI2C();
return true;
}


Here's my read function (now edited with working code):

bool I2CReadByte( long address, unsigned char* data)
{
unsigned char ret;
// to do a read, first do part of a write but don't send the data byte, then send a new control byte with bit 0 set to 1 for read.
// see 24AA1025 datasheet page 12
unsigned char control_byte;

control_byte = (address >= 65536) ? 0b10101000 : 0b10100000;

IdleI2C();
ret = SendControlByte( control_byte);
if( ret == -1)
return false;

if( ret == -1)
return false;
if( ret == -1)
return false;

control_byte = (address >= 65536) ? 0b10101001 : 0b10100001;
ret = SendControlByte( control_byte);
if( ret == -1)
return false;

// now return value
StopI2C();
return true;
}


EDIT -- The all-important SendControlByte() function, which does the requisite ack polling:

bool SendControlByte( unsigned char control_byte)
{
bool nack;
bool ret;

nack = true;

while( nack) {
StartI2C();
ret = WriteI2C( control_byte);
if( ret == -1)
return false;
if( SSPCON2bits.ACKSTAT == 0)
nack = false;
}
}


WriteI2C never returns an error, so I assume that it actually worked...

I used my logic sniffer's I2C protocol analysis tool, and it sure looks like all of the data is being sent/received properly:

Can anyone suggest something to do next for debugging? The control byte looks correct, as it is 0b1010 after START, followed by the block identifier, A0, A1, and R/!W. I have tested >64KB addresses and confirmed that B1 is set properly. My EEPROM has A0 and A1 grounded, so that looks correct as well. R/!W is low for writes and high just before the read. The only thing I haven't done yet is added a delay after the write, but I will give that a shot tomorrow.

EDIT -- The I2C analysis option does show what you guys have been saying:

• You certainly need a delay after the data write (try 10 ms to begin with, though I'd recommend using the acknowledge polling described when you're polishing it up later). Without it, the read is likely never performed, as the device won't respond to commands during a write cycle. My guess is that it returns 0xff because SDA remains high (since the device never pulls it low - it's busy!). – exscape Sep 11 '12 at 8:50
• @Dave Hi dave you have done a commendable job with the thorough analysis tools that you have got.Can you tell what are the tools that you have used to debug I2c and capture the send signals and displayed as shown above. And i also would like to explain how the SendControlByte works,I know it is working with acknowledge polling but when i tried compiling with the code that you posted ..it did not worked well.I tried with c18. And what values have you given for true and false?.Thanks – Rookie91 Dec 6 '13 at 4:12
• Hi @Rookie91, it's been a while, so let me try to remember. The software is from the Open Logic Sniffer project. A year ago I found it hard to get a build that worked, but the latest builds seem pretty good. Try this thread to get the download link: dangerousprototypes.com/forum/…. As far as true and false go, you can technically use anything you want, but 0 for false and 1 for true are typical. Or include <stdbool.h> and use its definition. – Dave Dec 11 '13 at 3:43