1. 串口轮询模式的底层机制与性能瓶颈
在嵌入式系统开发中,串口通信是最基础也是最频繁使用的外设之一。初学者常从轮询(Polling)模式入手,因其逻辑直观、易于理解。然而,当项目复杂度提升,轮询模式的固有缺陷便迅速暴露——它本质上是一种“CPU密集型”的数据搬运方式,严重制约系统实时性与多任务能力。
1.1 发送过程的寄存器级行为
以STM32的USART2为例,其发送路径包含两个关键寄存器: 发送数据寄存器(TDR) 和 发送移位寄存器(TSR) 。当调用 HAL_UART_Transmit(&huart2, pData, Size, Timeout) 时,CPU执行的是一个典型的“搬砖”流程:
- CPU将待发送缓冲区
pData中的第一个字节写入TDR; - 硬件自动将该字节从TDR加载至TSR;
- TSR按配置的波特率(如115200 bps),逐位将数据转换为TX引脚上的电平信号;
- 关键等待点 :CPU必须持续查询状态寄存器(SR)中的
TXE(Transmit Data Register Empty)标志位。该标志仅在TDR为空、可接受新数据时置位; - 一旦
TXE == SET,CPU立即将下一个字节写入TDR,重复步骤2–4; - 整个过程持续至所有
Size字节发送完毕,或超时(Timeout参数触发)。
此过程的核心矛盾在于: CPU在发送期间完全被绑定在查询-写入循环中,无法响应任何其他事件 。即使发送一个仅1字节的数据,在115200波特率下,单字节传输时间约87μs,但CPU需在此期间反复读取SR寄存器数十次。若发送100字节,则CPU可能被阻塞近9ms——这足以错过一次10ms周期的定时器中断,导致控制环路失稳。
1.2 接收过程的同步陷阱
接收流程同样依赖轮询,但逻辑略有不同。硬件RX引脚接收到起始位后,按波特率采样数据位,最终将一帧完整数据存入 接收移位寄存器(RSR) ,再由硬件自动转移至 接收数据寄存器(RDR) 。 HAL_UART_Receive(&huart2, pData, Size, Timeout) 的执行逻辑为:
- CPU持续查询SR中的
RXNE(Read Data Register Not Empty)标志; - 当
RXNE == SET,表示RDR中有新数据,CPU立即读取RDR内容并存入pData缓冲区; - 重复步骤1–2,直至接收满
Size字节或超时。
问题在于: 轮询接收要求上层应用必须预先知道确切的数据长度 。例如,若协议规定每次发送固定5字节指令(如”R1\0\0\0”),则 Size=5 可行;但若指令长度可变(”R1”、”B12”、”G255”),轮询模式便无能为力——设置 Size=3 会截断长指令,设置 Size=10 则需等待10字节全部到达,而实际指令可能仅3字节,导致后续操作无限期阻塞。
更严峻的是,轮询接收期间CPU处于“忙等”(Busy-Waiting)状态,无法处理按键扫描、ADC采样、LED PWM更新等并行任务。在资源受限的MCU上,这种设计直接扼杀了系统的并发能力。
1.3 轮询模式的本质:同步阻塞I/O
轮询模式在操作系统术语中属于 同步阻塞I/O(Synchronous Blocking I/O) 。其行为特征可总结为:
- 同步性 :应用程序逻辑与I/O操作严格串行,必须等待I/O完成才能继续;
- 阻塞性 :CPU在I/O过程中无法执行其他有意义的工作,空转消耗算力;
- 确定性长度依赖 :数据长度必须在调用前静态确定,缺乏对流式数据的适应能力。
这种模式仅适用于极简场景(如单任务Bootloader的调试输出),在现代嵌入式应用中已成技术债。要突破此瓶颈,必须引入异步机制——中断与DMA,它们共同构成了高效串口通信的基石。
2. 串口中断模式:释放CPU,实现异步通信
中断(Interrupt)是MCU硬件提供的核心异步机制,它允许外设在特定事件发生时(如数据发送完成、接收缓冲区非空),主动“打断”CPU当前执行流,跳转至专用服务程序(ISR)进行处理。对串口而言,中断模式彻底解耦了数据搬运与主程序逻辑,使CPU得以在I/O间隙执行其他任务。
2.1 中断机制的硬件基础
STM32的USART模块集成多个可屏蔽中断源,通过状态寄存器(SR)中的对应标志位触发:
- TXE(Transmit Data Register Empty) :TDR被清空,可写入新数据;
- TC(Transmission Complete) :TSR中最后一位数据发送完毕,整个发送过程结束;
- RXNE(Read Data Register Not Empty) :RDR中有有效数据,可被读取;
- IDLE(Idle Line Detected) :RX线上检测到空闲状态(连续高电平),常用于帧间隔识别;
- ORE(Overrun Error) :新数据到达时RDR尚未被读取,导致数据丢失。
这些中断请求经由 嵌套向量中断控制器(NVIC) 统一管理。NVIC支持中断优先级分组(如抢占优先级2位+子优先级2位),确保高实时性任务(如电机控制)可抢占低优先级串口中断。正确配置NVIC是启用中断的前提。
2.2 启用USART2中断的工程化配置
在STM32CubeMX中启用USART2中断,本质是生成符合CMSIS标准的初始化代码。其核心步骤包括:
-
使能USART2时钟与GPIO时钟 :
c __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); // PA2(TX), PA3(RX) -
配置GPIO为复用推挽输出/输入 :
c GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN


2072

被折叠的 条评论
为什么被折叠?



