cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F030 I2C1 interrupt not firing

Posted on November 09, 2016 at 15:50

Hi,

I'm trying to move my I2C1 code over from polling based functions to interrupt based(we use the standard peripheral libs.) I must be missing some basic configuration as the interrupt will not fire. The code below shows my configuration and I2C transmit/IRQ functionality. Am I missing a config piece or maybe an configuration ordering issue? Thanks, John C.

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// I2C1 channel init. LCD and EEPROM chip are on this bus.
I2C_DeInit(I2C1);
I2C_StructInit(&I2C_InitStruct);
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter = 0;
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_OwnAddress1 = 0;
//I2C_InitStruct.I2C_Timing = 0xB0420F13; // 100Khz I2C clock with main @ 48Mhz
I2C_InitStruct.I2C_Timing = 0x50330309; // 400Khz I2C clock with main @ 48Mhz
I2C_Init(I2C1, &I2C_InitStruct);
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_EnableIRQ(I2C1_IRQn);
NVIC_SetPriority(I2C1_IRQn,0);
// Start of I2C transmit
I2C_ITConfig(I2C1, I2C_IT_TCI, ENABLE);
// I have tried each of these and none seem to get the interrupt to fire.
I2C_TransferHandling(I2C1, 0x7C, SendCnt, I2C_Reload_Mode, I2C_Generate_Start_Write);
I2C_TransferHandling(I2C1, 0x7C, SendCnt, I2C_Reload_Mode, I2C_Generate_Start_Write);
I2C_TransferHandling(I2C1, 0x7C, SendCnt, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);
I2C_TransferHandling(I2C1, 0x7C, SendCnt, I2C_AutoEnd_Mode, I2C_Generate_Stop);
void __attribute__((optimize(''O0''))) I2C1_IRQHandler(void)
{
// See if we have received a Transmit complete
if(I2C_GetITStatus(I2C1, I2C_IT_TCR) != RESET)
{
}
}

7 REPLIES 7
Posted on November 09, 2016 at 16:39

I forgot to add the pin init code. When the transmit is started with the call to I2C_TransferHandling(), the I2C1-.ISR register shows the BUSY and TXIS flags going on. The TXIS(transmit interrupt status) flag means that ''This bit is set by hardware when the I2C_TXDR register is empty and the data to be transmitted must be written in the I2C_TXDR register''. Why would this not cause the interrupt to fire? I've tried using the reload mode and thought that when data is needed it would fire the interrupt with the TCR flag.

John C.

GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_1);
GPIO_InitStructure.GPIO_Pin = SCL1 | SDA1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);

Posted on November 09, 2016 at 16:52

What is the state of the individual interrupt enable bits in I2C_CR1 (the bits ending with ''IE'', i.e. bits 1..7)?

JW
Posted on November 09, 2016 at 17:14

Hey JW,

     The I2C1 CR1 shows the PE and TCIE bits on(nothing else.) If I modify the interrupt config call to include the TXI(transmit interrupt) then the interrupt does fire, but it will fire after the transfer is complete as well(which is why I only wanted to use the transfer complete/reload interrupt.) So the interrupt will work, I just need to figure out the proper configuration so that I only get the TC interrupt.

John C.

   I2C_ITConfig(I2C1, I2C_IT_TCI | I2C_IT_TXI, ENABLE);

Posted on November 09, 2016 at 18:30

If I turn on the TXI interrupt I end up getting two interrupts where I can transmit my 2 bytes of data. After the second transmit I no longer get any interrupts. I can see the STOPF bit being set in the I2C1->ISR register. I thought with I2C autoend mode the stop would be auto generated and if that is true then why no TC interrupt? I keep reading the reference manual, but I don't find anything.

John C.

I2C_ITConfig(I2C1, I2C_IT_TCI | I2C_IT_TXI, ENABLE);
I2C_TransferHandling(I2C1, 0x7C, SendCnt, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);

Posted on November 10, 2016 at 02:06

> I thought with I2C autoend mode the stop would be auto generated and if that is true then why no TC interrupt? I keep reading the reference manual, but I don't find anything.

RM0091 rev.8, 25.7.7  Interrupt and status register (I2C_ISR)

Bit 6 TC: Transfer Complete (master mode)

 

This flag is set by hardware when RELOAD=0, AUTOEND=0 and NBYTES data have beentransferred.
Posted on November 10, 2016 at 14:58

Now that I begin to understand this processor a bit more the small notes in the reference manual make sense. The issue I have is that I can't use autoend mode and know when the transmission is complete. If I leave autoend off, then I will get a TC, but then I need to transmit the I2C stop. I will then have to look at maybe the TXE bit to see if the stop transmission is complete. Are there any better solutions?

Thanks,

     John C.

Posted on November 10, 2016 at 16:13

> Are there any better solutions?

I am quite confident that they are, but sorry, I don't use the 'F0x. The I2C module in 'F4 which I'm primarily using is an older generation and simpler one, no autoend there.

JW