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),即收发双方 不共享同一时钟信号 ,而是依靠预先约定的时序参数,在各自独立的时钟下完成数据采样。这一机制的可靠性完全依赖于以下四个关键参数的严格匹配:

  1. 波特率(Baud Rate) :指单位时间内信号状态变化的次数,单位为bps(bits per second)。对于标准UART,波特率即等效于比特率(bit rate)。例如,波特率9600bps表示每秒传输9600个比特,每个比特持续时间为1/9600 ≈ 104.17μs。MCU的UART外设通过内部波特率发生器(通常基于APB总线时钟分频)生成精确的采样时钟。若收发双方波特率偏差超过±5%,接收端将无法在正确时刻采样每一位,导致帧错误。实际工程中,常用波特率(如9600、115200)均经过精心设计,使其在常见系统时钟(如72MHz)下能获得整数分频系数,最大限度减少误差。

  2. 数据位(Data Bits) :指一个字符中有效数据的位数,常见为5、6、7、8位。现代应用几乎全部采用8位数据位,与字节(Byte)概念对齐,简化软件处理。

  3. 停止位(Stop Bits) :标志一个字符传输结束的高电平持续时间,可设为1、1.5或2位。1位停止位最常用,它确保在下一个字符的起始位到来前,线路有足够时间恢复到空闲高电平状态。

  4. 校验位(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配置也无法保证通信的长期可靠性。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐