带有 DMA 的 STM32 I2C 传输已完成,但 DMA 中断程序不工作

Posted

技术标签:

【中文标题】带有 DMA 的 STM32 I2C 传输已完成,但 DMA 中断程序不工作【英文标题】:STM32 I2C Transfer with DMA completed but DMA interrupt routine is not work 【发布时间】:2021-10-31 18:30:15 【问题描述】:

我使用 HAL 库处理带有 DMA 的基本 i2c 示例。当我在调试部分观察到数据读取正确但 DMA 没有上升标志 TCIF(传输完成标志)时。可能是什么原因?

// INTERRUPT ROUTINE
    void DMA1_Channel1_IRQHandler(void) 
    if(__HAL_DMA_GET_FLAG(&hdma_i2c2_rx,DMA_FLAG_TC1))
    HAL_GPIO_TogglePin(LED_COM_BLUE_GPIO_Port, LED_COM_BLUE_Pin);
    sprintf(prnt, "Id:%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\r", Id[7], Id[6],
    Id[5], Id[4], Id[3], Id[2], Id[1], Id[0]);
    HAL_UART_Transmit(&huart1, (uint8_t*) prnt, strlen(prnt), 1000);
    __HAL_DMA_CLEAR_FLAG(&hdma_i2c2_rx,DMA_FLAG_TC1);
    
    

【问题讨论】:

【参考方案1】:

如果你想使用 HAL,你应该让 HAL 处理 IRQ 并且只使用预定义的回调。

在 'stm32fyxx_hal_i2c.h' 中寻找它们:

/******* I2C IRQHandler and Callbacks used in non blocking modes 
(Interrupt and DMA) */
void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c);
void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode);
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c);

如果你不使用 CubeMX,一定要检查 'stm32fyxx_it.c',你应该有类似的东西:

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 stream 
  *         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 stream 
  *         used for I2C data reception    
  */
void I2Cx_DMA_TX_IRQHandler(void)

  HAL_DMA_IRQHandler(I2cHandle.hdmatx);

如果不这样做,请检查 CubeMX 中针对 I2C 和 DMA 的所有 NVIC 选项,它将创建这些行,然后回调函数应该可以工作。

如果您想使用这些“低级”标志,我建议您不要使用 HAL 以确保完全控制它们。

您也可以使用 LL(低级)库。

【讨论】:

以上是关于带有 DMA 的 STM32 I2C 传输已完成,但 DMA 中断程序不工作的主要内容,如果未能解决你的问题,请参考以下文章

stm32dma填入的内容怎么修改

关于STM32的I2C硬件DMA实现

为啥说stm32 的i2c鸡肋

spidma发送更新中断

DMA+USART+stm32

STM32F7:ADC DMA 传输只工作一次