cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 I2C only transmits and receives once

HamzaBeder
Associate

MCU: STM32L476RGT6

Hello,

I am able to communicate with the MPU6050 via I2C with DMA and read the WHO_AM_I register, but only one transmit and receive transaction occurs even though I put my transmission and receive code in a while loop.

When using regular I2C transmission (no DMA), multiple transactions are performed (as expected). This tells me that there may be some flags I need to reset or functions I need to call between transmission. However, when comparing my code to this example, I could not tell what I was missing.

My code is getting stuck on line 61 here. That tells me that an internal process is occurring, so the MCU is never ready for another transmission.

Below is my driver code. What am I missing?

Thanks.

#define MPU6050ADDR 0b11010010
int main(void)
{
uint8_t WHO_AM_I[1] = {0x75};
HAL_Init();
SystemClock_Config();
I2C_Init();
DMA_Init();
while (1)
{
if(HAL_I2C_Master_Transmit_DMA(&hI2C, MPU6050ADDR, WHO_AM_I, 1,100) != HAL_OK)
Error_Handler();
while (HAL_I2C_GetState(&hI2C) != HAL_I2C_STATE_READY);
while(HAL_I2C_GetError(&hI2C) == HAL_I2C_ERROR_AF);
if(HAL_I2C_Master_Receive_DMA(&hI2C, MPU6050ADDR, Buffer_Dest,1,100) != HAL_OK)
Error_Handler();
while (HAL_I2C_GetState(&hI2C) != HAL_I2C_STATE_READY);
while(HAL_I2C_GetError(&hI2C) == HAL_I2C_ERROR_AF); }
}

 

2 REPLIES 2
Saket_Om
ST Employee

Hello @HamzaBeder 

 

I recommend referring to the I2C example available in the STM32CubeL4 firmware package instead of the STM32F0 example.

The STM32L4 series provides distinct interrupt handler for I2C events and errors, as well as for I2C DMA TX and RX.

/**
  * @brief  This function handles I2C event interrupt request.
  * @param  None
  * @retval None
  * @Note   This function is redefined in "main.h" and related to I2C data transmission
  */
void I2Cx_EV_IRQHandler(void)
{
  HAL_I2C_EV_IRQHandler(&I2cHandle);
}

/**
  * @brief  This function handles I2C error interrupt request.
  * @param  None
  * @retval None
  * @Note   This function is redefined in "main.h" and related to I2C error
  */
void I2Cx_ER_IRQHandler(void)
{
  HAL_I2C_ER_IRQHandler(&I2cHandle);
}

/**
  * @brief  This function handles DMA interrupt request.
  * @param  None
  * @retval None
  * @Note   This function is redefined in "main.h" and related to DMA Channel 
  *         used for I2C data transmission     
  */
void I2Cx_DMA_RX_IRQHandler(void)
{
  HAL_DMA_IRQHandler(I2cHandle.hdmarx);
}

/**
  * @brief  This function handles DMA interrupt request.
  * @param  None
  * @retval None
  * @Note   This function is redefined in "main.h" and related to DMA Channel 
  *         used for I2C data reception    
  */
void I2Cx_DMA_TX_IRQHandler(void)
{
  HAL_DMA_IRQHandler(I2cHandle.hdmatx);
}

 

Please review the example and update your implementation accordingly. If you have any further questions or need additional assistance, feel free to ask.

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar
Techn
Senior III

you can set a flag in the RxCpltCallback and check this flag in the while(1) of main, so that you dont call the DMA immediately after a DMA call. DMA call returns immediately and making further calls will create error. in the below example I have used a flag for the DMA receive, and DMA transmit is  blocking type. you can extend this idea if you want to transmit also in DMA.

 

void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
dmaCompleteFlag = 1;
}

 

in your while(1)

if ( dmaCompleteFlag)
{
dmaCompleteFlag = 0;

if(HAL_I2C_Master_Transmit(&hI2C, MPU6050ADDR, WHO_AM_I, 1,100) != HAL_OK)
Error_Handler();
while (HAL_I2C_GetState(&hI2C) != HAL_I2C_STATE_READY);
while(HAL_I2C_GetError(&hI2C) == HAL_I2C_ERROR_AF);
if(HAL_I2C_Master_Receive_DMA(&hI2C, MPU6050ADDR, Buffer_Dest,1,100) != HAL_OK)
Error_Handler();
while (HAL_I2C_GetState(&hI2C) != HAL_I2C_STATE_READY);
while(HAL_I2C_GetError(&hI2C) == HAL_I2C_ERROR_AF); }
}

 

If you feel a post has answered your question, please click "Accept as Solution".