0
Offline
Newbie
Karma: 0
Posts: 9
Arduino rocks
|
 |
« on: August 06, 2008, 09:58:46 am » |
I'm trying to figure out how to write a program that will dump the entire contents of an I2C EEPROM (in this case, a 24LC16B) out to serial. From what I read in the datasheet for the EEPROM, there's an internal pointer or something on the chip, and a read will start wherever it is (random read). If you want to do a sequential read, you have to do a write first to update that pointer, then switch to reading.
Can anyone give me an idea on how to get started? I've looked at the I2E_EEPROM sample on the playground, but there's something I'm missing.
|
|
|
|
|
Logged
|
|
|
|
|
Canberra, Australia
Offline
Jr. Member
Karma: 0
Posts: 53
Arduino rocks
|
 |
« Reply #1 on: August 07, 2008, 04:09:24 am » |
Hi, I have a 24LC256 (which I believe is similar to yours but just with a larger capacity). To update the pointer you send the address that you want to read from using Wire.send(). There are two Wire.send() calls because the EEPROM address, which ranges from 0x0000 to 0x07FF takes 2 bytes to store. So as an example, if you wanted to start reading from the 1024th byte of the EEPROM you would do: Wire.beginTransmission(I2C_EEPROM_ADDR); Wire.send(0x03); // send the high byte of the EEPROM memory address Wire.send(0xFF); // send the low byte Wire.endTransmission(); Once the internal address pointer has been set, you need to request however many bytes you want to read. Here is an example for reading 16 bytes: byte data[16]; // a byte array to store 16 bytes Wire.requestFrom(I2C_EEPROM_ADDR, 16); // request 16 bytes for (byte i = 0; i < 16; i++) { data[i] = Wire.receive(); // store each byte into the array } Do not read more than 30 bytes in one requestFrom() call because the size of the Wire library's receive buffer is 30 bytes. When dumping your EEPROM, I recommend you use 16 bytes as its evenly divisible into 2048 bytes (the size of your EEPROM). This way you can split your EEPROM into 128 "pages" or blocks (each 16 bytes in size). So to dump your entire EEPROM, loop through all 128 pages, incrementing the internal pointer by 16 each time. Instead of storing the result from Wire.receive() in an array you can print it directly over the serial connection. Note: In the above code examples, I2C_EEPROM_ADDR, should be the I2C address of your EEPROM (if you leave the 3 address pins floating or connected to ground, it will be 0x50). Hope this helps.
|
|
|
|
« Last Edit: August 07, 2008, 04:09:52 am by Waffle »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 9
Arduino rocks
|
 |
« Reply #2 on: August 07, 2008, 07:45:19 am » |
That's a great help, thank you! I did have one question about the WP pin though... If I have write protect enabled, is it still possible to update the internal address pointer?
|
|
|
|
|
Logged
|
|
|
|
|
Canberra, Australia
Offline
Jr. Member
Karma: 0
Posts: 53
Arduino rocks
|
 |
« Reply #3 on: August 07, 2008, 11:45:53 pm » |
If I have write protect enabled, is it still possible to update the internal address pointer? I haven't tested it myself, however it should still work.
|
|
|
|
|
Logged
|
|
|
|
|
Perth, Australia
Offline
Newbie
Karma: 0
Posts: 21
DuinoStamp :)
|
 |
« Reply #4 on: August 08, 2008, 12:22:11 am » |
I tested this only a week ago, not only does it work, but even with WP enabled you can send write commands to the chip....just nothing gets written.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 9
Arduino rocks
|
 |
« Reply #5 on: August 08, 2008, 10:15:18 am » |
Something's tripping me up... the sample code on the Playground for setting the address pointer looks like this: Wire.send((int)(eeaddress >> 8)); // MSB Wire.send((int)(eeaddress & 0xFF)); // LSB
If I do some basic math and set "eeaddress" to 1023, the above lines would send "3" and "255" to the I2C bus. Should it be sending "255" for the LSB, or should it be sending "FF"? Something more like this: Wire.send(eeaddress >> 8, HEX); //MSB Wire.send(eeaddress & 0xFF, HEX); //LSB
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 9
Arduino rocks
|
 |
« Reply #6 on: August 08, 2008, 03:11:34 pm » |
Here's an example of what I'm looking at: #include <Wire.h> #define EEPROM_ADDR 0x50
void setup(){ Wire.begin(); Serial.begin(9600);
int rdata = 33; Wire.beginTransmission(EEPROM_ADDR); Wire.send(0x00); // MSB Wire.send(0x00); // LSB Wire.send(rdata); Wire.endTransmission(); Serial.println(rdata);
Wire.beginTransmission(EEPROM_ADDR); Wire.send(0x00); Wire.send(0x00); Wire.endTransmission(); Wire.requestFrom(EEPROM_ADDR,1); if (Wire.available()) Serial.println(Wire.receive()); } void loop(){ }
From what I can tell, this should open the I2C bus, move the address pointer to the first memory block, and write either the decimal value "33" or the ASCII equivalent "!" to that space. My understanding from the datasheet for the 24LC16B is that the pointer increments by 1 after every operation, so the next little piece moves back to 0x0000 and does a read. I would expect that the read would come back with either the 33 or the ! as well, but I get nothing. My serial monitor shows the 33 on one line, and that unprintable square character on the second line.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 46
Arduino rocks
|
 |
« Reply #7 on: August 08, 2008, 05:36:15 pm » |
I've been doing some fiddling with my own 24LC16B, and I think I have it working. One thing to note is the upper 3 bits of the memory location form the lower 3 bits of the device address, so to access memory location 0x12C, you use the device address 0x51, rather than 0x50. I modified your code, and it now works for me: #include <Wire.h> #define EEPROM_ADDR 0x50
void setup(){ Wire.begin(); Serial.begin(9600);
//Write the data byte rdata = 33; Wire.beginTransmission(EEPROM_ADDR); //Wire.send(0x00); // MSB Wire.send(0x00); // LSB Wire.send(rdata); Wire.endTransmission(); Serial.println(rdata); delay(15);
//Set the memory pointer Wire.beginTransmission(EEPROM_ADDR); Wire.send(0x00); //Wire.send(0x00); Wire.endTransmission(); //Read Wire.beginTransmission(EEPROM_ADDR); Wire.requestFrom(EEPROM_ADDR,1); if (Wire.available()) Serial.println(Wire.receive()); Wire.endTransmission(); } void loop(){ }
To write you only pass it two values, one which specifies the lower 8 bits of the address, and one for data. Then, there needs to be a delay to allow the writing to happen, the data sheet says a max of 10ms, so 15ms might be longer than needed, but ensures it is definately written. Also, the requesting needs to go between its own set of begin/end transmission commands. Here's a simple method I wrote to dump the whole EEPROM for a project of mine: void dump() { Wire.beginTransmission(ADDRESS); Wire.send(0); Wire.endTransmission(); for ( byte upper=0; upper<=8; upper++ ) { for ( int i=0; i<32; i++) { Wire.beginTransmission(ADDRESS+upper); Wire.send(i*8); Wire.endTransmission();
Wire.beginTransmission(ADDRESS+upper); Wire.requestFrom(ADDRESS+upper, 8); //Wait till we get all the bytes while ( Wire.available()<8 ) {}; printInt(upper); Serial.print("-"); printInt(i*8); Serial.print(": "); for ( int j=0; j<8; j++ ) { printInt(Wire.receive()); Serial.print(" "); } Serial.println(); Wire.endTransmission(); } } } void printInt(int i) { Serial.print("0x"); if ( i<16 ) Serial.print("0"); Serial.print(i, HEX); }
HTH
|
|
|
|
« Last Edit: August 09, 2008, 09:56:12 am by agib »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 9
Arduino rocks
|
 |
« Reply #8 on: August 09, 2008, 10:39:41 am » |
I must still be doing something wrong... when I run the code that agib listed above, I get this:
0x00-0x00: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x08: 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x10: 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x18: 0x18 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x20: 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00
and so on, down to 0x08-0xF8. I get the same results with two different chips, which is why I think something isn't right. One of them is a brand new engineering sample, delivered from Taiwan earlier this week. The other was removed from a device (motorcycle dash) that was produced in 2003.
I'm using a Sparkfun Wee, attached to an FTID TTL-232R cable. I've got pins A0, A1, A2, and Vss on the EEPROM wired to GND on the Wee, Vcc wired to 3.3V, WP jumpered over to Vcc (which should enable WP), SCL to pin 5, and SDA to pin 4.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 46
Arduino rocks
|
 |
« Reply #9 on: August 10, 2008, 08:23:59 am » |
I must still be doing something wrong... when I run the code that agib listed above, I get this:
0x00-0x00: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x08: 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x10: 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x18: 0x18 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x20: 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00
and so on, down to 0x08-0xF8. I get the same results with two different chips, which is why I think something isn't right. One of them is a brand new engineering sample, delivered from Taiwan earlier this week. The other was removed from a device (motorcycle dash) that was produced in 2003.
I'm using a Sparkfun Wee, attached to an FTID TTL-232R cable. I've got pins A0, A1, A2, and Vss on the EEPROM wired to GND on the Wee, Vcc wired to 3.3V, WP jumpered over to Vcc (which should enable WP), SCL to pin 5, and SDA to pin 4.
I'd check your power connections, I get exactly that output when I remove the chip from the circuit.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 9
Arduino rocks
|
 |
« Reply #10 on: August 10, 2008, 01:20:32 pm » |
Power looks good (at least according to my Fluke)... 5 Volts at Vcc. With A0-A2 connected to GND and WP connected to Vcc, does the address change? I've tried both 0x50 and 0x51 with the same results.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 46
Arduino rocks
|
 |
« Reply #11 on: August 10, 2008, 06:14:10 pm » |
A0-2 don't matter as they're not used internally, as such assuming you have the 24LC16B the address has to be 0x50 (plus the upper 3 bytes of the memory address)
WP needs to be tied to Vss to be able to write to the eeprom, but you should still be able to read with it tied to Vcc, maybe you could try switching it?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 20
Arduino rocks
|
 |
« Reply #12 on: August 10, 2008, 07:12:12 pm » |
I am a beginner, and probably don't know what I am talking about, but I have been having problems interfacing with I2C and a sparkfun wee. I was wondering if pin 4 is still sda and pin 5 is scl on that board.
|
|
|
|
|
Logged
|
|
|
|
|
Perth, Australia
Offline
Newbie
Karma: 0
Posts: 21
DuinoStamp :)
|
 |
« Reply #13 on: August 10, 2008, 08:35:56 pm » |
I must still be doing something wrong... when I run the code that agib listed above, I get this:
0x00-0x00: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x08: 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x10: 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x18: 0x18 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-0x20: 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00
and so on, down to 0x08-0xF8. I get the same results with two different chips, which is why I think something isn't right. One of them is a brand new engineering sample, delivered from Taiwan earlier this week. The other was removed from a device (motorcycle dash) that was produced in 2003.
I'm using a Sparkfun Wee, attached to an FTID TTL-232R cable. I've got pins A0, A1, A2, and Vss on the EEPROM wired to GND on the Wee, Vcc wired to 3.3V, WP jumpered over to Vcc (which should enable WP), SCL to pin 5, and SDA to pin 4.
Just to clarify....do you have it connecte to pin 4 & 5 digital or analog - I2C bus is pins 4 & 5 of the Analog inputs. I've seen quite a few people get this mixed up.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 20
Arduino rocks
|
 |
« Reply #14 on: August 10, 2008, 09:24:16 pm » |
The sparkfun wee doesn't have analog pins 4 and 5.
|
|
|
|
|
Logged
|
|
|
|
|
|