I2C IICIF bit flag not activated on transfer

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

I2C IICIF bit flag not activated on transfer

Jump to solution
2,065 Views
luisluna
Contributor II

Hi,

Does anybody of you have happen that after reading some registers in a slave device the IICIF bit flag does not get activated after sendind the register address to the slave device?

This is happening after reading successfully a register and attempting to send the next register address with the same slave address. I think that the I2C module is properly configured because I can communicate with the accelerometer in the board, but when I try other devices I get stuck waiting to for the register address to be send.

This is my init code for the I2C

void init_I2C(void)

{

    SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK;   // Turn on clock to I2C0 module

  

    BW_PORT_PCRn_MUX(PORTE_BASE,24u,kPortMuxAlt5);  // Configure pin functionality for I2C0

    BW_PORT_PCRn_MUX(PORTE_BASE,25u,kPortMuxAlt5);

    I2C0_F  = 0x17;                     // SLC divider is 128 for 50MHz clock (I2C works in ~390KHz).

    I2C0_C1 = I2C_C1_IICEN_MASK;        // enable IIC

}

This is how I read the registers:

unsigned char ReadRegister(unsigned char u8RegisterAddress)

{

unsigned char result;

  /* Send Slave Address */

  IIC_StartTransmission(SlaveID,MWSR);

  i2c_Wait();

  /* Write Register Address */

  I2C0_D = u8RegisterAddress;

  i2c_Wait();

  /* Do a repeated start */

  I2C0_C1 |= I2C_C1_RSTA_MASK;

  /* Send Slave Address */

  I2C0_D = (OV7740_I2C_ADDRESS << 1) | 0x01; //read address

  i2c_Wait();

  /* Put in Rx Mode */

  I2C0_C1 &= (~I2C_C1_TX_MASK);

  /* Turn off ACK since this is second to last byte being read*/

  I2C0_C1 |= I2C_C1_TXAK_MASK;

  /* Dummy read */

  result = I2C0_D ;

  i2c_Wait();

  /* Send stop since about to read last byte */

  i2c_Stop();

  /* Read byte */

  result = I2C0_D ;

  return result;

}

#define i2c_Start()            I2C0_C1 |= I2C_C1_TX_MASK;\

                                         I2C0_C1 |= I2C_C1_MST_MASK

#define i2c_Stop()             I2C0_C1 &= ~I2C_C1_MST_MASK;\

                                          I2C0_C1 &= ~I2C_C1_TX_MASK

This is how I wait fo the byte to be transmited and were my code get stuck because the IICIF bit never gets active.

#define i2c_wait()   while((I2C0_S & I2C_S_IICIF_MASK)==0) {} \

                               I2C0_S |= I2C_S_IICIF_MASK;

1 Solution
1,404 Views
mjbcswitzerland
Specialist V

Luis

Are you sure that the first I2C message transmission has completed (stop condition completed) before sending a second message to a different device?

Try waiting for the bus to become idle before sending the second message - eg.

while (I2C0_S & IIC_IBB) {}

Regards

Mark

View solution in original post

0 Kudos
Reply
5 Replies
1,404 Views
luisluna
Contributor II

Thanks Mark,

Seems like this was causing the issue.

0 Kudos
Reply
1,404 Views
jonathanlee
Contributor II

Hi,Luis,

I have the same question as yours, would you please tell me where you put this "while (I2C0_S & IIC_IBB) {}" to solve the problem?

Best Regards!

0 Kudos
Reply
1,404 Views
luisluna
Contributor II

Hi Li,

It was needed to be added after the read of the data, like:

unsigned char ReadRegister(unsigned char u8RegisterAddress)

{

unsigned char result;

  /* Send Slave Address */

  IIC_StartTransmission(SlaveID,MWSR);

  i2c_Wait();

  /* Write Register Address */

  I2C0_D = u8RegisterAddress;

  i2c_Wait();

  /* Do a repeated start */

  I2C0_C1 |= I2C_C1_RSTA_MASK;

  /* Send Slave Address */

  I2C0_D = (OV7740_I2C_ADDRESS << 1) | 0x01; //read address

  i2c_Wait();

  /* Put in Rx Mode */

  I2C0_C1 &= (~I2C_C1_TX_MASK);

  /* Turn off ACK since this is second to last byte being read*/

  I2C0_C1 |= I2C_C1_TXAK_MASK;

  /* Dummy read */

  result = I2C0_D ;

  i2c_Wait();

  /* Send stop since about to read last byte */

  i2c_Stop();

  /* Read byte */

  result = I2C0_D ;

/* Wait for the bus to be free */

  while (I2C0_S & I2C_S_BUSY_MASK)

  {}

  return result;

}

where  I2C_S_BUSY_MASK is  0x20u

Hope this helps :smileysilly:

1,404 Views
jonathanlee
Contributor II

Hi,Luis,

Thanks for your reply.

It helps,my program works well now. I add   while (I2C0_S & I2C_S_BUSY_MASK), and send nack.

Thanks again.

Best Regards!

Li

0 Kudos
Reply
1,405 Views
mjbcswitzerland
Specialist V

Luis

Are you sure that the first I2C message transmission has completed (stop condition completed) before sending a second message to a different device?

Try waiting for the bus to become idle before sending the second message - eg.

while (I2C0_S & IIC_IBB) {}

Regards

Mark

0 Kudos
Reply