cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with I2Cx_EV_IRQHandler called way too frequent

kennethf
Associate II
Posted on June 18, 2014 at 11:17

Hi, I am new to this forum and to using the STM32 processors, so please forgive me if this topic has already been discussed. 

I am using a Discovery board with a STM32L152RC micro-processor on. I am trying to implement the I2C2 as a slave for a GUI I am using. The I2C interface itself is working, but it seems to stop the main loop from running. 

By debugging I can see that the SB bit is set over and over, thus calling the I2C2_EV_IRQHandler again and again even though my I2C port should be a slave and not a master. 

The SB bit should only be set when I create a Start condition, so why is it set again and again when the I2C is in slave mode? The interrupt should only be called if the I2C interface detects an address match. 

void MX_I2C_Init(void)

{

GPIO_InitTypeDef GPIO_InitStruct;

I2C_InitTypeDef  I2C_InitStructure;

  /** I2C1 GPIO Configuration (Master) 

  PB8   ------> I2C1_SCL

  PB9   ------> I2C1_SDA

** I2C2 GPIO Configuration (Slave)

  PB10   ------> I2C2_SCL

  PB11   ------> I2C2_SDA

  */

  /*Enable or disable the AHB peripheral clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // Enable GPIO peripheral clock

  /*Configure GPIO pin : PB */

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // set pins to alternative function

  GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; // Setup as open-drain if used as output

  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // No internal pull-up/down resistor

  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; // For fast mode, use 10MHz

  GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin alternate function */

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1); // Alternative function I2C1

  /*Configure GPIO pin alternate function */

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); // Alternative function I2C1

/*Configure GPIO pin alternate function */

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2); // Alternative function I2C2

  /*Configure GPIO pin alternate function */

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2); // Alternative function I2C2

  // I2C1 clock enable

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // Enable peripheral clock I2C1

  RCC_AHBPeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // Enable peripheral clock I2C1

// I2C2 clock enable

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); // Enable peripheral clock I2C2

  RCC_AHBPeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); // Enable peripheral clock I2C2

I2C_DeInit(I2C1); // Important to reset I2C after clock enabled

I2C_DeInit(I2C2); // Important to reset I2C after clock enabled

  I2C_InitStructure.I2C_ClockSpeed = 200000; // I2C clockspeed 200 kHz

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // Alternative function I2C mode

  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // Duty Cycle 50%

  I2C_InitStructure.I2C_OwnAddress1 = 0x00; // Own address, not relevant in Master mode

  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // Acknoledge enabled

  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7 bit address

I2C_Init(I2C1, &I2C_InitStructure); // Init I2C1

I2C_InitStructure.I2C_OwnAddress1 = TIA_Address; // Address 0x60, (remember to shift address left by one bit = 0xC0)

I2C_Init(I2C2, &I2C_InitStructure); // Init I2C2

I2C_StretchClockCmd(I2C1,ENABLE); // Enable clock streching

I2C_StretchClockCmd(I2C2,ENABLE); // Enable clock streching

I2C_OwnAddress2Config(I2C2,Driver_Address); // Set I2C2 address2 to 0x68, (remember to shift address left by one bit = 0xD0)

I2C_Cmd(I2C1, ENABLE); // Enable I2C1 peripheral

I2C_Cmd(I2C2, ENABLE); // Enable I2C2 peripheral

}

int main(void)

{

  MX_GPIO_Init();

MX_I2C_Init();

MX_Timer_Init();

  SystemCoreClockUpdate();                       // Get Core Clock Frequency   

  if (SysTick_Configuration(SystemCoreClock / 1000)) { // SysTick 1 msec interrupts  

    while (1);                                   // Capture error              

  }

I2C_ITConfig(I2C2, (I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF ), ENABLE);

NVIC_EnableIRQ(I2C2_EV_IRQn);

NVIC_EnableIRQ(I2C2_ER_IRQn);

  while (1)

  {

GPIO_SetBits(GPIOB,GPIO_Pin_6);  

Delay(100);

GPIO_ResetBits(GPIOB,GPIO_Pin_6);

Delay(100);

  }

}

The code runs until I enable the NVIC_EnableIRQ(I2C2_EV_IRQn), then it seems to jump instantly to the interrupt and just go around and around in the I2C2_EV_IRQHandler, never to continue to the while(1) loop in the main().

Any suggestions would be greatly appreciated. 
1 REPLY 1
kennethf
Associate II
Posted on June 18, 2014 at 12:33

Never mind, I solved it myself. Turned out it had nothing to do with the SB bit, it was the AF bit that was set when the master did not ACK on a read. Clearing the AF bit made it work.