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

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

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

跳至解决方案
1,578 次查看
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 项奖励
回复
1 解答
1,570 次查看
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

在原帖中查看解决方案

2 回复数
1,571 次查看
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

1,547 次查看
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 项奖励
回复