24LC256 Page Wrap Writing errors.

Recently got the 24LC256 from sparkfun, and wanted to incude it in a current project I am working on. I was having problems with corrupted and missing data, however.

From the datasheet-

Page write operations are limited to writing
bytes within a single physical page,
regardless of the number of bytes actually
being written. Physical page boundaries
start at addresses that are integer
multiples of the page buffer size (or ‘page
size’) and end at addresses that are
integer multiples of [page size – 1]. If a
Page Write command attempts to write
across a physical page boundary, the
result is that the data wraps around to the
beginning of the current page (overwriting
data previously stored there), instead of
being written to the next page, as might be
expected. It is, therefore, necessary for the
application software to prevent page write
operations that would attempt to cross a
page boundary.

To summarize as I understand it presently, corrections welcome!!

The memory in the 24LC256 is set up in pages. These pages are 64 Bytes in size. This makes the starting address of the first page 0x0000 and the last address on the first page is 0x003F. The second page starts at 0x0040, and finishes at 0x007F. Third is 0x0080 to 0x00BF and so on.

If you set the Internal Address Pointer close to the end of one of the pages, and attempt to write past it, it DOES NOT continue on to the beginning of the next page as one might expect. It wraps around to the beginning of that page and overwrites the data there.

Now… if you set the Internal Address Pointer close to the end of one of the pages, and attempt to read past it, it DOES continue on to the beginning of the next page as one might expect. There is no page wrap.

I cobbled this together to demonstrate-

// Some code to demonstrate 'page wrap' that occurs on writing past certain address points on a 24LC256.
// mashup from Volkemon 7/2010



#include <Wire.h>  


char chipAdress=0x50;   // 24LC256 address on the bus, pins a0,a1 and a2 tied to ground. 

int pacs = 30;  // variable to control how many Bytes are read/written per string. Decimal Value!! Set to desired value for test,minimum value is 1. 
                // Maximum is 31 due to <Wire.h> library resrtriction. Any data written after that will be lost, without error message.


char startaddr = 0x14; // variable to set start address in memory we are writing to.   HEX value!!!    maximum value is FF.
                       // 64= 0x40, 63=0x3F, 50=0x32, 40=0x28, 30=0x1E, 20=0x14, etc 
                       // http://www.easycalculation.com/decimal-converter.php   Decimal to HEX converter tool and more.

                   



void setup()

{
  Wire.begin();             // enable the i2c bus 
  Serial.begin(19200);      // Make sure you set the serial monitor to match! :)
}



void loop()
{

  Serial.print("Writing starting at bite/slot "); Serial.print(startaddr, DEC);  // info sent to serial monitor for debugging.
  Wire.beginTransmission(chipAdress);    // chip address on the TWI bus, not chip memory address.
  
                  //Set up the chip Internal Address Pointer to the desired location
  Wire.send(0x00);          //First  7 bits of the address (max value 7F, BTW :)  Make sure you change it below also if you change this!!
  Wire.send(startaddr);     //Second 8 bits of the address set in the beginning, set above. 

  
  for (char ct=0x0; ct<pacs; ct++)  // loop where we write info to Wire library buffer.
  {
    
   Wire.send(ct);   // Sends the value of 'ct' to Wire library buffer.
                    // 'ct' is the increment count to 'pacs'. Makes the wrap point easy to detect.
  
  }
  Wire.endTransmission();      // commands write of data from Wire library buffer to chip , 'closes' chip
  
  Serial.println(" Done.");


  Serial.print("Reading from bite/slot "); Serial.print(startaddr, DEC);
  Wire.beginTransmission(chipAdress); // chip address on the TWI bus, not chip memory address.
  
                      //Set up the chip Internal Address Pointer and start reading where you started writing before
                      
  Wire.send(0x00);           //First  7 bits of the address in chip memory  (max value 7F, BTW :)
  Wire.send(startaddr);          //Second 8 bits of the address in chip memory, (set in the beginning).
  Wire.endTransmission();    // sends data from Wire library buffer to chip, setting chip Internal Address Pointer
  
                                     
  Wire.requestFrom(chipAdress, pacs);         // from chipAdress (bus address of chip) , Wire requests 'pacs' number of packets in a string.
  
  while(Wire.available()){                // 'while loop' start, Checks to see if data is waiting
    Serial.print("  ");                  // space to format packets on serial monitor
    Serial.print(Wire.receive(), HEX);  // print the values received in hexadecimal format on the serial monitor. FF is the page wrap.
  }                                    // end bracket for 'while loop'
  
  Wire.endTransmission();           // when 'while loop' is finished (no more data available) 'closes' chip and removes it from the bus.
  
  Serial.println("");
  delay(1000);
}

Using the code above, you can change the start address of where you write a 30 Byte sting to chip memory. It is set to start at address 0x1E (dec 20) and write a 30 character string.

Opening the serial monitor, you will see a write notice, “Done”, and then a read notice, then the data that results. Note that the count is linear.

Now go into the code and change ‘startaddr’ to 0x28 (dec 40). This will cause out 30 byte message to go over the end of the page. Now upload the change, and open the serial monitor.

Opening the serial monitor, you will see a write notice, “Done”, and then a read notice, then the data that results. Note that the count is linear up to the 14th value, then returns FF. This is because the page wrap caused the write to go to the beginning of the page, and the read goes on to the next page unaffected.
(EDIT* I say it returns the value FF above…if you have a virgin 24LC256! If you already have data written, it will be listed instead. The break in the linear progression will alert you to the page break, however.)

THIS simple fact was causing great problems in my datalogger project, as data gets corrupted as Page Wraps happen on a somewhat random basis. This was when I used a simple counter to advance the Internal Address Pointer from the software. I now realize that there must be some sort of check to see if the start address is too close to a ‘page end’ to write the desired data without causing a Page Wrap.

I am looking towards organizing the data written to the 24LC256 in a 30 byte packet, increment the ‘startaddr’ by 2, and so on. This should make the beginning of a page be the start address every other data string, and only ‘waste’ 4 bytes per page.

I have read that the Wire.library allows for 32 byte strings, but I can only put the variable ‘pacs’ to 30. It will read 31 or 32 bytes at once, but will only seem to write 30. No error sent upon the inability to write the last two bytes either.

Thats where I am now. Any help or advice is appreciated!