【串口技术系列文档 08】中断驱动vs轮询vs DMA

本文目标:掌握三种UART数据传输模式的原理、优缺点及应用场景


### 目录

  • [@TOC(目录)](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [三种模式对比](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [轮询模式](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [原理](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [优缺点](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [应用场景](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [中断驱动模式](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [发送中断实现](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [接收中断实现](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [DMA传输模式](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [DMA配置](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [循环DMA(接收)](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [混合模式](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [RX中断 + TX DMA](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)
  • [性能对比实测](#目录 @TOC 三种模式对比 轮询模式 原理 优缺点 应用场景 中断驱动模式 发送中断实现 接收中断实现 DMA传输模式 DMA配置 循环DMA(接收) 混合模式 RX中断 + TX DMA 性能对比实测)

三种模式对比

特性 轮询模式 中断驱动 DMA传输
CPU占用 极高(阻塞等待) 中等(中断上下文切换) 极低(硬件自动)
实时性 高(立即响应) 中等(中断延迟) 低(DMA延迟)
吞吐量 低 中 高
实现复杂度 简单 中等 复杂
功耗 高 中 低
适用场景 简单调试、Bootloader 通用应用 高速大数据量传输

轮询模式

原理

c 复制代码
// 轮询发送
void uart_send_polling(uint8_t data) {
    while (!(UART->LSR & LSR_THRE));  // 等待发送缓冲区空
    UART->THR = data;
}

// 轮询接收
uint8_t uart_recv_polling(void) {
    while (!(UART->LSR & LSR_DR));  // 等待数据就绪
    return UART->RBR;
}

优缺点

优点:

  • 实现简单,代码量少
  • 无需配置中断
  • 实时性好(立即检测到数据)

缺点:

  • CPU 100%占用,无法处理其他任务
  • 功耗高
  • 不适合RTOS环境

应用场景

  • Bootloader固件下载(简单可靠)
  • 早期调试阶段
  • 单线程简单应用

中断驱动模式

发送中断实现

c 复制代码
#define TX_BUF_SIZE 256
static uint8_t tx_buffer[TX_BUF_SIZE];
static volatile uint16_t tx_head = 0, tx_tail = 0;

// 启动发送
void uart_send_start(const uint8_t *data, uint16_t len) {
    for (uint16_t i = 0; i < len; i++) {
        uint16_t next = (tx_head + 1) % TX_BUF_SIZE;
        if (next == tx_tail) break;  // 缓冲区满
        
        tx_buffer[tx_head] = data[i];
        tx_head = next;
    }
    
    UART->IER |= IER_THRE;  // 使能发送中断
}

// 发送中断处理
void uart_tx_isr(void) {
    if (tx_head != tx_tail) {
        UART->THR = tx_buffer[tx_tail];
        tx_tail = (tx_tail + 1) % TX_BUF_SIZE;
    } else {
        UART->IER &= ~IER_THRE;  // 关闭发送中断
    }
}

接收中断实现

c 复制代码
#define RX_BUF_SIZE 256
static uint8_t rx_buffer[RX_BUF_SIZE];
static volatile uint16_t rx_head = 0, rx_tail = 0;

// 接收中断处理
void uart_rx_isr(void) {
    while (UART->LSR & LSR_DR) {
        uint8_t data = UART->RBR;
        
        uint16_t next = (rx_head + 1) % RX_BUF_SIZE;
        if (next != rx_tail) {  // 缓冲区未满
            rx_buffer[rx_head] = data;
            rx_head = next;
        } else {
            // 溢出处理
        }
    }
}

// 读取数据
int uart_getchar(void) {
    if (rx_head == rx_tail) return -1;
    
    uint8_t c = rx_buffer[rx_tail];
    rx_tail = (rx_tail + 1) % RX_BUF_SIZE;
    return c;
}

DMA传输模式

DMA配置

c 复制代码
// 配置TX DMA
void uart_tx_dma_init(void) {
    // 配置DMA通道
    DMA_CH->SAR = (uint32_t)tx_dma_buffer;  // 源地址
    DMA_CH->DAR = (uint32_t)&UART->THR;     // 目标地址
    DMA_CH->CTL = DMA_MEM_TO_PERIPH | 
                  DMA_MINC_ENABLE |  // 源地址递增
                  DMA_BYTE_SIZE;
    
    // UART使能DMA
    UART->DMACR |= UART_TXDMAE;
}

// 启动DMA发送
void uart_send_dma(const uint8_t *data, uint16_t len) {
    memcpy(tx_dma_buffer, data, len);
    
    DMA_CH->CNDTR = len;  // 传输长度
    DMA_CH->CCR |= DMA_EN;  // 启动DMA
}

// DMA传输完成中断
void DMA_IRQHandler(void) {
    if (DMA->ISR & DMA_TCIF) {  // 传输完成
        DMA->IFCR = DMA_CTCIF;  // 清除标志
        DMA_CH->CCR &= ~DMA_EN;  // 停止DMA
        
        // 通知应用层
        tx_complete_callback();
    }
}

循环DMA(接收)

c 复制代码
#define RX_DMA_SIZE 1024

void uart_rx_dma_init(void) {
    DMA_CH->SAR = (uint32_t)&UART->RBR;
    DMA_CH->DAR = (uint32_t)rx_dma_buffer;
    DMA_CH->CNDTR = RX_DMA_SIZE;
    DMA_CH->CTL = DMA_PERIPH_TO_MEM | 
                  DMA_MINC_ENABLE | 
                  DMA_CIRCULAR_MODE;  // 循环模式
    
    DMA_CH->CCR |= DMA_EN;
    UART->DMACR |= UART_RXDMAE;
}

// 读取已接收数据
uint16_t uart_rx_dma_read(uint8_t *buf, uint16_t len) {
    uint16_t dma_pos = RX_DMA_SIZE - DMA_CH->CNDTR;
    uint16_t available = (dma_pos - rx_tail + RX_DMA_SIZE) % RX_DMA_SIZE;
    
    if (len > available) len = available;
    
    for (uint16_t i = 0; i < len; i++) {
        buf[i] = rx_dma_buffer[rx_tail];
        rx_tail = (rx_tail + 1) % RX_DMA_SIZE;
    }
    
    return len;
}

混合模式

RX中断 + TX DMA

c 复制代码
// 接收:中断驱动(低延迟)
// 发送:DMA(高效率)

适用场景:
- 接收数据量小,需要快速响应(命令/协议)
- 发送数据量大(日志、文件传输)

性能对比实测

测试条件:

  • MCU: STM32F4, 168MHz
  • 波特率: 921600 bps
  • 数据: 连续发送1KB
模式 CPU占用 传输时间 中断次数
轮询 100% 11.1ms 0
中断 15% 11.2ms ~1000
DMA 2% 11.1ms 1

延伸阅读:\[09-FIFO管理与流控]、\[13-多串口并发处理]

上一篇 :\[07-UART控制器寄存器详解]

下一篇:\[09-FIFO管理与流控]


✨ 感谢你的阅读 ✨

技术之路漫漫,分享是为了更好地交流。

如果本文的内容对你有启发,希望能得到你的支持:

👍 点赞 | ⭐ 收藏 | 👀 关注

如果你在调试过程中遇到了其他问题,

欢迎在 评论区 💬 留言,我们一起探讨。

关注我,一起交流底层开发的那些事儿!🚀


相关推荐
NamoAmitabha12810 分钟前
嵌入式开发中的定时器---deepseek
单片机·嵌入式硬件
福建佰胜张工31 分钟前
深度解析 Allen-Bradley 150-B135NBDA 智能电机控制器:选型、参数与工业应用
运维·数据库·单片机·嵌入式硬件·安全·自动化
secondyoung31 分钟前
Cortex-R52与TriCore详细对比
arm开发·单片机·嵌入式硬件·mcu
送外卖的工程师43 分钟前
STM32仓库环境监测系统
stm32·单片机·嵌入式硬件
苏州福兰克1 小时前
没有3D内容,裸眼3D显示器还能用吗?
3d·计算机外设
芯思路1 小时前
STM32开发学习笔记之十【AI部署】
笔记·stm32·学习
豪气的程序猿1 小时前
Windows 11 外接键盘偶尔漏键?用键盘小鹿练习前先做双设备对照
计算机外设·电脑
2501_922639581 小时前
率能半导体 SS6840单通道H桥驱动芯片:42V/7A,覆盖打印机、办公自动化、机器人、工业缝纫机四大应用场景
stm32·单片机·嵌入式硬件·硬件工程
天空'之城1 小时前
002基于 STM32 的智能灯光窗帘控制系统
stm32·单片机·毕业设计·智能家居·pwm
电子科技圈2 小时前
芯科科技2026年Tech Talks技术系列讲座再增添全新主题共探无线SoC架构演进与安全合规
科技·嵌入式硬件·mcu·物联网·安全·架构·iot