AR26
AR26

Reputation: 29

STM32 - I2C in interrupt mode doesn't works

I am using a STM32 board to send I2C commands to a I2C slave using interrupt mode. I have initialized I2C module as below,

  hi2c2.Instance = I2C2;
  hi2c2.Init.Timing = 0x00303D5B;
  hi2c2.Init.OwnAddress1 = 0;
  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c2.Init.OwnAddress2 = 0;
  hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
  {
    Error_Handler();
  }

And for transfer I use the HAL API,

HAL_I2C_Master_Transmit_IT(&hi2c2, 0x60, buffer, 2);

But this code doesn't seem to work for me.

In buffer, first byte is the register address on the I2C slave and second byte is the data. When I use the blocking mode API,

HAL_I2C_Master_Transmit(&hi2c2, 0x60, buffer, 2,HAL_MAX_DELAY);

It works fine. Any suggestions what could be wrong here?

Upvotes: 1

Views: 3913

Answers (3)

MacroController
MacroController

Reputation: 332

The reason your interrupt HAL call doesn't work while your polling one does, is because when using the interrupt, you need to make sure that the bus is ready first. You have to manually do the "timeout" that is embedded in the HAL_MAX_DELAY of the polling HAL call.

Thus:

  1. Polling implementation (that you called correctly):
HAL_I2C_Master_Transmit(&hi2c2, 0x60, buffer, 2, HAL_MAX_DELAY);
  1. Interrupt implementation:
while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY)
{
}
HAL_I2C_Master_Transmit_IT(&hi2c2, 0x60, buffer, 2);

will do the trick.

It also means that without the ready check, your code could work as intended if you call your interrupt HAL at a low enough frequency, because then, the bus is always ready when you need it. This is a pernicious bug: in appearance, your code could function without the check... but only by accident (or luck, depending on how you call it).

Upvotes: 0

das_jasper
das_jasper

Reputation: 1

Take a look at your HAL_I2C_MspInit function and if HAL_NVIC_SetPriority(I2C2_IRQn, 0, 0) and HAL_NVIC_EnableIRQ(I2C2_IRQn) are called.

Upvotes: 0

das_jasper
das_jasper

Reputation: 1

Have you actually enabled the I2C Interrupt? That might be the Problem.

Upvotes: 0

Related Questions