2010-12-23 01:31 AM
I2C communication with I2C_EV interrupts
2011-05-17 05:19 AM
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.2011-05-17 05:19 AM
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.2011-05-17 05:19 AM
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; } }2011-05-17 05:19 AM
2011-05-17 05:19 AM
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; } }2011-05-17 05:19 AM
Hello,
Still it doesnot read. Same problem persist :(2011-05-17 05:19 AM
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.