[STM32F4] STM32F446RE基于UART和DMA实现高效数据传输

[复制链接]
1320|14
 楼主| Bblythe 发表于 2024-11-23 07:49 | 显示全部楼层 |阅读模式
STM32F446RE是一款高性能的Cortex-M4核心微控制器,具有丰富的外设资源和较高的运行频率。在嵌入式开发中,UART通信是一个非常常见的需求,而DMA的引入可以显著提高数据传输的效率和性能。本文将介绍如何在STM32F446RE上结合UART和DMA,实现一个高效的数据收发机制。
项目需求
  • 使用UART接口发送和接收数据,通过DMA实现无CPU干预的数据传输。
  • 设定固定的数据缓冲区大小,用于存储接收到的数据。
  • 实现数据接收回调函数,在接收完成后触发处理逻辑。
  • 在主循环中模拟数据发送。
硬件环境
  • MCU型号:STM32F446RE
  • 开发工具:STM32CubeIDE
  • 外设配置:USART2与DMA通道结合使用。

代码实现以下是完整代码:
  1. #include "main.h"
  2. #include <string.h>

  3. /* UART句柄和DMA缓冲区 */
  4. UART_HandleTypeDef huart2;
  5. DMA_HandleTypeDef hdma_usart2_rx;
  6. uint8_t rx_buffer[64]; // 接收缓冲区
  7. uint8_t tx_buffer[] = "Hello from STM32F446RE via UART DMA!\r\n";

  8. /* UART初始化函数 */
  9. void MX_USART2_UART_Init(void) {
  10.     huart2.Instance = USART2;
  11.     huart2.Init.BaudRate = 115200;
  12.     huart2.Init.WordLength = UART_WORDLENGTH_8B;
  13.     huart2.Init.StopBits = UART_STOPBITS_1;
  14.     huart2.Init.Parity = UART_PARITY_NONE;
  15.     huart2.Init.Mode = UART_MODE_TX_RX;
  16.     huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  17.     huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  18.     if (HAL_UART_Init(&huart2) != HAL_OK) {
  19.         Error_Handler();
  20.     }
  21. }

  22. /* DMA初始化函数 */
  23. void MX_DMA_Init(void) {
  24.     __HAL_RCC_DMA1_CLK_ENABLE();

  25.     /* 配置DMA RX通道 */
  26.     hdma_usart2_rx.Instance = DMA1_Stream5;
  27.     hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4;
  28.     hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
  29.     hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
  30.     hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
  31.     hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  32.     hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  33.     hdma_usart2_rx.Init.Mode = DMA_CIRCULAR;
  34.     hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;
  35.     hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  36.     if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK) {
  37.         Error_Handler();
  38.     }

  39.     /* 将DMA与UART关联 */
  40.     __HAL_LINKDMA(&huart2, hdmarx, hdma_usart2_rx);
  41. }

  42. /* 主函数 */
  43. int main(void) {
  44.     HAL_Init();
  45.     SystemClock_Config();

  46.     MX_DMA_Init();
  47.     MX_USART2_UART_Init();

  48.     /* 启动DMA接收 */
  49.     HAL_UART_Receive_DMA(&huart2, rx_buffer, sizeof(rx_buffer));

  50.     while (1) {
  51.         /* 模拟周期性发送数据 */
  52.         HAL_UART_Transmit(&huart2, tx_buffer, strlen((char *)tx_buffer), HAL_MAX_DELAY);
  53.         HAL_Delay(1000);
  54.     }
  55. }

  56. /* 接收完成回调函数 */
  57. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
  58.     if (huart->Instance == USART2) {
  59.         /* 数据处理逻辑:这里简单打印接收到的数据 */
  60.         HAL_UART_Transmit(&huart2, rx_buffer, sizeof(rx_buffer), HAL_MAX_DELAY);
  61.     }
  62. }

  63. /* 错误处理函数 */
  64. void Error_Handler(void) {
  65.     while (1) {
  66.         // 错误循环
  67.     }
  68. }
代码说明
  • UART初始化:USART2配置为115200波特率,无校验位,使用全双工模式。
  • DMA初始化:DMA通道与UART接收器关联,配置为循环模式,用于持续接收数据。
  • 回调函数:当接收到数据时触发HAL_UART_RxCpltCallback回调函数,模拟数据的回显逻辑。
  • 数据发送:主循环中定时发送字符串,以验证UART发送功能。

项目特点
  • 使用DMA减少了CPU的负载,使得数据传输更加高效。
  • 循环模式使UART接收端能够持续处理数据,无需频繁重新配置。
  • HAL库的使用提高了代码的可读性和兼容性。

公羊子丹 发表于 2024-11-23 07:49 来自手机 | 显示全部楼层
STM32F446RE性能确实不错,DMA加UART真的很实用!
周半梅 发表于 2024-11-23 07:50 来自手机 | 显示全部楼层
UART回调函数写得挺好,接收到数据后直接回显,挺方便的。
帛灿灿 发表于 2024-11-23 07:50 来自手机 | 显示全部楼层
我用的STM32F103,代码看起来能直接改用到我的项目里。
童雨竹 发表于 2024-11-23 07:50 来自手机 | 显示全部楼层
这个例子挺全的,连DMA的配置都包括了,学习了!
万图 发表于 2024-11-23 07:50 来自手机 | 显示全部楼层
我发现HAL库确实方便,但性能要求高时还是更喜欢用LL。
Wordsworth 发表于 2024-11-23 07:50 来自手机 | 显示全部楼层
如果想用多个UART通道,是不是每个都需要一个独立的DMA通道?
 楼主| Bblythe 发表于 2024-11-23 07:51 来自手机 | 显示全部楼层
这个接收缓冲区大小会不会影响大文件传输的稳定性?
Pulitzer 发表于 2024-11-23 07:51 来自手机 | 显示全部楼层
能不能加个超时检测逻辑,防止UART卡住?
Uriah 发表于 2024-11-23 07:51 来自手机 | 显示全部楼层
下次能讲讲如何通过中断和DMA结合处理复杂协议吗?
Clyde011 发表于 2024-11-23 07:51 来自手机 | 显示全部楼层
感觉这个例子扩展性很好,直接用到项目里没问题!
发送到工地施工 发表于 2024-12-30 23:55 | 显示全部楼层
要在 STM32F446RE 上实现 UART 和 DMA 的结合使用,首先需要进行一些基础的硬件配置,并编写相应的代码来实现高效的数据收发。
慢动作 发表于 2024-12-31 00:09 | 显示全部楼层
使用 STM32CubeMX 或 STM32CubeIDE 进行硬件配置。此配置步骤将在 STM32CubeMX 中演示,并生成代码,之后我们可以在 STM32CubeIDE 中进行开发。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

162

主题

6081

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部