STM32 中断与 DMA 串口通信实战指南
在嵌入式开发领域,STM32 凭借强大的性能与丰富的外设深受工程师青睐。当基础串口通信无法满足高效数据传输需求时,中断(Interrupt)与直接内存访问(DMA)技术便成为提升性能的关键武器。本文将结合 STM32CubeMX 与 HAL 库,通过实战案例带您掌握这两项核心技术。
突破性能瓶颈:STM32 中断与 DMA 串口通信实战指南
在嵌入式开发领域,STM32 凭借强大的性能与丰富的外设深受工程师青睐。当基础串口通信无法满足高效数据传输需求时,中断(Interrupt)与直接内存访问(DMA)技术便成为提升性能的关键武器。本文将结合 STM32CubeMX 与 HAL 库,通过实战案例带您掌握这两项核心技术。
一、中断与 DMA:嵌入式通信的 “效率神器”
1. 中断(Interrupt):CPU 的 “紧急呼叫系统”
中断机制赋予 CPU “多任务处理” 能力。当串口接收到新数据或完成数据发送时,硬件会触发中断请求,CPU 立即暂停当前任务,跳转执行中断服务函数。以串口接收为例,传统轮询方式需 CPU 不断检查接收状态,而中断模式下,CPU 可并行处理其他任务,数据到来时自动响应,大幅提升系统实时性。
2. 直接内存访问(DMA):数据传输的 “特快专递”
DMA 允许外设(如串口)绕过 CPU,直接在内存与外设间搬运数据。想象大量传感器数据需通过串口上传,若使用 CPU 传输,其将被占用无法执行其他任务;而 DMA 控制器可独立完成数据搬运,CPU 仅需在传输前后进行简单配置与处理,极大释放系统资源,尤其适用于高速、大批量数据传输场景。
二、串口中断实战:让指令控制更灵敏
1. STM32CubeMX 配置:开启中断通道
- 基础配置:打开 STM32CubeMX,选择对应芯片型号,配置 USART1 参数:波特率 115200bps、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 通道
- USART1 配置:保持波特率 115200bps 等串口参数不变。
- 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 资源占用率显著降低。需注意,高速传输时应确保硬件连接可靠,必要时采用屏蔽线等措施减少干扰。
更多推荐



所有评论(0)