According to the data sheet:
"Transfer Complete Flag
Acknowledges a byte transfer; TCF is set on the completion of a byte transfer. This bit is valid only during
or immediately following a transfer to or from the I2C module. TCF is cleared by reading the I2C data
register in receive mode or by writing to the I2C data register in transmit mode.
0 Transfer in progress
1 Transfer complete"
After I have written to the buffer, the TCF should be set to zero. But that's not the case, the TCF has always been set to one.
My code is here which is not working:
bool I2C_SendByte(uint8_t data)
{
I2C0->D = (uint8_t)data; //Write Byte to the Buffer
while(!(I2C0->S & I2C_S_TCF_MASK)); //Waiting until the TCF Bit is set.
if(I2C0->S & I2C_S_RXAK_MASK) return 1; //acknowledge signal detected
else return 0; //No acknowledge signal detected
}
but if write it like this, it works!
bool I2C_SendByte(uint8_t data)
{
I2C0->D = (uint8_t)data; ///Write Byte to the Buffer
while(!(I2C0->S & I2C_S_IICIF_MASK)); //Waiting until the TCF Bit is set.
I2C0->S |= I2C_S_IICIF_MASK; //Clear the bit by writing to 1
if(I2C0->S & I2C_S_RXAK_MASK) return 1; //acknowledge signal detected
else return 0; //No acknowledge signal detected
}
Could someone help me please why the TCF Bit doesn't work properly?
Solved! Go to Solution.
Hi
Take a look at Appendix A of https://www.utasker.com/docs/uTasker/uTasker_I2C.pdf to see the behavior of the status register flags for various I2C implementations in the Kinetis parts.
In your particular case you are not respecting the fact that your code writes have to be first synchronised to the clock used by the I2C and so when you write a byte to the data register and then immediately read the status register the I2C bus (which is probably at about 100kb/s rather than the CPU bus of perhaps 60MHz) the I2C bus will still not have had any time to do anything and so you are reading the state "before" it could start (which is "TCF == 1").
Therefore it is not possible to control the transfer as you initially tried (unless you first wait for the flag to go low and then for it to go high again).
Regards
Mark
[uTasker project developer for Kinetis and i.MX RT]
Contact me by personal message or on the uTasker web site to discuss professional training, solutions to problems or rapid product development requirements
For professionals searching for faster, problem-free Kinetis and i.MX RT 10xx developments the uTasker project holds the key: https://www.utasker.com/kinetis/TWR-K22F120M.html
Hi
Take a look at Appendix A of https://www.utasker.com/docs/uTasker/uTasker_I2C.pdf to see the behavior of the status register flags for various I2C implementations in the Kinetis parts.
In your particular case you are not respecting the fact that your code writes have to be first synchronised to the clock used by the I2C and so when you write a byte to the data register and then immediately read the status register the I2C bus (which is probably at about 100kb/s rather than the CPU bus of perhaps 60MHz) the I2C bus will still not have had any time to do anything and so you are reading the state "before" it could start (which is "TCF == 1").
Therefore it is not possible to control the transfer as you initially tried (unless you first wait for the flag to go low and then for it to go high again).
Regards
Mark
[uTasker project developer for Kinetis and i.MX RT]
Contact me by personal message or on the uTasker web site to discuss professional training, solutions to problems or rapid product development requirements
For professionals searching for faster, problem-free Kinetis and i.MX RT 10xx developments the uTasker project holds the key: https://www.utasker.com/kinetis/TWR-K22F120M.html
Thank you for your help and time!
As you mentioned, it takes time to go from high to low.
Now it works!
bool I2C_SendByte(uint8_t data)
{
I2C0->D = (uint8_t)data; //Write Byte to the Buffer
while((I2C0->S & I2C_S_TCF_MASK)); //Do Dummy
while(!(I2C0->S & I2C_S_TCF_MASK)); //Transfer in progress. Wait until Buffer is empty.
if(I2C0->S & I2C_S_RXAK_MASK) return 1; //acknowledge signal detected
else return 0; //No acknowledge signal detected
}