??? 04/05/07 10:26 Read: times Msg Score: +1 +1 Good Answer/Helpful |
#136670 - Asif,s C Code for I2C Responding to: ???'s previous message |
dear Asif,
I have looked at your C code (but not your assembler). I have some (untested) suggestions that may help. Unlike Erik, I think that it is far easier to write your code in C and then rewrite in assembler if required. make both iic_start() and ack() return the status of SDA line instead of being void functions. And change your no_ack(void) to read_more(char more) function. so: iic_start() returns with "is bus free?" so: ack() is rewritten as: char iic_start(void) { sda = 1; if (scl == 0 || sda == 0) return 0; // bus is BUSY scl = 1; _nop_(); sda = 0; // START condition _nop_(); scl = 0; // tell everyone that we have the bus return 1; // yes we are free } char ack(void) { char ret; sda = 1; // let SDA line float scl = 1; ret = sda; // read the ACK bit _nop_(); scl = 0; // keep hold of the bus return ret; // now you know if you succeeded } void read_more(char more) // was the no_ack() function { sda = !more; // your example only wanted to read one byte. scl = 1; _nop_(); scl = 0; // keep hold of bus } you should find that calling iic_start() will now tell you if the bus is free. and you should always check a send_byte() operation by seeing if you have an ACK. Your call to no_ack() will be replaced by a read_more(0) because you only want to read a single byte. The eeprom needs about 5mS to complete its write-page operation. Either call a 10mS delay() to be safe, or you can poll the eeprom as per the data sheet. You do this by waiting for both iic_start() && send_byte()/ack() to return true. I personally use a char i2c_write(unsigned char j) function that combines your send_byte() and ack() functions. I also suggest that you replace the _nop_() macro with something different. Then you can alter your timing with editing one macro. Your 12MHz micro does not really need the delays except in the start and stop conditions. However if you ever change to a one-clock micro then you will need to slow things down. Once you have our code working, then you can use page-write and multiple read functions of your eeprom. Even the larger 64k eeproms can be written quite fast if you do it a page at a time. And having set a start address, you can read consecutive bytes ad-infinitum. I hope that this helps. David |