STM32 UART DMA使用方法总结

目录

概述

[1 UART DMA 核心原理](#1 UART DMA 核心原理)

[1.1 原理介绍](#1.1 原理介绍)

[1.2 代码实现逻辑](#1.2 代码实现逻辑)

[2 STM32 Cube 配置UART&DMA](#2 STM32 Cube 配置UART&DMA)

[2.1 配置参数方法](#2.1 配置参数方法)

[2.2 完整代码实现(HAL 库)](#2.2 完整代码实现(HAL 库))

[3 验证](#3 验证)


概述

STM32 单片机中 UART(串口)配合 DMA(直接存储器访问)进行数据收发的使用方法,包括核心原理、配置步骤和实际代码实现,这是 STM32 中提升串口数据传输效率的常用方式。

1 UART DMA 核心原理

1.1 原理介绍

DMA(直接存储器访问)的作用是在外设(UART)内存(RAM) 之间直接传输数据,无需 CPU 参与,仅在传输开始 / 结束时通过中断通知 CPU,能大幅减轻 CPU 负担,特别适合大量、连续的串口数据收发场景。

STM32 UART 的 DMA 支持两个方向:

  • TX(发送):内存 → DMA → UART 数据寄存器 → 发送出去
  • RX(接收):UART 数据寄存器 → DMA → 内存

1.2 代码实现逻辑

以 STM32F205 为例,配置 USART1 的 DMA 收发(新手优先用 HAL 库,降低上手难度):

步骤 1:CubeMX 硬件配置

1) 启用 UART 外设

  • 选择 USART1,模式设为「Asynchronous(异步)」。
  • 配置基本参数:波特率(如 115200)、数据位 8、停止位 1、无校验、收发使能。

2) 启用 DMA 控制器

找到「DMA Settings」,点击「Add」添加 DMA 通道(通道映射需查芯片手册):

  • USART1_TX:选择 DMA1 Channel4,传输方向「Memory to Peripheral(内存到外设)」。
  • USART1_RX:选择 DMA1 Channel5,传输方向「Peripheral to Memory(外设到内存)」

3) 配置 DMA 关键参数

  • 数据宽度:Byte(字节,最常用)。
  • 内存增量模式:开启(内存地址自动递增,适配数组传输)。
  • 外设增量模式:关闭(UART 数据寄存器地址固定)。
  • 循环模式:发送一般关闭(单次传输),接收如需持续接收可开启(环形缓冲区)。
  • 优先级:Medium(中等,可按需调整)。

4) 启用中断(可选)

启用 DMA 的「传输完成 / 错误中断」,或 UART 的 IDLE 中断(用于不定长接收)。

2 STM32 Cube 配置UART&DMA

2.1 配置参数方法

1) 使能UART接口

2) 配置UART 的参数

3)配置UART-DMA

  1. 确认时钟频率

5) STM32的MCU型号

2.2 完整代码实现(HAL 库)

1) 代码框架结构

2) main.c函数中实现粗航空函数

cpp 复制代码
#define RX_BUFFER_SIZE 256
uint8_t rx_buffer[RX_BUFFER_SIZE];

extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;

void UART_DMA_StartReceive(void) 
{
    HAL_UART_Receive_DMA(&huart1, rx_buffer, RX_BUFFER_SIZE);
    
    // 使能空闲中断
    // __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
}

// 获取已接收数据长度
uint32_t UART_DMA_GetReceivedLength(void) 
{
    // 计算已接收数据长度
    uint32_t pos = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
    return pos;
}

// DMA发送数据
void UART_DMA_Send(uint8_t *data, uint16_t size) 
{
    if (HAL_UART_Transmit_DMA(&huart1, data, size) == HAL_OK) 
    {
          // 等待发送完成或做其他任务
          while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX) 
          {
             //vTaskDelay(pdMS_TO_TICKS(1));  // 短暂延时
          }
    }
}

// 发送字符串
void UART_DMA_SendString(const char *str) 
{
    uint16_t len = strlen(str);
    HAL_UART_Transmit_DMA(&huart1, (uint8_t*)str, len);
}


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 
{
    if (huart->Instance == USART1) 
    {
        HAL_UART_Receive_DMA(&huart1, rx_buffer, RX_BUFFER_SIZE);
    }
}

uint32_t lenght;
void  test_code( void )
{
    lenght = UART_DMA_GetReceivedLength();
    if( lenght > 0)
    {
        HAL_UART_DMAStop(&huart1);
        __HAL_DMA_SET_COUNTER(&hdma_usart1_rx, RX_BUFFER_SIZE);
        HAL_UART_Receive_DMA(&huart1, rx_buffer, RX_BUFFER_SIZE);
    }
}

3 验证

1) MCU发送数据功能

在代码中发送如下数据

串口终端上收到:

  1. MCU接收数据

发送字节94个

MCU接收到的数据

相关推荐
FreakStudio1 天前
不用装软件!这款MicroPython浏览器 IDE :让你在手机上也能调试树莓派 Pico
python·单片机·嵌入式·电子diy·tinyml
yuan199971 天前
STM32远程升级系统(Bootloader + 上位机)
stm32·单片机·嵌入式硬件
Heartache boy1 天前
野火STM32_HAL库版课程笔记-ADC多通道采集热敏、光敏、反射传感器(轮询)
笔记·stm32·单片机
AI+程序员在路上1 天前
嵌入式软件技术大全
linux·开发语言·arm开发·单片机
秀秀更健康1 天前
STM32的程序下载不进去----VDDA悬空
stm32·单片机·嵌入式硬件
长安第一美人1 天前
AI辅助下的嵌入式UI系统设计与实践(二)[代码阅读理解]
c++·嵌入式硬件·ui·显示屏·工业应用
我在人间贩卖青春1 天前
DMA的应用
单片机·dma·gpdma
学嵌入式的小杨同学1 天前
STM32 进阶封神之路(二十五):ESP8266 深度解析 —— 从 WiFi 通信原理到 AT 指令开发(底层逻辑 + 实战基础)
c++·vscode·stm32·单片机·嵌入式硬件·mcu·智能硬件
树爷只认钱1 天前
ESP01S模块+串口底座 AT指令连接中移Onenet物联网全过程(第1篇)
单片机·嵌入式硬件·物联网·esp8266
学嵌入式的小杨同学1 天前
STM32 进阶封神之路(二十六):ESP8266 实战全攻略 ——TCP 通信 + 数据上传 + 远程控制 + 透传模式(库函数 + 代码落地)
stm32·单片机·嵌入式硬件·mcu·硬件架构·硬件工程·智能硬件