kl25 I2C_HAL_WriteByte()

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

kl25 I2C_HAL_WriteByte()

Jump to solution
1,093 Views
Edrianocarlos
Contributor IV

Hello.

I am currently writing an I2c Baremetal function.

and after a long time testing and analyzing the data i could realize that   ITCF and  RXAK flags does not work as i thought.

after sending a byte to I2c if i try to test either TCF and RXAK both of them are true and i start to overwrite the data register. if i use the code below nothing works. i already found a way to solve that testing the IICIF flag. this one works.

but my question is. doesnot this flags works at all? i am assuming something wrong?

I2C_HAL_WriteByte(I2C0,0xA0);

while((I2C0_S & I2C_S_TCF_MASK )==0){}

I2C_HAL_WriteByte(I2C0,0x00);

while((I2C0_S & I2C_S_TCF_MASK )==0){}

I2C_HAL_WriteByte(I2C0,0x00);

while((I2C0_S & I2C_S_TCF_MASK )==0){}

also if i use RXAK the same problem occurs

I2C_HAL_WriteByte(I2C0,0xA0);

while((I2C0_S & I2C_S_RXAK_MASK )==0){}

I2C_HAL_WriteByte(I2C0,0x00);

while((I2C0_S & I2C_S_RXAK_MASK )==0){}

I2C_HAL_WriteByte(I2C0,0x00);

while((I2C0_S & I2C_S_RXAK_MASK )==0){}

the code below works fine.

  I2C_HAL_SendStart(I2C0);

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,endereco);

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,0x00);

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,0x00);

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

0 Kudos
1 Solution
670 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Edriano Araujo:

As you will find in most of the I2C projects with Kinetis, in polling mode the IICIF flag is used instead of the TCF flag. The reason for this is that TCF is only valid for a specific period of time during the byte transfer and it is a read only flag. TCF does not clear immediately after writing to the I2Cx_D register but until the I2C peripheral starts sending the clock signal. In comparison the flag IICIF can be cleared by the user and it must be 0 before sending any byte.

The picture below shows what I mean, by reflecting the values of TCF and IICIF in digital pins during a byte transfer; the pulse at the bottom is another pin which is toggled just after the write to I2Cx_D.

pastedImage_7.png

The next code might work when polling TCF, but you will notice that it is redundant (waiting while TCF = 1 then waiting while TCF = 0

  I2C_HAL_SendStart(I2C0_BASE_PTR);

  I2C_HAL_WriteByte(I2C0_BASE_PTR, 0xA0);

  while((I2C0_S & I2C_S_TCF_MASK) == I2C_S_TCF_MASK){}

  while((I2C0_S & I2C_S_TCF_MASK) == 0){}

  I2C_HAL_WriteByte(I2C0_BASE_PTR, 0xB0);

  while((I2C0_S & I2C_S_TCF_MASK) == I2C_S_TCF_MASK){}

  while((I2C0_S & I2C_S_TCF_MASK) == 0){}

  I2C_HAL_WriteByte(I2C0_BASE_PTR, 0xC0);

  while((I2C0_S & I2C_S_TCF_MASK) == I2C_S_TCF_MASK){}

  while((I2C0_S & I2C_S_TCF_MASK) == 0){}

  I2C_HAL_SendStop(I2C0_BASE_PTR);

I hope this helps to clarify.


Best regards,
Jorge Gonzalez

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

0 Kudos
5 Replies
670 Views
Stano
NXP Employee
NXP Employee

Hello Edriano,

please send me the code of the function I2C_HAL_WriteByte(I2C0,0xA0), or whole code you are working with for I2C communication.

Then I can send you suggestions.

I'm waiting for your answer.

Best Regards,

Stano.

0 Kudos
670 Views
Edrianocarlos
Contributor IV

Hello Stanislav.

Here is my routine. it is blocking read and now it is working perfect but i had to read the interrupt flag.

My question was aboult why reading he TCF flag it does not work? wasnt this flag for this?

anyway i will share my function that may help others searching for the same thing.

void Read_24LC_I2C(unsigned int address,unsigned char *buffer,unsigned char qtd)

{

  unsigned char cnt_i2c;

  while((I2C0_S & I2C_S_TCF_MASK )==0){}

  I2C_HAL_SetDirMode(I2C0,1);

  I2C_HAL_SendStart(I2C0);

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,endereco);

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,(unsigned char)((address >> 8) & 0X00FF));

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,(unsigned char)((address) & 0X00FF));

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C_HAL_SendStart(I2C0);

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,0xA1);

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C_HAL_SetDirMode(I2C0,0);

  I2C_HAL_SendAck(I2C0);

  (void)I2C_HAL_ReadByte(I2C0);

  for (cnt_i2c=0 ; cnt_i2c != qtd; ++ cnt_i2c)

  {

  while((I2C0_S & I2C_S_TCF_MASK )==0){}

  buffer[cnt_i2c] = I2C_HAL_ReadByte(I2C0);

  }

  I2C_HAL_SendNak(I2C0);

  while((I2C0_S & I2C_S_TCF_MASK )==0){}

  I2C_HAL_SendStop(I2C0);

}

0 Kudos
671 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Edriano Araujo:

As you will find in most of the I2C projects with Kinetis, in polling mode the IICIF flag is used instead of the TCF flag. The reason for this is that TCF is only valid for a specific period of time during the byte transfer and it is a read only flag. TCF does not clear immediately after writing to the I2Cx_D register but until the I2C peripheral starts sending the clock signal. In comparison the flag IICIF can be cleared by the user and it must be 0 before sending any byte.

The picture below shows what I mean, by reflecting the values of TCF and IICIF in digital pins during a byte transfer; the pulse at the bottom is another pin which is toggled just after the write to I2Cx_D.

pastedImage_7.png

The next code might work when polling TCF, but you will notice that it is redundant (waiting while TCF = 1 then waiting while TCF = 0

  I2C_HAL_SendStart(I2C0_BASE_PTR);

  I2C_HAL_WriteByte(I2C0_BASE_PTR, 0xA0);

  while((I2C0_S & I2C_S_TCF_MASK) == I2C_S_TCF_MASK){}

  while((I2C0_S & I2C_S_TCF_MASK) == 0){}

  I2C_HAL_WriteByte(I2C0_BASE_PTR, 0xB0);

  while((I2C0_S & I2C_S_TCF_MASK) == I2C_S_TCF_MASK){}

  while((I2C0_S & I2C_S_TCF_MASK) == 0){}

  I2C_HAL_WriteByte(I2C0_BASE_PTR, 0xC0);

  while((I2C0_S & I2C_S_TCF_MASK) == I2C_S_TCF_MASK){}

  while((I2C0_S & I2C_S_TCF_MASK) == 0){}

  I2C_HAL_SendStop(I2C0_BASE_PTR);

I hope this helps to clarify.


Best regards,
Jorge Gonzalez

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
670 Views
Edrianocarlos
Contributor IV

Hello, Jorge.

thank you very much for your replay.

I have done the exactly same test as you do and realized that. I am trying to use more the hall and drive function present at the KSDK. But for many reasons i like to make my own rotines and for that i read the reference manual.

It would save a lot of time if there was a better documentations regarding this. If you read the manual and intend to make a pooling rotine TC would be the choice but does not work as documented.

here is the rotine i made to read the MMA8451. hope this help people with the same problem

unsigned char Read_MMA8451Q_I2C(unsigned char address,unsigned char *buffer,unsigned char qtd)

{

  unsigned char cnt_i2c;

  while((I2C0_S & I2C_S_TCF_MASK )==0){}

  I2C_HAL_SetDirMode(I2C0,1);

  I2C_HAL_SendStart(I2C0);

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,I2C_MMA8451Q_ADD | I2C_WR);

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  if ((I2C0_S & I2C_S_RXAK_MASK) != 0) return(0);

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,(address));

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C_HAL_SendStart(I2C0);

  I2C0_S |= I2C_S_IICIF_MASK;

  I2C_HAL_WriteByte(I2C0,I2C_MMA8451Q_ADD | I2C_RD);

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C_HAL_SetDirMode(I2C0,0);

  I2C_HAL_SendAck(I2C0);

  I2C0_S |= I2C_S_IICIF_MASK;

  (void)I2C_HAL_ReadByte(I2C0);

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  for (cnt_i2c=0 ; cnt_i2c != qtd; ++ cnt_i2c)

  {

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C0_S |= I2C_S_IICIF_MASK;

  buffer[cnt_i2c] = I2C_HAL_ReadByte(I2C0);

  }

  I2C_HAL_SendNak(I2C0);

  while((I2C0_S & I2C_S_IICIF_MASK)==0){}

  I2C_HAL_SendStop(I2C0);

  return(1);

}

0 Kudos
670 Views
Stano
NXP Employee
NXP Employee

Thanks for your reply.

When I saw you code, I think the original code for KL25 FRDM board could be very helpful. It is available on web:

http://cache.nxp.com/files/32bit/software/KL25_SC.exe?fsrch=1&sr=2&pageNum=1

It is *.exe file and will be unpacked to folder you will point to. Then select this folder and open file "FRDM_KL25ZDemo.eww" in IAR:

c:\....\KL25 Sample Code\kl25_sc_rev8\klxx-sc-baremetal\build\iar\FRDM_KL25ZDemo\

Then look for "project\I2C\hal_i2c.c" file. There are tested routines for I2C communication which you can use in your project.

I think it will help you build your code.

Best Regards,

Stano.

0 Kudos