The "TCF" Bit which located in the I2C Status register(I2Cx_S) is always set. MK22FN512VLH12

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

The "TCF" Bit which located in the I2C Status register(I2Cx_S) is always set. MK22FN512VLH12

Jump to solution
803 Views
John_Tekle
Contributor I

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? 

0 Kudos
1 Solution
795 Views
mjbcswitzerland
Specialist V

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

View solution in original post

2 Replies
796 Views
mjbcswitzerland
Specialist V

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

772 Views
John_Tekle
Contributor I

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
}

0 Kudos