2025-03-24 2:39 AM
Hi All,
I am integrating the IMU sensor Using I2C DMA in circular mode on stm32f103c8t6 using Hal Library, so facing an issue reading the address value.
In the below code "HAL_I2C_STATE_READY " this flag is not resetting after once function executes so in 2nd execution this HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) function is not trigering to DMA Handler function.
if (hi2c->State == HAL_I2C_STATE_READY)
{
/* Wait until BUSY flag is reset */
count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U);
do
{
count--;
if (count == 0U)
{
hi2c->PreviousState = I2C_STATE_NONE;
hi2c->State = HAL_I2C_STATE_READY;
hi2c->Mode = HAL_I2C_MODE_NONE;
hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
return HAL_BUSY;
}
}
while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET);
/* Process Locked */
__HAL_LOCK(hi2c);
/* Check if the I2C is already enabled */
if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE)
{
/* Enable I2C peripheral */
__HAL_I2C_ENABLE(hi2c);
}
/* Disable Pos */
CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS);
hi2c->State = HAL_I2C_STATE_BUSY_RX;
hi2c->Mode = HAL_I2C_MODE_MEM;
hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
/* Prepare transfer parameters */
hi2c->pBuffPtr = pData;
hi2c->XferCount = Size;
hi2c->XferSize = hi2c->XferCount;
hi2c->XferOptions = I2C_NO_OPTION_FRAME;
hi2c->Devaddress = DevAddress;
hi2c->Memaddress = MemAddress;
hi2c->MemaddSize = MemAddSize;
hi2c->EventCount = 0U;
/* Enable Acknowledge */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK);
/* Generate Start */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_START);
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
if (hi2c->XferSize > 0U)
{
/* Note : The I2C interrupts must be enabled after unlocking current process
to avoid the risk of I2C interrupt handle execution before current
process unlock */
/* Enable EVT, BUF and ERR interrupt */
__HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR);
}
return HAL_OK;
}
2025-03-24 5:57 AM
How are you calling the HAL functions and what you're expecting to happen?
2025-03-26 12:41 AM
Hello @Piyoosh
The HAL_I2C_STATE_READY flag is not reset immediately after the execution of HAL_I2C_Mem_Read_DMA(). Instead, the state remains busy until the transfer is complete. The end of the transfer is indicated by the invocation of the HAL_I2C_MemRxCpltCallback() function. To ensure that a subsequent transfer can be initiated successfully, you can either call the next transfer within the callback function or set a flag within this function and check it in the main loop before initiating the second transfer.
Please refer to the implementation in the code snippet below:
volatile uint8_t transferCompleteFlag = 0;
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) {
// Set the flag to indicate the transfer is complete
transferCompleteFlag = 1;
}
void I2C_Read_DMA(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
// Start the I2C memory read using DMA
if (HAL_I2C_Mem_Read_DMA(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size) != HAL_OK) {
// Handle error
}
}
int main(void) {
// HAL initialization
HAL_Init();
// System clock configuration
SystemClock_Config();
// I2C initialization
MX_I2C1_Init();
uint8_t data[10];
uint16_t deviceAddress = 0x50;
uint16_t memoryAddress = 0x00;
// First I2C read transfer
I2C_Read_DMA(deviceAddress, memoryAddress, data, sizeof(data));
// Wait for the first transfer to complete
while (transferCompleteFlag == 0) {
// Optionally, you can add a timeout mechanism here
}
// Reset the flag for the next transfer
transferCompleteFlag = 0;
// Second I2C read transfer
I2C_Read_DMA(deviceAddress, memoryAddress + 10, data, sizeof(data));
// Main loop
while (1) {
// Application code
}
}