串口通信原理与STM32 UART实战配置指南
串口通信是嵌入式系统中最基础的异步串行通信技术,其核心在于通过起始位、数据位、停止位和波特率等参数实现收发双方的时序同步。作为典型的‘用时间换空间’工程方案,它以极低硬件开销(仅需TXD/RXD/GND三线)支撑调试输出、传感器交互、AT指令控制等关键场景。相比SPI和I²C,UART无需共享时钟,天然适配长距离、多协议(TTL/RS-232/RS-485)扩展,尤其在STM32等主流MCU中,U
1. 串口通信:嵌入式系统中最基础且最实用的片上外设
串口(UART/USART)是绝大多数微控制器芯片内置的标准通信外设,其设计目标并非追求极致带宽,而是以极低的硬件资源开销实现可靠、可预测、易调试的数据交换能力。在嵌入式开发实践中,从最小系统板的调试输出、传感器数据采集、模块AT指令交互,到工业现场的多节点组网,串口始终是工程师接触硬件的第一接口,也是系统联调阶段最值得信赖的“生命线”。本文不讨论抽象理论,而是基于实际工程视角,解析串口通信的本质特征、物理层实现约束、协议参数配置逻辑,以及在主流MCU(以STM32F10x系列为例)上的典型应用实现。
1.1 串行通信的本质:用时间换空间的工程权衡
并行通信曾是早期计算机内部总线的主流方案,其优势在于单次传输多位数据,吞吐率高。但其致命缺陷在于布线复杂度随位宽线性增长:8位并行总线需至少9根信号线(8数据线+1地线),16位则需17根。在PCB走线空间受限、长距离传输易受干扰、多设备互联需复杂总线仲裁的现实约束下,并行方案迅速被串行方案取代。
串行通信的核心思想是 将一个字节(或字)的数据按位(bit)顺序,在单一数据线上逐位发送 。这仅需两根有效信号线(TXD发送、RXD接收)加一根共地线(GND),物理连接极度简化。其代价是传输时间延长——发送一个8位字节,在波特率为9600bps时需耗时约8.3ms(含起始位、停止位)。这种“用时间换空间”的权衡,在绝大多数嵌入式应用场景中是完全可接受的:传感器采样率通常为Hz级,固件升级数据流可接受秒级延迟,而调试信息打印对实时性要求更低。因此,串口成为平衡成本、可靠性与开发效率的最优解。
1.2 物理层标准:TTL、RS-232与RS-485的工程选型逻辑
串口协议本身定义的是数据帧格式与时序逻辑,而物理层则规定了电信号的电气特性。同一套UART逻辑,通过不同的电平转换电路,可适配多种物理接口标准。选择何种标准,取决于具体的应用场景约束:
| 标准 | 电平范围 | 最大距离 | 最大速率 | 连接拓扑 | 典型应用 |
|---|---|---|---|---|---|
| TTL | 0V / +3.3V或+5V | <1m | <1Mbps | 点对点 | MCU间板内通信、调试接口 |
| RS-232 | -15V ~ +15V | ~15m | ~115kbps | 点对点 | 传统PC串口、工控机调试口 |
| RS-485 | 差分±1.5V | ~1200m | ~10Mbps | 多点总线 | 工业现场总线、楼宇自控系统 |
TTL电平 是MCU原生IO口的电气标准,成本最低,无需额外芯片。但其0/+3.3V或0/+5V的电压摆幅抗干扰能力极弱,且驱动能力有限,仅适用于同一块PCB板内或极短距离(<1米)的设备间通信。STM32的USART引脚直接输出TTL电平,与另一颗MCU的UART引脚交叉连接(TXD↔RXD,共GND)即可工作。
RS-232标准 诞生于模拟通信时代,其±12V以上的电平摆幅提供了强大的噪声容限,能有效抑制长导线引入的共模干扰。但其负电压需要电荷泵电路生成,增加了硬件复杂度。当MCU需与传统PC的DB9串口通信时,必须通过电平转换芯片(如MAX232、SP3232)完成TTL↔RS-232的双向转换。此时,MCU的TXD连接转换芯片的TTL输入端,转换芯片的RS-232输出端(T1OUT)连接PC的RXD;反之,MCU的RXD连接转换芯片的TTL输出端,转换芯片的RS-232输入端(R1IN)连接PC的TXD。DB9接口的引脚定义(公头)如下:
| 引脚 | 名称 | 方向 | 功能说明 |
|---|---|---|---|
| 1 | DCD | IN | 载波检测(Modem专用) |
| 2 | RXD | IN | 接收数据(PC→设备) |
| 3 | TXD | OUT | 发送数据(PC→设备) |
| 4 | DTR | OUT | 数据终端就绪(PC通知Modem) |
| 5 | GND | — | 信号地 |
| 6 | DSR | IN | 数据设备就绪(Modem通知PC) |
| 7 | RTS | OUT | 请求发送(PC请求Modem发送) |
| 8 | CTS | IN | 清除发送(Modem允许PC发送) |
| 9 | RING | IN | 振铃指示(Modem专用) |
在纯数据透传场景(如MCU与PC调试),仅需使用引脚2(RXD)、3(TXD)、5(GND)三线即可,其余控制线可悬空。USB转串口模块(如CH340、CP2102)内部已集成USB协议栈与TTL电平转换,对外提供标准的3.3V/5V TTL串口引脚,极大简化了现代开发环境的连接。
RS-485标准 针对工业多点通信需求而设计,采用差分信号传输(A/B两线),其抗共模干扰能力远超单端TTL/RS-232。RS-485总线支持半双工(主从结构,同一时刻仅一设备发送)或多点全双工(需4线),典型应用中多采用半双工模式,通过DE(驱动使能)和RE(接收使能)信号控制收发状态。STM32的USART可通过外接SP3485等芯片接入RS-485总线,此时软件需精确管理DE/RE引脚的电平切换时机,确保在发送数据前拉高DE、发送完毕后拉低DE并拉高RE,避免总线冲突。
1.3 通信协议核心参数:波特率、数据帧结构与同步机制
串口通信是典型的异步通信(Asynchronous Communication),即收发双方 不共享同一时钟信号 ,而是依靠预先约定的时序参数,在各自独立的时钟下完成数据采样。这一机制的可靠性完全依赖于以下四个关键参数的严格匹配:
-
波特率(Baud Rate) :指单位时间内信号状态变化的次数,单位为bps(bits per second)。对于标准UART,波特率即等效于比特率(bit rate)。例如,波特率9600bps表示每秒传输9600个比特,每个比特持续时间为1/9600 ≈ 104.17μs。MCU的UART外设通过内部波特率发生器(通常基于APB总线时钟分频)生成精确的采样时钟。若收发双方波特率偏差超过±5%,接收端将无法在正确时刻采样每一位,导致帧错误。实际工程中,常用波特率(如9600、115200)均经过精心设计,使其在常见系统时钟(如72MHz)下能获得整数分频系数,最大限度减少误差。
-
数据位(Data Bits) :指一个字符中有效数据的位数,常见为5、6、7、8位。现代应用几乎全部采用8位数据位,与字节(Byte)概念对齐,简化软件处理。
-
停止位(Stop Bits) :标志一个字符传输结束的高电平持续时间,可设为1、1.5或2位。1位停止位最常用,它确保在下一个字符的起始位到来前,线路有足够时间恢复到空闲高电平状态。
-
校验位(Parity Bit) :位于数据位与停止位之间,用于简单检错。分为无校验(None)、奇校验(Odd)、偶校验(Even)、标记校验(Mark)、空格校验(Space)。奇校验要求数据位+校验位中“1”的总数为奇数;偶校验则要求为偶数。在噪声较低的板内通信中,常禁用校验位以提升有效数据率;在工业RS-485长线通信中,启用偶校验是提高链路鲁棒性的低成本手段。
一个完整的UART数据帧结构如下图所示(以8N1为例):
空闲态(高) → 起始位(低, 1bit) → 数据位(8bit, LSB先发) → 停止位(高, 1bit) → 空闲态(高)
起始位 是强制的逻辑“0”,其下降沿作为接收端启动内部采样计时器的触发信号,解决了异步通信的初始同步问题。接收端在起始位中间时刻(即0.5 bit时间后)进行第一次采样,随后每隔1 bit时间采样一次,共采样8次(数据位),最后在停止位中间时刻验证其是否为高电平,以确认帧完整性。
1.4 单工、半双工与全双工:通信方向性的硬件实现
通信方向性由物理连接方式与协议逻辑共同决定:
- 单工(Simplex) :数据仅能单向流动,如广播电台发射。在UART硬件层面,仅需连接TXD或RXD中的一根线,另一根悬空。实际嵌入式项目中极少使用。
- 半双工(Half-Duplex) :数据可双向传输,但同一时刻只能单向进行。RS-485总线是典型代表,其物理层仅有一对差分线(A/B),所有设备挂载在同一总线上。通信时,主设备发送命令后,必须释放总线并切换为接收模式,等待从设备响应。此模式节省线路,但需严格的时序控制与冲突避免机制。
- 全双工(Full-Duplex) :数据可同时双向传输。标准UART/TTL/RS-232均为此模式,其硬件基础是独立的TXD(发送)和RXD(接收)两根信号线。MCU在发送数据的同时,可不间断地接收来自对端的数据,无需切换状态,编程模型最为简洁。STM32的USART外设原生支持全双工,是绝大多数应用的默认选择。
1.5 STM32F10x系列中的USART外设配置实践
STM32F10x系列提供了USART(通用同步异步收发器)和UART(通用异步收发器)两种外设。USART支持同步模式(需额外时钟线CLK),而UART仅支持异步模式。对于标准串口通信,两者功能一致。以常见的USART1为例,其典型初始化流程包含三个核心步骤:
步骤一:GPIO引脚复用配置
USART的TXD和RXD引脚需配置为复用推挽输出(TXD)和浮空输入(RXD),并开启对应GPIO端口的时钟。
// 开启GPIOA时钟 (USART1 TX=PA9, RX=PA10)
RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
// 配置PA9为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置PA10为浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
步骤二:USART外设参数初始化
配置波特率、数据位、停止位、校验位、硬件流控及工作模式(收/发使能)。
// 开启USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_USART1, ENABLE);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200; // 波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No; // 无校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 使能收发
USART_Init(USART1, &USART_InitStructure);
步骤三:中断与使能配置
为实现非阻塞式数据接收,通常启用接收中断(RXNE),并配置NVIC优先级。
// 配置NVIC
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 抢占优先级2位,子优先级2位
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // USART1中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 使能USART1接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// 使能USART1外设
USART_Cmd(USART1, ENABLE);
中断服务程序(ISR)示例
在 USART1_IRQHandler 中,需首先检查中断标志,然后读取数据寄存器(DR)以清除RXNE标志,最后进行数据处理。
void USART1_IRQHandler(void)
{
uint8_t res;
USART_TypeDef* USARTx = USART1;
if(USART_GetITStatus(USARTx, USART_IT_RXNE) != RESET) // 接收到数据
{
res = USART_ReceiveData(USARTx); // 读取DR,自动清除RXNE标志
// 在此处添加你的数据处理逻辑,例如存入缓冲区
// ...
}
}
1.6 UART、SPI与I²C总线的关键差异辨析
在嵌入式系统中,UART、SPI、I²C是三种最常用的片上通信外设,其设计目标与适用场景截然不同:
| 特性 | UART (异步) | SPI (同步) | I²C (同步) |
|---|---|---|---|
| 时钟源 | 无共享时钟,靠波特率同步 | 主机提供SCK时钟线 | 主机提供SCL时钟线 |
| 信号线数 | 2线 (TXD/RXD) + GND | 4线 (SCK/MOSI/MISO/SS) | 2线 (SCL/SDA) + GND |
| 拓扑结构 | 点对点 | 点对点或一主多从(需多SS线) | 多主多从(总线仲裁) |
| 速率 | 低至中速 (≤1Mbps) | 高速 (可达几十MHz) | 中低速 (标准模式100kHz, 快速400kHz) |
| 数据格式 | 帧结构(起始/数据/停止) | 无固定帧,连续移位 | 有起始/停止/地址/数据/ACK/NACK |
| 主要用途 | 设备间长距离、低速数据交换 | 高速外设(Flash、ADC、LCD) | 低速外设(EEPROM、传感器、RTC) |
选择依据清晰: 需要与PC调试、连接蓝牙/WiFi模块、或进行长距离工业通信,首选UART;需要高速读写外部Flash或驱动高速ADC,选SPI;需要挂载多个低速传感器或配置寄存器,I²C是最佳选择。 三者并非竞争关系,而是在同一系统中各司其职。
1.7 关于GND:被忽视却至关重要的参考平面
在所有串口通信描述中,“共地”(Common Ground)被反复强调,但其物理本质常被忽略。GND并非简单的“零伏”,而是整个电路系统的 参考电位基准面 。所有电压测量值(如TTL的0V/3.3V、RS-232的±12V)都是相对于GND定义的。当两个设备GND未连接时,它们的“0V”电位可能相差数伏甚至数十伏,此时即使TXD发出理想的3.3V逻辑高电平,RXD端测量到的电压可能是3.3V + ΔV,若ΔV过大,将超出RXD的输入高电平阈值(Vih),导致逻辑识别错误。在长距离RS-485通信中,GND线还承担着为差分接收器提供共模电压回路的功能。因此,在硬件设计中,GND走线应尽可能宽、短,并避免与大电流电源路径平行走线,以降低地弹(Ground Bounce)噪声。
一块设计良好的PCB,其GND覆铜层是整个系统稳定运行的基石。它不仅是信号的返回路径,更是电磁兼容(EMC)设计的核心。忽视GND的设计,再完美的UART配置也无法保证通信的长期可靠性。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐
所有评论(0)