cancel
Showing results for 
Search instead for 
Did you mean: 

I2C communication with I2C_EV interrupts

nanayakkaraan
Associate II
Posted on December 23, 2010 at 10:31

I2C communication with I2C_EV interrupts

7 REPLIES 7
mtaallah
Associate II
Posted on May 17, 2011 at 14:19

Hi,

** These steps should be done before starting I2C communication with Interrupt in main program :

1- Configure I2C :  Fill Init structure with adequate values

  e.g:

      /*!< I2C Struct Initialize */

  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

  I2C_InitStructure.I2C_DutyCycle = I2C_DUTYCYCLE;

  I2C_InitStructure.I2C_OwnAddress1 = 0xA0;

  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

  I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;

  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

2- Call I2c_Init : 

  /*!< I2C Initialize */

  I2C_Init(I2Cx, &I2C_InitStructure);

  /* I2C ENABLE */

  I2C_Cmd(I2Cx, ENABLE);

  

3- Enable Interrupt :

  /* Enable Event and Buffer Interrupts */

  I2C_ITConfig(I2Cx, (I2C_IT_EVT | I2C_IT_BUF), ENABLE);

4- Generate start to start communication:

  /* Generate the Start condition */

  I2C_GenerateSTART(I2Cx, ENABLE);

 

** In stm32l1xx_it.c file you must implement  I2Cx Event IRQHANDLER:

 e.g: how to implement handler for master transmitter :

  void I2C1_EV_IRQHANDLER(void)

   {

      /* Get Last I2C Event */

      Event = I2C_GetLastEvent(I2C1);

   

      switch (Event)

       {

    

        /* Check on EV5 */

        case I2C_EVENT_MASTER_MODE_SELECT :

              /* Send slave Address for write */

              I2C_Send7bitAddress(I2C1, (uint8_t)SLAVE_ADDRESS, I2C_Direction_Transmitter);

        break;

     

     

        /* Check on EV6 */

        case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:

              /* Transmit the First Data  */

              I2C_SendData(I2C1, TxBuffer[Tx_Idx++]);

        break;

     

        /* Check on EV8 */

        case I2C_EVENT_MASTER_BYTE_TRANSMITTING:

              /* Transmit Data TxBuffer */

              I2C_SendData(I2C1, TxBuffer[Tx_Idx++]);

              if (Tx_Idx == (uint8_t)NumberOfByteToTransmit)

              {

                /* Send STOP condition */

                I2C_GenerateSTOP(I2C1, ENABLE);

                /* Disable the Transmit complete interrupt */

                I2C_ITConfig(I2C1, I2C_IT_BUF, DISABLE);;

              }

        break;

     

        default:

        

        break;

       }

   

    }

       

    TxBuffer : is the buffer that contains data to be transmitted

** If you want to handle i2c error you have to enable Error interrupt:*

        /* Enable Error Interrupt */

       I2C_ITConfig(I2Cx, I2C_IT_ERR , ENABLE);

  

   and implement Error IRQHANDLER

  

   void I2Cx_ER_IRQHANDLER(void)

    {    

      /* Read SR1 register to get I2C error */

      if ((I2C_ReadRegister(I2Cx, I2C_Register_SR1) & 0xFF00) != 0x00)

        {          

           /* you can add your code to monitor which error is

           occurred */

          

           /* Clears error flags */

           I2Cx->SR1 &= 0x00FF;

         }

     }

    

END.

    

          

          

          

          

          
nanayakkaraan
Associate II
Posted on May 17, 2011 at 14:19

Thanks for the reply.

Here I am attaching my I2CEV IRQ handler function which does not give me the desired functionality.

What I want is to just read a 8 bit data at the given register address and it does not do that.

void I2C2_EV_IRQHandler(void)

{

 

  // Get Last I2C Event   

  Event = I2C_GetLastEvent(I2C2);

  switch (Event)

  {

  // EV5- 0x00030001 BUSY, MSL and RXNE flags

  case I2C_EVENT_MASTER_MODE_SELECT:

  {

    // Send I2C slave address for write

    I2C_Send7bitAddress(I2C2,I2C_read.u8SlaveAdd ,

                        I2C_read.u8I2CDir);

  }   

  break;  

 

  // EV6 - 0x00070082 BUSY, MSL, ADDR, TXE and TRA flags

  case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:

  {

  }

  break;

 

  // EV6 - 0x00030002 BUSY, MSL and ADDR flags

  case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:

  break;

 

  //EV7 - 0x00030040 BUSY, MSL and RXNE flags

  case I2C_EVENT_MASTER_BYTE_RECEIVED:

  {

      I2C_read.u16Reading = I2C_ReceiveData(I2C2) <<8;

    //Disable Acknowledgement

    I2C_AcknowledgeConfig(I2C2, DISABLE);

    //Generate Stop

    I2C_GenerateSTOP(I2C2,ENABLE);

  }

  break;

  // EV8(EV8_1)- 0x00070080 TRA, BUSY, MSL, TXE flags

  case I2C_EVENT_MASTER_BYTE_TRANSMITTING:

  {

    // Send read register address

    I2C_SendData(I2C2, I2C_read.u8RegAdd);

  } 

  break;

  

  // EV8_2(EV8)- 0x00070084 TRA, BUSY, MSL, TXE and BTF flags

  case I2C_EVENT_MASTER_BYTE_TRANSMITTED:

  {

    I2C_read.u8I2CDir = I2C_Direction_Receiver;

    //Generate a Restart condition

    I2C_GenerateSTART(I2C2,ENABLE);

  }

  default:

  break;

  }

}

Can anybody figure out where I am going wrong/ any idea to proceed with?

Thank you.

mtaallah
Associate II
Posted on May 17, 2011 at 14:19

Hi,

you will find as follow how to read 1byte:

void I2C2_EV_IRQHandler(void)

{

 

  // Get Last I2C Event   

  Event = I2C_GetLastEvent(I2C2);

  switch (Event)

  {

  // EV5- 0x00030001 BUSY, MSL and SB flags

  case I2C_EVENT_MASTER_MODE_SELECT:

  {

    // Send I2C slave address for write

    I2C_Send7bitAddress(I2C2,I2C_read.u8SlaveAdd ,

                        I2C_read.u8I2CDir);

  }   

  break;  

 

  // EV6 - 0x00070082 BUSY, MSL, ADDR, TXE and TRA flags

  case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:

  {

 

  }

  break;

 

  // EV6 - 0x00030002 BUSY, MSL and ADDR flags

  case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:

  {

   //Disable Acknowledgement

    I2C_AcknowledgeConfig(I2C2, DISABLE);

    //Generate Stop

    I2C_GenerateSTOP(I2C2,ENABLE);

  }

  break;

 

  //EV7 - 0x00030040 BUSY, MSL and RXNE flags

  case I2C_EVENT_MASTER_BYTE_RECEIVED:

  {

      I2C_read.u16Reading = I2C_ReceiveData(I2C2) <<8;

  

  }

  break;

  // EV8(EV8_1)- 0x00070080 TRA, BUSY, MSL, TXE flags

  case I2C_EVENT_MASTER_BYTE_TRANSMITTING:

  {

    // Send read register address

    I2C_SendData(I2C2, I2C_read.u8RegAdd);

  } 

  break;

  

  // EV8_2(EV8)- 0x00070084 TRA, BUSY, MSL, TXE and BTF flags

  case I2C_EVENT_MASTER_BYTE_TRANSMITTED:

  {

    I2C_read.u8I2CDir = I2C_Direction_Receiver;

    //Generate a Restart condition

    I2C_GenerateSTART(I2C2,ENABLE);

  }

  default:

  break;

  }

}

nanayakkaraan
Associate II
Posted on May 17, 2011 at 14:19

hello,

Still it does not work :(

As I see by debugging (am checking the value of Event) it is blocked between EV6 - 0x00070082 and EV8(EV8_1)- 0x00070080.

because the Event variable value is 0x00070082 and SR1 and SR 2 values corresponds to 0x00070080 (which means the value of Event at the next run is 0x00070080).

Any suggestion to overcome the issue?

Thank you.

mtaallah
Associate II
Posted on May 17, 2011 at 14:19

I corrected the code.

I made an error in the previous post.

please test with the new code and tell me if it's ok.

void I2C2_EV_IRQHandler(void)

  // Get Last I2C Event   

  Event = I2C_GetLastEvent(I2C2);

  switch (Event)

  {

    // EV5- 0x00030001 BUSY, MSL and SB flags

  case I2C_EVENT_MASTER_MODE_SELECT:

    {

      // Send I2C slave address for write

      I2C_Send7bitAddress(I2C2,I2C_read.u8SlaveAdd ,

                          I2C_read.u8I2CDir);

    }   

    break;  

   

    // EV6 - 0x00070082 BUSY, MSL, ADDR, TXE and TRA flags

  case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:

    {

      // Send read register address

      I2C_SendData(I2C2, I2C_read.u8RegAdd);

    }

    break;

   

    // EV8(EV8_1)- 0x00070080 TRA, BUSY, MSL, TXE flags

  case I2C_EVENT_MASTER_BYTE_TRANSMITTING:

    {

      I2C_read.u8I2CDir = I2C_Direction_Receiver;

      //Generate a Restart condition

      I2C_GenerateSTART(I2C2,ENABLE);

    } 

    break;

   

    // EV6 - 0x00030002 BUSY, MSL and ADDR flags

  case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:

    {

      //Disable Acknowledgement

      I2C_AcknowledgeConfig(I2C2, DISABLE);

      //Generate Stop

      I2C_GenerateSTOP(I2C2,ENABLE);

    }

    break;

   

    //EV7 - 0x00030040 BUSY, MSL and RXNE flags

  case I2C_EVENT_MASTER_BYTE_RECEIVED:

    {

      I2C_read.u16Reading = I2C_ReceiveData(I2C2) <<8;

     

    }

    break;

       

  default:

    break;

  }

}
nanayakkaraan
Associate II
Posted on May 17, 2011 at 14:19

Hello,

Still it doesnot read.

Same problem persist :(

nanayakkaraan
Associate II
Posted on May 17, 2011 at 14:19

Hello all,

I will be glad if somebody can help me.

When my I2C_Ev ISR is the following I2C data can be read.

///////////////////////////////////////////////////////////////////////////////////////

void I2C2_EV_IRQHandler(void)

{

 

  //Disable I2CEV interrupts

  I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE);

 

   // Get Last I2C Event   

  Event = I2C_GetLastEvent(I2C2);

   //EV5- 0x00030001 BUSY, MSL and RXNE flags 

  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))

  {

  }

  //Send I2C slave address for write

  I2C_Send7bitAddress(I2C2,I2C_read.u8SlaveAdd ,I2C_read.u8I2CDir);

  //EV6 - 0x00070082 BUSY, MSL, ADDR, TXE and TRA flags

   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

  {

  }

 

  //EV8(EV8_1)- 0x00070080 TRA, BUSY, MSL, TXE flags

  while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING ))

  {

  }

 

  //Send read register address

  I2C_SendData(I2C2, I2C_read.u8RegAdd);

 

  //EV8_2(EV8)- 0x00070084 TRA, BUSY, MSL, TXE and BTF flags

   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED))

  {

  }

 

  //Reception

   I2C_read.u8I2CDir = I2C_Direction_Receiver;

 

  //Generate a Restart condition

  I2C_GenerateSTART(I2C2,ENABLE);

 

  //EV5- 0x00030001 BUSY, MSL and RXNE flags

  while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT))

  {

  }

 

  //Send I2C slave address for read

  I2C_Send7bitAddress(I2C2,I2C_read.u8SlaveAdd ,I2C_read.u8I2CDir);

 

  //EV6 - 0x00030002 BUSY, MSL and ADDR flags

  while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))

  {

  } 

 

  //EV7 - 0x00030040 BUSY, MSL and RXNE flags

  while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED))

  {

  }

  I2C_read.u16Reading = I2C_ReceiveData(I2C2) <<8;

 

  //Disable Acknowledgement

  I2C_AcknowledgeConfig(I2C2, DISABLE);

  //Generate Stop

  I2C_GenerateSTOP(I2C2,ENABLE);

    while(!(I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE)))

  {}

  I2C_read.u16Reading |= I2C_ReceiveData(I2C2);

}

/////////////////////////////////////////////////////////////////////////////////////////////////////

but if I change the I2C_EV ISR to the following it does not work.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void I2C2_EV_IRQHandler(void)

{

  // Get Last I2C Event   

  Event = I2C_GetLastEvent(I2C2);

  switch (Event)

  {

  // EV5- 0x00030001 BUSY, MSL and RXNE flags

  case I2C_EVENT_MASTER_MODE_SELECT:

  { 

    // Send I2C slave address for write

    I2C_Send7bitAddress(I2C2,I2C_read.u8SlaveAdd ,

                        I2C_read.u8I2CDir);

  }   

  break;  

 

  // EV6 - 0x00070082 BUSY, MSL, ADDR, TXE and TRA flags

  case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:

  {

    // Send read register address

    I2C_SendData(I2C2, I2C_read.u8RegAdd);

  }

  break;

 

  // EV6 - 0x00030002 BUSY, MSL and ADDR flags

  case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:

  break;

 

  //EV7 - 0x00030040 BUSY, MSL and RXNE flags

  case I2C_EVENT_MASTER_BYTE_RECEIVED:

  {

    I2C_read.u16Reading = I2C_ReceiveData(I2C2) <<8;

    //Disable Acknowledgement

    I2C_AcknowledgeConfig(I2C2, DISABLE);

    //Generate Stop

    I2C_GenerateSTOP(I2C2,ENABLE);

    while(!(I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE)))

    {}

    I2C_read.u16Reading |= I2C_ReceiveData(I2C2);

 

  }

  break;

  // EV8(EV8_1)- 0x00070080 TRA, BUSY, MSL, TXE flags

  case I2C_EVENT_MASTER_BYTE_TRANSMITTING:

  {

   } 

  break;

  

  // EV8_2(EV8)- 0x00070084 TRA, BUSY, MSL, TXE and BTF flags

  case I2C_EVENT_MASTER_BYTE_TRANSMITTED:

  {

    I2C_read.u8I2CDir = I2C_Direction_Receiver;

    //Generate a Restart condition

    I2C_GenerateSTART(I2C2,ENABLE);

  }

  break;

  default:

  break;

  }

}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

In the second case I am expecting to get the I2C_EV interrupt at each time events are occurring. As I notice only EV5 and EV 6 are captured and after that it gets trapped in somewhere in between EV6 and EV8_1.

As I understood both implementation are same.

When looking into St library files, both I2C_CheckEvent() and I2C_GetLastEvent() function has similar implementation.

If possible please let me know where I am going wrong and how to overcome this cumbersome issue.

Thank you.