Hi, I am looking for simple read and write routines for I2C interface between Atmel low-end 89C2051 microcontroller and 24C04 serial EEPROM. Any help would be great . Thanks in Advance. Rocknmoon
Rockn, Here is some code I used to dump the contents of a 24C01 EEPROM on a PC. You will need to insert your own code into raise_sda(), drop_sda(), raise_scl(), drop_scl(), and read_sda(). This was written in Borland C to run under DOS, so you may need some minor changes to work under Keil C. This code is not optimised, and was deliberately written to run slowly so I could easily watch each transition using a Digital Storage Oscilloscope. Read the data sheet for the EEPROM you want to talk to, then just do exactly what they tell you to...
void raise_sda(void) { //code to raise(= float) the SDA pin } void drop_sda(void) { //code to drop(= drive low) the SDA pin } void raise_scl(void) { //code to raise(= float) the SCL pin } void drop_scl(void) { //code to drop(= drive low) the SCL pin } int read_sda(void) { //return 0 if SDA is low, or 1 if SDA is high } //---------------------------------------------------------------------- void i2c_stop(void) { delay(1); raise_scl(); delay(1); raise_sda(); delay(1); } void i2c_start(void) { i2c_stop(); //make sure we are starting from a STOP condition drop_sda(); delay(1); drop_scl(); delay(1); } //send BYTE in data. Return 0 is slave sent an ACK, or 1 if slave did not respond int i2c_send(BYTE data) //assumes SCL is already low { int i; for (i=0; i<8; i++) { if ((data & 0x80) != 0) raise_sda(); else drop_sda(); delay(1); //*** this delay for debugging only. remove later. raise_scl(); delay(1); drop_scl(); delay(1); data <<= 1; } raise_sda(); //release SDA so slave can control it delay(1); //*** this delay for debugging only. remove later. raise_scl(); delay(1); i = read_sda(); //read ACK pulse drop_scl(); delay(1); drop_sda(); return i; //return ACK value } int i2c_recv(void) //assumes SCL is low { int i; int accum=0; raise_sda(); //release SDA so slave can control it delay(1); //*** this delay for debugging only. remove later. for (i=0; i<8; i++) { raise_scl(); delay(1); accum <<= 1; //slide left one bit accum |= read_sda();//and copy SDA to bit 0 drop_scl(); delay(1); } return accum; //return data byte } void send_nak(void) { raise_scl(); delay(1); drop_scl(); delay(1); drop_sda(); //prepare to send STOP } void send_ack(void) { drop_sda(); //should always be floating after a read anyway delay(1); //*** this delay for debugging only. remove later. raise_scl(); delay(1); drop_scl(); delay(1); } #define EEP_ADDR 0xa0 //I2C address of EEPROM #define DUMP_END 0xff //last address of EEPROM void main(void) { int i,temp; int result; i2c_start(); //start a write cycle (just to set the address) result = i2c_send(EEP_ADDR);//send write address if (result != 0) { printf("Didn't ACK write cmmand\n",result); return 1; } result = i2c_send(0x00);//to address 00 if (result != 0) { printf("Didn't ACK EEPROM address\n",result); return 2; } i2c_stop(); //stop write cycle i2c_start(); //and start a read cycle result = i2c_send(EEP_ADDR | 0x01); //send read address if (result != 0) { printf("Didn't ACK read command\n",result); return 3; } for (i=0;i < DUMP_END;i++) { temp = i2c_recv(); //read one byte printf("%02x ",temp); if ((i & 0xf) == 0xf) printf("\n"); if (i != DUMP_END) send_ack(); else send_nak(); } i2c_stop(); return 0; }