2025-04-07 10:47 PM
Hello Community, Am interfacing LIS2DTW12 Acceleration Sensor with STM NucleoL476RGT6U by I2C communication protocal in blocking mode working everything fine. But i want collect data in non blocking mode so collecting data to DMA and implementing the custom callback but control not coming to custom call back (custom callback was not triggered ) if i stop the program data will present in the Data array .
While Debugging DMA transfer complete interrupt triggered succesfully when going to handle DMA_IRQ Handler during that time am check the I2C state thats still HAL_I2C_STATE_BUSY_RX Whats the issue ?
if i forcefully Change the I2C state to ready and forcefully call the custom implemented callback then it will work .May i know Whats happening whats the issue is from hardware side or software ?Anyone helpme to resolve this ....
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
SensorLIS2DTW12Acc_init();
start_dma_read();
void SensorLIS2DTW12Acc_init(void) {
// Read the WHO_AM_I register to verify communication with the LIS2DTW12
Ret = HAL_I2C_Mem_Read(&hi2c1, SLAVE_ADDR_LIS2DTW12, LIS2DTW12_WHO_AM_I, I2C_MEMADD_SIZE_8BIT, ®_data, 1, HAL_MAX_DELAY);
ctrl1Data = LIS2DTW12_ODR_HP_MODE;
HAL_I2C_Mem_Write(&hi2c1, SLAVE_ADDR_LIS2DTW12, LIS2DTW12_CTRL1, I2C_MEMADD_SIZE_8BIT, &ctrl1Data, 1, HAL_MAX_DELAY);
ctrl6Data = g_Selection;
HAL_I2C_Mem_Write(&hi2c1, SLAVE_ADDR_LIS2DTW12, LIS2DTW12_CTRL6, I2C_MEMADD_SIZE_8BIT, &ctrl6Data, 1, HAL_MAX_DELAY);
fifoctrl = LIS2DTW12_CONTI_MODE_FTH_LEVEL;
HAL_I2C_Mem_Write(&hi2c1, SLAVE_ADDR_LIS2DTW12, LIS2DTW12_FIFO_CTRL, I2C_MEMADD_SIZE_8BIT, &fifoctrl, 1, HAL_MAX_DELAY);
}
void start_dma_read(void) {
// Send the register address to read from (OUT_X_L)
if (HAL_I2C_Master_Transmit(&hi2c1, SLAVE_ADDR_LIS2DTW12, ®_addr, 1, HAL_MAX_DELAY) == HAL_OK) {
// Start DMA reception (6 bytes for X, Y, Z)
if (HAL_I2C_Master_Receive_DMA(&hi2c1, SLAVE_ADDR_LIS2DTW12, accel_data, sizeof(accel_data)) == HAL_OK) {
} }}
Control stuck inside of bellow program .....
/* Transfer Complete Interrupt management ***********************************/
else if (((flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_TC) != 0U))
{
// printf("DMA TC Interrupt, I2C State: 0x%X\n", hi2c1.State);
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
/* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
/* Disable the transfer complete and error interrupt */
/* if the DMA mode is not CIRCULAR */
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
}
/* Clear the transfer complete flag */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1CU));
/* Process Unlocked */
__HAL_UNLOCK(hdma);
if (hdma->XferCpltCallback != NULL)
{
printf("Calling XferCpltCallback: %p\n", hdma->XferCpltCallback);
hi2c1.XferCount = 0; // Force XferCount to 0
/* Transfer complete callback */
hdma->XferCpltCallback(hdma);
hi2c1.Instance->CR2 |= I2C_CR2_STOP; // These lines of codes are inserted manually to check?
while (hi2c1.Instance->ISR & I2C_ISR_BUSY);
hi2c1.Instance->ICR = I2C_ICR_STOPCF;
hi2c1.State = HAL_I2C_STATE_READY;
HAL_I2C_MasterRxCpltCallback(&hi2c1); // Forced callback
}
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) {
if (hi2c->Instance == I2C1) {
dmaTransferComplete = 1;
printf("Rx Callback! State: 0x%X, Error: 0x%lX\n", hi2c->State, hi2c->ErrorCode);
int16_t x = (int16_t)(accel_data[1] << 8 | accel_data[0]);
printf("X: %d\n", x);
hi2c->State = HAL_I2C_STATE_READY; // Ensure state is reset
start_dma_read();
}
}
Solved! Go to Solution.
2025-04-11 4:10 AM
Hello,
When you use DMA with I2C to Transmit or Receive data, you should
Enable I2Cx_ER_IRQn and I2Cx_EV_IRQn interrupts.
because they all called I2C_DMAXferCplt (hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt)
and it enable interrupt call to handle I2C state.
__HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR);
This is the solution for my prolem . Before i Didn't Enabled the I2Cx_ER_IRQn and I2Cx_EV_IRQn interrupts so my callback function was not triggering After enabling these 2 interrupts now triggering .
2025-04-11 4:10 AM
Hello,
When you use DMA with I2C to Transmit or Receive data, you should
Enable I2Cx_ER_IRQn and I2Cx_EV_IRQn interrupts.
because they all called I2C_DMAXferCplt (hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt)
and it enable interrupt call to handle I2C state.
__HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR);
This is the solution for my prolem . Before i Didn't Enabled the I2Cx_ER_IRQn and I2Cx_EV_IRQn interrupts so my callback function was not triggering After enabling these 2 interrupts now triggering .