Working with an 24FC256 EEPROM
Got it working, but after sending data to it, once the Stop condition is received, it enters an internal write cycle, which means it will not generate Acknowledge signals, according to datasheet.
My test program consists of writing 30 bytes, then reading them back. I got the read-function working by checking the return value from Wire.requestFrom(), trying again until it delivers the bytes I asked for, but I haven't found a way for multiple writes in series, perhaps other than reading a byte inbetween ...
Advice?
#include <Wire.h>
#define DEVICE_ADDR 0x50
#define WRITE_COUNT 30
// Wire.h writebuffer is 32, but we send a 2 byte address, so max 30 data bytes
// (EEPROM page size = 64 bytes)
byte buf[WRITE_COUNT];
/*
* At 400k writing a 30 bytes block takes 1 ms, while
* reading the same takes 4 ms. I would like it to be
* faster on read, but it works now!
*
* The 24LC256 has 64 bytes page size. The Wire library
* has 32 bytes buffer, which given that the address
* is 2 bytes, means we can write 30 bytes.
*
* After writing a number of bytes, the device enters a
* write cycle, where it does not respond normally.
*
* For the immediate read, we detect this, by checking
* return value from requestFrom(), which should be the
* number of bytes we asked for.
*
*/
void setup() {
Serial.begin(9600);
Wire.begin();
Wire.setClock(400000);
while (!Serial) ;
for (int i=0; i<WRITE_COUNT; i++) buf[i]=i;
long start=millis();
writeData(0,buf);
//writeData(128,buf); // <-- second write without delay fails both writes
long end=millis();
Serial.print("Writing done: ");
Serial.println(end-start);
start=millis();
readBytes(0,buf);
end=millis();
Serial.print("Reading ");
Serial.print(WRITE_COUNT);
Serial.print(" bytes = ");
Serial.println(end-start);
for (int i=0; i<WRITE_COUNT; i++) Serial.println(buf[i]);
}
void writeData(unsigned int address, byte *buf) {
for (;;) {
Wire.beginTransmission(DEVICE_ADDR);
Wire.write((address >> 8) & 0xFF); // MSB
Wire.write((address & 0xFF)); // LSB
for (int i=0; i<WRITE_COUNT; i++) {
Wire.write(buf[i]);
}
Wire.endTransmission(); // <-- works for single call to writeData or with 5 ms delay inbetween
//int count = Wire.endTransmission();
//if (count != WRITE_COUNT + 2) continue;
// +2 for address
break;
}
}
/*
* Seems that if we do not wait long enough after writing data, we
* have no way of detecting that when trying to read, ending in a
* situation where
*/
int readBytes (unsigned int address, byte *buf) {
for (;;) {
Wire.beginTransmission(DEVICE_ADDR);
Wire.write((int)(address >> 8)); // MSB
Wire.write((int)(address & 0xFF)); // LSB
Wire.endTransmission();
/*Serial.print("endTransmission returns ");
Serial.println(count);
if (count != 2) {
// device busy?
Serial.println("Busy");
continue;
}*/
int count = Wire.requestFrom(DEVICE_ADDR, WRITE_COUNT);
//Serial.print("requestFrom: ");
//Serial.println(code);
if (count != WRITE_COUNT) continue;
for (int i=0; i<WRITE_COUNT; i++) {
while (!Wire.available());
buf[i]=Wire.read();
}
return 0;
}
return -1; // not found
}
void loop() {
// put your main code here, to run repeatedly:
}