2022-08-10 01: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 05: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.