HAL库——UART的DMA发送(对比接收)

本文详细介绍了STM32使用HAL库进行UART的DMA发送过程,对比了发送和接收的区别。在启动发送后,当DMA发送完成,会触发中断。在normal模式下,会进入UART中断请求,调用特定的中断处理函数;而在circular模式下,处理方式与接收类似,直接调用发送完成回调。文章强调理解不同工作模式下的回调函数和中断处理机制的重要性。
摘要由CSDN通过智能技术生成

前面讲到的UART接收执行过程:

  • 启动UART的DMA接收(这里面还定义了DMA回调函数):HAL_UART_Receive_DMA
  • 接收完成后,请求DMA中断(判断中断的类型):HAL_DMA_IRQHandler
  • 调用DMA接收完成回调函数(同时关闭了DMA接收):UART_DMAReceiveCplt
  • 调用UART接收回调函数(处理数据,启动DMA接收):HAL_UART_RxCpltCallback

 UART的DMA发送和接收的过程类似,部分细节不同,DMA的发送执行过程如下:

  • 启动UART的DMA发送(其中定义了发送的回调函数):HAL_UART_Transmit_DMA
  • 发送完成,请求DMA中断(判断中断的类型):HAL_DMA_IRQHandler
  • 调用DMA发送完成回调函数:UART_DMATransmitCplt

到这一步还是一样的,执行到 UART_DMATransmitCplt里面时,开始不一样了。看一下UART_DMATransmitCplt说了啥:

static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
  UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
  /* DMA Normal mode*/                                //看这里1
  if ((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)
  {
    huart->TxXferCount = 0x00U;

    /* Disable the DMA transfer for transmit request by setting the DMAT bit
       in the UART CR3 register */
    CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);

    /* Enable the UART Transmit Complete Interrupt */
    SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);

  }
  /* DMA Circular mode */                             //看这里2
  else
  {
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
    /*Call registered Tx complete callback*/
    huart->TxCpltCallback(huart);
#else
    /*Call legacy weak Tx complete callback*/
    HAL_UART_TxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
  }
}

程序不长,看着好像和UART_DMARe

  • 9
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是基于 STM32 HAL 库的 UART2 DMA 初始化代码示例: ```c /* 定义 UART2 接收缓冲区大小 */ #define UART2_RX_BUF_SIZE 64 /* 定义 DMA 缓冲区大小 */ #define DMA_BUF_SIZE 128 /* 定义 UART2 句柄和 DMA 句柄 */ UART_HandleTypeDef huart2; DMA_HandleTypeDef hdma_usart2_rx; /* 定义 UART2 接收缓冲区和 DMA 缓冲区 */ uint8_t uart2_rx_buf[UART2_RX_BUF_SIZE]; uint8_t dma_rx_buf[DMA_BUF_SIZE]; void UART2_DMA_Init(void) { /* 使能 DMA 时钟 */ __HAL_RCC_DMA1_CLK_ENABLE(); /* 配置 DMA 句柄 */ hdma_usart2_rx.Instance = DMA1_Channel6; hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart2_rx.Init.Mode = DMA_CIRCULAR; hdma_usart2_rx.Init.Priority = DMA_PRIORITY_HIGH; hdma_usart2_rx.Init.Request = DMA_REQUEST_2; if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK) { /* 初始化 DMA 失败 */ Error_Handler(); } /* 关联 DMA 句柄到 UART2 */ __HAL_LINKDMA(&huart2, hdmarx, hdma_usart2_rx); /* 使能 UART2 时钟 */ __HAL_RCC_USART2_CLK_ENABLE(); /* 配置 UART2 */ huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { /* 初始化 UART2 失败 */ Error_Handler(); } /* 开启 UART2 接收 DMA */ HAL_UART_Receive_DMA(&huart2, dma_rx_buf, DMA_BUF_SIZE); } /* UART2 接收 DMA 中断回调函数 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /* 处理接收到的数据 */ // ... } /* DMA 传输错误中断回调函数 */ void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { /* 处理 DMA 错误 */ // ... } ``` 在上述代码中,我们首先定义了 UART2 接收缓冲区大小和 DMA 缓冲区大小,然后定义了 UART2 句柄和 DMA 句柄以及这两个缓冲区。接着在 `UART2_DMA_Init()` 函数中,我们首先使能 DMA 时钟,并配置 DMA 句柄。然后我们将 DMA 句柄关联到 UART2 句柄上,并使能 UART2 时钟,最后配置 UART2 句柄。最后,我们通过调用 `HAL_UART_Receive_DMA()` 函数开启 UART2 接收 DMA。在 DMA 传输完成后,`HAL_UART_RxCpltCallback()` 函数会被调用,我们可以在这个回调函数中处理接收到的数据。如果 DMA 传输出现错误,`HAL_UART_ErrorCallback()` 函数会被调用。需要注意的是,这里的 DMA 模式是循环模式,即 DMA 缓冲区满后会自动重新从缓冲区头开始填充,因此我们需要在处理数据时注意判断 DMA 缓冲区指针的位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值