2022-08-10 1:59 PM
Hello,
I'm currently working with a STM32F411RC chip in a custom board and using I2C to communicate with some peripherals (namely memory and ADCs). I decided to use I2C with DMA, but it wasn't working, so I switched to I2C with interruptions.
My setup is done exactly as in the cube examples. The important part of the code follows:
void I2C_Start(void)
{
// Start I2C hardware.
main_i2c.scl = MCU_InitGPIO(I2C_SCL_PORT, I2C_SCL_PIN, GPIO_Type_AF_OD, GPIO_Speed_Max, GPIO_PuPd_NoPull);
main_i2c.sda = MCU_InitGPIO(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_Type_AF_OD, GPIO_Speed_Max, GPIO_PuPd_NoPull);
MCU_SetGPIOAlternativeFuction(main_i2c.sda, GPIO_Alt_I2C_1);
MCU_SetGPIOAlternativeFuction(main_i2c.scl, GPIO_Alt_I2C_1);
main_i2c.i2c.Instance = I2C1;
main_i2c.i2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
main_i2c.i2c.Init.ClockSpeed = 400000;
main_i2c.i2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
main_i2c.i2c.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
main_i2c.i2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
main_i2c.i2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
main_i2c.i2c.Init.OwnAddress1 = I2C_MASTER_DEVICE_ADDRESS;
main_i2c.i2c.Init.OwnAddress2 = 0xFE;
if(HAL_I2C_Init(&main_i2c.i2c) != HAL_OK)
{
ERROR_Add(ERR_I2C_UNABLE_TO_INITIALIZE);
}
// Set interruption functions
irq_functions_buffer[I2C1_ER_IRQn] = I2C_ERIRQ;
irq_structures_buffer[I2C1_ER_IRQn] = &main_i2c.i2c;
irq_functions_buffer[I2C1_EV_IRQn] = I2C_EVIRQ;
irq_structures_buffer[I2C1_EV_IRQn] = &main_i2c.i2c;
}void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
/* Enable I2C1 clock */
__HAL_RCC_I2C1_CLK_ENABLE();
/*##-5- Configure the NVIC for I2C #########################################*/
/* NVIC for I2C1 */
NVIC_SetPriority(I2C1_ER_IRQn, 1);
NVIC_EnableIRQ(I2C1_ER_IRQn);
NVIC_SetPriority(I2C1_EV_IRQn, 2);
NVIC_EnableIRQ(I2C1_EV_IRQn);
}There is a pull-up of 10kOhms in both SDA and SCL lines. The I2C_ERIRQ and I2C_EVIRQ functions are equal to, respectively, HAL_I2C_ER_IRQHandler and HAL_I2C_EV_IRQHandler.
The I2C initially works fine and the MCU is perfectly capable of communicating with the peripherals. The issue is that, eventually, the I2C gets stuck in the HAL_I2C_STATE_BUSY_TX state. Since i'm using IAR, I can observe the state of the I2C register and the internal object, as follows:
and
The interesting thing is that the registers indicate that a transmission operation is ongoing, but in the internal object XferCount is zero, indicating that everything was transferred. It's like the closing steps never happened (and I checked the interruption with a breakpoint and it is never called).
Just one more bit of information: if I use the blocking I2C functions (with polling), everything works fine.
2022-08-16 5:58 AM
Hi @THML ,
Is I2C_Start() the only location where SCL & SDA lines are configured?
Please make sure that GPIO configuration is done before I2C clock enabling.
-Amel
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.