Jaromir Sukuba

AN3291 oddity (problems with I2C device on QG8)

Discussion created by Jaromir Sukuba on Nov 28, 2006
Latest reply on May 21, 2018 by Nikhil Prasad
Hi all,
I'm trying to connect 24FC512 EEPROM to QG8 device. I downloaded AN3291 and copied routines to read/write from EEPROM with I2C module in HCS08 devices into my project, after a slight changes (like converting IIC1S to IICS and so on) I downloaded code to FLASH and the routines behaved somehow strange. Write routine followed with read routine worked, but reading byte back stopped at waiting for ACK signal after third transmitted byte (first is device address, second and third are memory address bytes). I searched for problem in read routine, but when I placed two write routines subsequently, the second one stopped at the same place, indicating the is something wrong with the write routine. Putting AN in contrast with datasheet showed that IICIF flag should be cleared (by writing 1) after writing data byte into EEPROM.
This is how routine looked originally:

void I2C_write_byte (word addr,byte data)
{
EE_Addr = addr; // address input;
temp = (EE_Addr_H & 0x07) 1;
IIC1C_TX = 1; // Set transmit mode;
//-------start of transmit first byte to IIC bus-----
IIC1C_MST = 1; // Start transfer - Master bit = 1;
IIC1D = sl_addr | temp; // send "Write" + high address;
while (!(IIC1S_IIC1IF));
IIC1S_IIC1IF = 1;
while (IIC1S_RXAK); // wait for ACK from slave;
//-----Slave ACK occurred------------
IIC1D = EE_Addr_L; // send low address byte;
while (!(IIC1S_IIC1IF)); // wait till data transferred;
IIC1S_IIC1IF = 1;
while (IIC1S_RXAK); // wait for ACK from slave;
//-----Slave ACK occurred------------
IIC1D = data; // write data byte into EEPROM;
while (!(IIC1S_IIC1IF)); // wait till data transferred;
while (IIC1S_RXAK); // wait for ACK from slave;
IIC1C_MST = 0; // STOP bit;
}

and this is how the routine works for me:

void I2C_write_byte (word addr,byte data)
{
EE_Addr = addr; // address input;
temp = (EE_Addr_H & 0x07) 1;
IIC1C_TX = 1; // Set transmit mode;
//-------start of transmit first byte to IIC bus-----
IIC1C_MST = 1; // Start transfer - Master bit = 1;
IIC1D = sl_addr | temp; // send "Write" + high address;
while (!(IIC1S_IIC1IF));
IIC1S_IIC1IF = 1;
while (IIC1S_RXAK); // wait for ACK from slave;
//-----Slave ACK occurred------------
IIC1D = EE_Addr_L; // send low address byte;
while (!(IIC1S_IIC1IF)); // wait till data transferred;
IIC1S_IIC1IF = 1;
while (IIC1S_RXAK); // wait for ACK from slave;
//-----Slave ACK occurred------------
IIC1D = data; // write data byte into EEPROM;
while (!(IIC1S_IIC1IF)); // wait till data transferred;
//*****************************here is flag clearing*************************
IIC1S_IIC1IF = 1; //!!!!!!!!!!!ADDED LINE!!!!!!!!!!!!
//***************************************************************************
while (IIC1S_RXAK); // wait for ACK from slave;
IIC1C_MST = 0; // STOP bit;
}

I think it is quite logical to clear flag after it was set. This is also mentioned in datasheet for QG8 device (figure 11-3) - there is difference, described as interrupt routine, but it can be easily converted into polled routines, IICIF flag is cleared after EVERY entry to interrupt routine, it means everytime when IICIF flag is set.
After adding line routines work like expected - I'm able to write/read from external EEPROM.

Is the missed line mistake in document or I have got another problem?


By the way, interesting fact is that the write/read sequence worked well when doing single steps through routine code AND with Data window opened. With Data windows closed, routine hanged on the same place as before. It is probably because I2C module registers were showed in Data window and thus read by BDM POD.

Outcomes