avatar

松果工作室

欢迎光临

  • 首页
  • ESP
  • LVGL
  • CubeMX
  • freeRTOS
  • 快速笔记
  • 个人收藏
  • 我的服务
  • 所见所闻
Home [CubeMX] 串口 DMA
文章

[CubeMX] 串口 DMA

Posted 昨天 Updated 昨天
By YCP
11~14 min read

使用 STM32CubeMX 配置 USART + DMA 并编写测试程序,一般分为三个部分:

  1. CubeMX 图形化配置
  2. 生成代码后的初始化确认
  3. 编写 DMA 收发测试代码

测试可用


一、CubeMX 配置步骤

1 配置串口

进入 Pinout & Configuration

选择一个 USART,例如:

Connectivity → USART1
Mode → Asynchronous

配置参数:

  • Baud Rate:115200
  • Word Length:8 Bits
  • Parity:None
  • Stop Bits:1
  • Hardware Flow Control:Disable

启用

USART1 global interrupt

2 开启 DMA

在 USART 配置页面:

USART1 → DMA Settings

添加两个 DMA:

TX DMA

Add → USART1_TX
Direction → Memory to Peripheral
Mode → Normal
Priority → Low / Medium

RX DMA

Add → USART1_RX
Direction → Peripheral to Memory
Mode → Circular(推荐)
Priority → High

说明:

DMA模式作用
Normal一次传输结束停止
Circular自动循环接收(适合串口)

通常:

  • TX:Normal
  • RX:Circular

3 NVIC 配置

CubeMX 一般会自动启用:

DMAx Streamx interrupt
USARTx global interrupt

确认以下中断开启:

DMA RX IRQ
DMA TX IRQ
USART IRQ

4 时钟配置

在 Clock Configuration

确保:

APB USART 时钟正常

例如:

USART1 → APB2
USART2 → APB1

5 生成代码

Project Manager:

Toolchain → Makefile / STM32CubeIDE / CMake

点击

GENERATE CODE

二、CubeMX生成的关键代码

生成后你会看到:

UART Handle

UART_HandleTypeDef huart1;

DMA Handle

DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;

初始化

MX_USART1_UART_Init();
MX_DMA_Init();

注意:

MX_DMA_Init() 必须在 USART 初始化之前

三、DMA 发送测试代码

发送最简单:

uint8_t tx_buf[] = "Hello DMA UART\r\n";

HAL_UART_Transmit_DMA(&huart1, tx_buf, sizeof(tx_buf)-1);

发送完成会进入回调:

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        // 发送完成
    }
}

四、DMA 接收测试代码

定义接收缓冲区:

uint8_t rx_buf[64];

启动 DMA 接收:

HAL_UART_Receive_DMA(&huart1, rx_buf, sizeof(rx_buf));

接收完成回调:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        // 收到一帧
    }
}

但是:

⚠️ 串口长度不固定时,这种方法不好用

因为:

DMA只有接满 buffer 才触发

五、推荐:IDLE + DMA 接收(工业常用)

开启:

USART → NVIC → USART global interrupt

启动 DMA:

HAL_UART_Receive_DMA(&huart1, rx_buf, sizeof(rx_buf));

开启 IDLE 中断:

__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

中断处理:

void USART1_IRQHandler(void)
{
    if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);

        uint16_t len = sizeof(rx_buf) - __HAL_DMA_GET_COUNTER(huart1.hdmarx);

        // 处理数据
    }

    HAL_UART_IRQHandler(&huart1);
}

优点:

  • 不需要固定长度
  • 适合协议解析
  • 工业常用方案

六、完整测试 main 示例

uint8_t rx_buf[64];
uint8_t tx_buf[] = "DMA UART Test\r\n";

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    MX_DMA_Init();
    MX_USART1_UART_Init();

    HAL_UART_Receive_DMA(&huart1, rx_buf, sizeof(rx_buf));

    while (1)
    {
        HAL_UART_Transmit_DMA(&huart1, tx_buf, sizeof(tx_buf)-1);
        HAL_Delay(1000);
    }
}

七、调试建议

常见问题:

1 DMA没进中断

检查:

DMA NVIC 是否开启

2 串口没数据

检查:

GPIO AF 配置
TX RX 引脚

3 发送只成功一次

因为:

DMA Busy

需要等待回调。


八、DMA串口性能

普通发送:

HAL_UART_Transmit
CPU占用高

DMA发送:

CPU占用几乎为0
适合高速日志

例如:

printf 重定向到 DMA

CubeMX
License:  CC BY 4.0
Share

Further Reading

OLDER

[CubeMX] SPI

NEWER

[CubeMX] 基础工程配置

Recently Updated

  • [CubeMX] SPI
  • [CubeMX] 串口 DMA
  • [CubeMX] 基础工程配置
  • (LVGL)接口预览 样式
  • (LVGL)案例预览 页面滚动吸附

Trending Tags

LVGL WCH Linux Elec ThatProject freeRTOS STM ESP Flutter Others

Contents

©2026 松果工作室. Some rights reserved.

Using the Halo theme Chirpy