Hardware : STM32L452RET6

Software : STM32CubeFW_L4 v1.17

My problem : After using I2C with standard polling functions, i would like to use IT Functions to optimize my firmware. I try to work with HAL_I2C_Master_Transmit_IT & HAL_I2C_Master_Receive_IT but my firmware stay blocked in the I2C1_EV_IRQHandler :

void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c)
  /* Get current IT Flags and IT sources value */
  uint32_t itflags   = READ_REG(hi2c->Instance->ISR);
  uint32_t itsources = READ_REG(hi2c->Instance->CR1);

  /* I2C events treatment -------------------------------------*/
  if (hi2c->XferISR != NULL)
    hi2c->XferISR(hi2c, itflags, itsources);

The IT flags seems not to be cleared and the hi2c->XferISR register seems to be NULL : enter image description here

enter image description here

Edit 1 : Some additional informations : The following functions are never called.

void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)

void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)

void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) 

I tried to clear I2C_FLAG_TXE & I2C_FLAG_TXIS but it's seems not possible.

Edit 2 : To answer some questions in comment :

The init code is well passed :

Status I2C_Init(I2C_HandleTypeDef *hi2c)
    // Peripheral Clock Enable

    hi2c->Instance = I2C1;
    hi2c->Init.Timing = 0x10909CEC;
    hi2c->Init.OwnAddress1 = 0;
    hi2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    hi2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c->Init.OwnAddress2 = 0;
    hi2c->Init.OwnAddress2Masks = I2C_OA2_NOMASK;
    hi2c->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    hi2c->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

    // Interrupts Activation
    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);

    if (HAL_I2C_Init(hi2c) != HAL_OK)
        return STATUS_ERROR;

    return STATUS_OK;

There is no bus activity on scope.

  • 1
    \$\begingroup\$ How have you initialized the I2C? Did you write init code yourself or did you let CubeIDE/CubeMX generate initial code for you? \$\endgroup\$
    – Justme
    Sep 6, 2021 at 14:54
  • \$\begingroup\$ Is the slave responding correct? \$\endgroup\$
    – jay
    Sep 6, 2021 at 16:05
  • \$\begingroup\$ @jay That would be unknown, since the ISR is null, so the code would not even go that far to know if any slave is on the bus. \$\endgroup\$
    – Justme
    Sep 6, 2021 at 17:54
  • \$\begingroup\$ TXE sounds like TX empty. Meantime TXIS is used for slave mode. Read the reference manual. \$\endgroup\$
    – jay
    Sep 6, 2021 at 23:23
  • \$\begingroup\$ p1127, I2C_TXDR register is not empty. p1141, Slave transmitter A transmit interrupt status (TXIS) is generated when the I2C_TXDR register becomes empty. An interrupt is generated if the TXIE bit is set in the I2C_CR1 register. The TXIS bit is cleared when the I2C_TXDR register is written with the next data byte to be transmitted. \$\endgroup\$
    – jay
    Sep 6, 2021 at 23:24

1 Answer 1


Ok i found the source of my problem :

I have three steps to drive the I2C :

  1. My main function drive a peripheral one : VL53L0X_Init(...);
  2. My peripheral function drive a register one : I2C_WriteRegister(...);
  3. My register function use HAL_I2C_Master_Transmit_IT(...);

On the first one : I give a pointer on I2C Structure when it is received i saved this pointer with : *I2C = hi2c;

I2C is the global variable contained in the peripheral file : I2C_HandleTypeDef I2C.

My error here is to affect the pointer to the variable. The solution is to declare a pointer and to copy the I2C structure pointer to it during the init :

I2C_HandleTypeDef *I2C;

I2C_HandleTypeDef *hi2c;

I2C = hi2c;


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.