前言
使用HAL库方式DMA中断时,在网上找了好多资料都没有怎么介绍。所以就自己研究了一下,并做个记录。我的芯片型号是STM32G030。下面我以I2C传数据为例介绍下HAL库是如何使用DMA中断的。
MXCUBE配置
我使用的是I2C2,简单配置下参数,加上DMA通道。
DMA貌似默认开启了中断,蓝色的勾勾是我自己勾上的,没有用到I2C的中断不勾也可以。
DMA初始化
打开工程后主函数里有个MX_DMA_Init();它的内部就是开启DMA的RCC和NVIC,这里就不放图了。
I2C初始化
打开这个文件的第一眼,看到最上端的全局变量hdma_i2c2_rx和hdma_i2c2_tx,实际上DMA的初始化我更感觉是放在这里的。
I2C_HandleTypeDef hi2c2;
DMA_HandleTypeDef hdma_i2c2_rx;
DMA_HandleTypeDef hdma_i2c2_tx;
I2C的初始化我直接略过,和只用I2C通讯配置没区别。拉到最下边的函数HAL_I2C_MspInit
/* I2C2 DMA Init */
/* I2C2_RX Init */
hdma_i2c2_rx.Instance = DMA1_Channel1;
hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX;
hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c2_rx.Init.Mode = DMA_NORMAL;
hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_i2c2_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c2_rx);
/* I2C2_TX Init */
hdma_i2c2_tx.Instance = DMA1_Channel2;
hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX;
hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c2_tx.Init.Mode = DMA_NORMAL;
hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_i2c2_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c2_tx);
这里实际上跟I2C+DMA通信也没什么区别。
I2C+DMA+中断通信过程
在我看了他的驱动函数后,我发现只要是后缀带有DMA的函数,都自动有DMA中断的处理过程。有这几个函数:
- HAL_I2C_Mem_Write_DMA
- HAL_I2C_Master_Receive_DMA
- HAL_I2C_Master_Seq_Receive_DMA
- HAL_I2C_Master_Seq_Transmit_DMA
- HAL_I2C_Master_Transmit_DMA
- HAL_I2C_Mem_Read_DMA
- HAL_I2C_Mem_Write_DMA
- HAL_I2C_Slave_Receive_DMA
…
我随便点开一个HAL_I2C_Mem_Write_DMA,这几个都是差不多,只是用途不一样,带Mem的方便与EEPROM类似的通讯,他需要发从机的设备地址和内存地址,就可以用这个。
在该函数内我只列出我觉得重要的代码,
-
hi2c->XferISR用于绑定中断处理函数
hi2c->XferISR = I2C_Master_ISR_DMA;
-
这里dma绑定了相关的传输处理函数,传输完成和传输错误,然后开启DMA的中断使能,当传输完成后就会进入I2C_DMAMasterTransmitCplt。
if (hi2c->hdmatx != NULL) { /* Set the I2C DMA transfer complete callback */ hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt; /* Set the DMA error callback */ hi2c->hdmatx->XferErrorCallback = I2C_DMAError; /* Set the unused DMA callbacks to NULL */ hi2c->hdmatx->XferHalfCpltCallback = NULL; hi2c->hdmatx->XferAbortCallback = NULL; /* Enable the DMA channel */ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize); }
-
该函数最后开启DMA搬运。
/* Enable DMA Request */ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
最后是通讯过程的DMA中断了,当触发了DMA的中断类型就会进入该函数,就只有三种传输完成一半、传输完成以及传输错误。
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
/* USER CODE END DMA1_Channel1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_i2c2_rx);
/* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
/* USER CODE END DMA1_Channel1_IRQn 1 */
}
进入到HAL_DMA_IRQHandler,假设触发了传输完成,就会执行相应关闭DMA中断、清空DMA中断标志位最后调用传输完成的回调函数。
...
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
/* Disable the transfer complete and error interrupt */
__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 */
__HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU)));
/* Process Unlocked */
__HAL_UNLOCK(hdma);
if (hdma->XferCpltCallback != NULL)
{
/* Transfer complete callback */
hdma->XferCpltCallback(hdma);
}
}
...
这个hdma->XferCpltCallback()函数指针在我们在开始时就赋值了
/* Set the I2C DMA transfer complete callback */
hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt;
进入到该函数发现关闭了I2C的DMA请求
/* Disable DMA Request */
hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
但是函数内我并没有找到用户可以自定义的回调函数,可供我们自己使用。我自己在里边加入了些代码,实测发现是可以进去的。文章来源:https://www.toymoban.com/news/detail-856654.html
总结
最后总结HAL库方式的DMA中断默认就是开启状态,只是没有给用户开启自定义回调函数使用,也不知道是没必要还是我没找到。文章来源地址https://www.toymoban.com/news/detail-856654.html
到了这里,关于STM32 HAL DMA中断配置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!