突破性能瓶颈:STM32 中断与 DMA 串口通信实战指南

在嵌入式开发领域,STM32 凭借强大的性能与丰富的外设深受工程师青睐。当基础串口通信无法满足高效数据传输需求时,中断(Interrupt)与直接内存访问(DMA)技术便成为提升性能的关键武器。本文将结合 STM32CubeMX 与 HAL 库,通过实战案例带您掌握这两项核心技术。

一、中断与 DMA:嵌入式通信的 “效率神器”

1. 中断(Interrupt):CPU 的 “紧急呼叫系统”

中断机制赋予 CPU “多任务处理” 能力。当串口接收到新数据或完成数据发送时,硬件会触发中断请求,CPU 立即暂停当前任务,跳转执行中断服务函数。以串口接收为例,传统轮询方式需 CPU 不断检查接收状态,而中断模式下,CPU 可并行处理其他任务,数据到来时自动响应,大幅提升系统实时性。

2. 直接内存访问(DMA):数据传输的 “特快专递”

DMA 允许外设(如串口)绕过 CPU,直接在内存与外设间搬运数据。想象大量传感器数据需通过串口上传,若使用 CPU 传输,其将被占用无法执行其他任务;而 DMA 控制器可独立完成数据搬运,CPU 仅需在传输前后进行简单配置与处理,极大释放系统资源,尤其适用于高速、大批量数据传输场景。

二、串口中断实战:让指令控制更灵敏

1. STM32CubeMX 配置:开启中断通道

  1. 基础配置:打开 STM32CubeMX,选择对应芯片型号,配置 USART1 参数:波特率 115200bps、1 位停止位、无校验位,与基础串口配置相同。
  1. 中断使能:在USART1的NVIC Settings选项卡中,勾选USART1 Global Interrupt,为串口 1 开启全局中断。这一步相当于给 CPU 安装了 “接收串口紧急信号” 的功能。

2. 代码实现:中断驱动的双向通信


#include "main.h"

UART_HandleTypeDef huart1;

char rx_char; // 存储接收字符

uint8_t send_flag = 1; // 发送控制标志,1为发送,0为暂停

// 中断服务函数:处理串口中断请求

void USART1_IRQHandler(void) {

HAL_UART_IRQHandler(&huart1);

}

// 接收中断回调函数:数据处理核心逻辑

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {

if(huart == &huart1) {

if(rx_char == '#') { // 接收到'#',暂停发送

send_flag = 0;

} else if(rx_char == '*') { // 接收到'*',恢复发送

send_flag = 1;

}

// 重新开启接收中断,等待下一个字符

HAL_UART_Receive_IT(&huart1, (uint8_t*)&rx_char, 1);

}

}

int main(void) {

HAL_Init();

MX_GPIO_Init();

MX_USART1_UART_Init();

char tx_buffer[] = "hello windows!\r\n";

uint16_t tx_len = sizeof(tx_buffer);

// 首次开启接收中断

HAL_UART_Receive_IT(&huart1, (uint8_t*)&rx_char, 1);

while (1) {

if(send_flag) {

HAL_UART_Transmit(&huart1, (uint8_t*)tx_buffer, tx_len, 1000);

}

}

}

3. 效果验证:指令实时响应

将程序烧录至 STM32,打开串口助手发送#和*指令。可观察到,发送#后,“hello windows!” 的发送立即暂停;发送*,数据恢复发送。中断机制确保了上位机指令的实时处理,避免主程序阻塞。

三、串口 DMA 实战:高速传输的终极方案

1. STM32CubeMX 配置:搭建 DMA 通道

  1. USART1 配置:保持波特率 115200bps 等串口参数不变。
  1. DMA 设置:在USART1配置界面点击Add,添加TX方向的 DMA 通道。配置数据宽度为Byte,传输模式选择Circular(循环模式,适合连续发送);若需在传输完成时触发中断处理,可在DMA Settings中勾选对应中断选项。

2. 代码实现:解放 CPU 的数据搬运


#include "main.h"

UART_HandleTypeDef huart1;

DMA_HandleTypeDef hdma_usart1_tx;

// 待发送数据缓冲区

char tx_buffer[] = "hello windows!\r\n";

uint16_t tx_len = sizeof(tx_buffer);

int main(void) {

HAL_Init();

MX_GPIO_Init();

MX_USART1_UART_Init();

MX_DMA_Init(); // 初始化DMA

// 启动DMA发送,数据自动循环传输

HAL_UART_Transmit_DMA(&huart1, (uint8_t*)tx_buffer, tx_len);

while (1) {

// 主程序可执行其他复杂任务,如传感器数据处理

}

}

// 可选:DMA传输完成回调函数

void HAL_DMA_TCCallback(DMA_HandleTypeDef* hdma) {

if(hdma == &hdma_usart1_tx) {

// 可在此添加传输完成后的处理逻辑,如切换发送数据

}

}

3. 性能测试:挑战高速极限

将波特率提升至 921600bps 甚至更高,观察串口助手接收数据的连续性。实测表明,DMA 模式下数据传输稳定,CPU 资源占用率显著降低。需注意,高速传输时应确保硬件连接可靠,必要时采用屏蔽线等措施减少干扰。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐