2. 串口硬件原理:UART帧格式、波特率、发送/接收FIFO、硬件流控
在嵌入式RTOS系统中,串口(UART)是最常用的外设通信接口之一。理解其硬件底层原理,是编写高效、稳定的串口驱动与中断服务函数的前提。本节将深入剖析UART的核心硬件机制,包括帧格式、波特率生成、FIFO缓冲以及硬件流控,为后续多任务互斥设计奠定基础。
2.1 UART帧格式:数据在线上如何表示
UART是一种异步串行通信协议,数据以帧为单位在单根数据线上逐位传输。一个标准的UART帧由以下部分组成:
- 起始位(Start Bit):逻辑低电平,标志一帧数据的开始。
- 数据位(Data Bits):通常为5~8位,常见配置为8位(一个字节)。
- 校验位(Parity Bit):可选,用于简单的错误检测(奇校验/偶校验/无校验)。
- 停止位(Stop Bit):逻辑高电平,标志一帧数据的结束,常见长度为1位、1.5位或2位。
RTOS驱动要点: 帧格式的配置(数据位、校验位、停止位)必须在驱动初始化阶段与对端设备完全一致。中断服务函数中解析数据时,通常只关心数据位部分,硬件会自动剥离起始位和停止位。
2.2 波特率:通信的节拍器
波特率(Baud Rate)定义了每秒传输的符号数。在UART中,一个符号即一个位,因此波特率等于比特率(bps)。常见的波特率有9600、115200、921600等。
波特率的生成依赖于系统时钟分频。硬件内部通过一个波特率发生器(通常是一个可编程分频器)将系统时钟分频到目标频率。计算公式如下:
// 波特率寄存器值计算(以STM32 USART为例)
// 公式:USARTDIV = f_CK / (16 * BaudRate)
// 其中 f_CK 为USART时钟频率,BaudRate为目标波特率
uint32_t usart_div = (f_CK + (8 * BaudRate)) / (16 * BaudRate); // 四舍五入
USART->BRR = usart_div;
RTOS实时性警告: 波特率越高,单位时间内中断触发频率越高。例如115200bps下,每字节传输约耗时86.8μs,若使能接收中断,则每86.8μs就会产生一次中断。高波特率下中断服务函数的执行时间必须极短,否则会拖累系统实时性,甚至导致数据溢出。
2.3 发送/接收FIFO:缓解中断压力的硬件缓冲
现代MCU的UART外设通常集成了硬件FIFO(First In First Out),用于暂存发送或接收的数据。FIFO的存在可以显著减少中断频率,提升CPU利用率。
| 特性 | 无FIFO(传统UART) | 带FIFO(如STM32 USART) |
|---|---|---|
| 中断触发条件 | 每收发1字节触发一次中断 | 可配置为FIFO半满/满/空时触发中断 |
| CPU负载 | 高(频繁进出中断) | 低(批量处理数据) |
| 数据溢出风险 | 高(软件未及时取走数据) | 低(FIFO提供缓冲深度) |
| 典型深度 | 1字节 | 16字节或32字节 |
2.4 硬件流控:防止数据丢失的握手信号
硬件流控(Hardware Flow Control)通过额外的RTS(Request to Send)和CTS(Clear to Send)信号线,协调通信双方的收发节奏,防止接收端数据溢出。
- RTS(输出):接收端准备好接收数据时,将RTS置为有效(低电平);接收缓冲区满时,置为无效(高电平),通知发送端暂停。
- CTS(输入):发送端检测CTS信号,若为有效则继续发送,若为无效则暂停发送。
RTOS驱动设计建议: 在中断服务函数中,当接收FIFO达到阈值触发中断时,驱动应立即读取FIFO中的数据存入RTOS消息队列,并置位RTS信号允许继续接收。若任务处理不及时导致队列满,驱动应通过RTS信号通知对端暂停发送,避免数据丢失。这是多任务互斥中“生产者-消费者”模型的硬件级体现。
2.5 关键参数配置清单
在RTOS串口驱动初始化阶段,以下参数必须正确配置,否则通信将失败或产生不可预期的行为:
| 参数 | 典型值 | RTOS驱动注意事项 |
|---|---|---|
| 波特率 | 115200 | 高波特率下中断频率高,需确保ISR执行时间 < 1字节传输时间 |
| 数据位 | 8 | 通常使用8位数据,与字节对齐 |
| 校验位 | 无 | 若使能校验,ISR中需检查校验错误标志 |
| 停止位 | 1 | 1.5位和2位停止位用于低速或噪声环境 |
| FIFO使能 | 使能 | 强烈建议使能,降低中断频率 |
| FIFO触发阈值 | 8字节(半满) | 根据系统实时性要求调整,阈值越低响应越快但中断越频繁 |
| 硬件流控 | 根据需求 | 多任务环境下建议使能,防止数据溢出 |
实战经验: 在RTOS中,串口驱动初始化应放在系统启动早期、调度器启动之前完成。中断优先级应设置为低于系统Tick中断,但高于普通任务优先级,以确保串口中断能够及时响应,同时不阻塞系统时钟节拍。