3、串口通信基础:串口原理、RS232/RS485/TTL区别、波特率、数据位、停止位、校验位等参数详解

串口通信(UART,Universal Asynchronous Receiver/Transmitter)是硬件控制领域最基础、最常用的通信方式。无论是单片机与传感器交互、PLC与上位机对接,还是嵌入式设备调试,串口都扮演着不可替代的角色。与SPI、I2C等同步通信不同,UART属于异步串行通信,收发双方不需要共享时钟信号,而是通过预先约定好的波特率、数据帧格式来完成数据解析。理解串口原理、电气标准差异以及帧参数配置,是后续实现Python串口编程、设备自动化控制的前提。本章将从物理层原理出发,系统拆解RS232、RS485、TTL三种电气标准的区别,并深入讲解波特率、数据位、停止位、校验位等关键参数的实际配置逻辑。

UART串口通信链路与参数配置关系图 发送端 MCU UART_TX GND TTL: 0V / 3.3V~5V (MCU直接输出) 电平转换/驱动芯片 MAX232 / MAX485 / SP3485 TTL ⇄ RS232 / RS485 RS232: ±3V~±15V RS485: 差分 A/B 0.2V~6V 接收端设备 UART_RX GND TX GND RS232/RS485 GND/参考地 UART 数据帧格式(以 8N1 为例) 起始位 0 数据位 bit0~bit7 校验位 可选 停止位 1/1.5/2 空闲位 高电平 波特率:9600 / 115200 / 460800 ... 数据位:5/6/7/8 校验位:None/Even/Odd

3.1 串口通信核心原理:异步收发与帧同步机制

UART通信的本质是异步串行数据传输。所谓“异步”,是指收发双方不共享时钟信号,而是各自使用独立的时钟源,通过约定相同的波特率来保证每一位数据的时长一致。发送端按照约定的时间间隔逐位发送数据,接收端在检测到起始位后,按照相同的时间间隔采样数据线,从而恢复出完整的数据帧。

UART的数据帧结构是通信的基础。一个完整的数据帧由以下部分组成:

  • 起始位(Start Bit):线路空闲时为高电平,发送端拉低一个位时间,表示“开始发送”。接收端正是通过检测这个下降沿来同步采样时钟。
  • 数据位(Data Bits):紧跟在起始位之后,通常为5~8位,低位在前(LSB First)。数据位是实际要传输的有效载荷。
  • 校验位(Parity Bit):可选字段,用于简单的错误检测。偶校验(Even)保证数据位+校验位中“1”的个数为偶数;奇校验(Odd)则保证为奇数。
  • 停止位(Stop Bit):数据帧结束标志,必须为高电平,持续1、1.5或2个位时间。停止位为接收端提供帧边界,也用于区分下一帧的起始位。

从时序角度看,UART的每一位持续时间由波特率决定。例如波特率为9600bps时,每位持续约104.2微秒;波特率为115200bps时,每位约8.68微秒。接收端在起始位下降沿后,通常会在每位的中点附近采样,以避开信号跳变区域,提高采样可靠性。

核心理解:UART的“异步”并不意味着没有时序约束,而是将时钟同步的责任转移到了“波特率一致”和“起始位触发”这两个机制上。收发双方必须使用完全相同的波特率,且允许存在一定误差(通常不超过±2%),否则长时间传输会导致位偏移累积,最终产生乱码。

3.2 RS232、RS485、TTL三种电气标准对比与选型

UART协议定义了数据帧的逻辑格式,但物理层信号的电压水平、传输距离、抗干扰能力则由电气标准决定。在实际项目中,最常遇到的三种标准是TTL、RS232和RS485。三者的核心差异如下表所示:

对比维度 TTL电平 RS232 RS485
逻辑1电平 2.4V~5V(取决于VCC) -3V ~ -15V A-B 电压差 > +0.2V
逻辑0电平 0V ~ 0.5V +3V ~ +15V A-B 电压差 < -0.2V
传输方式 单端,参考GND 单端,参考GND 差分,A/B双线
最大传输距离 约1米(板级) 约15米(9600bps) 约1200米(9600bps)
最大节点数 1对1 1对1 最多32个(标准)/ 128个(扩展)
抗干扰能力 弱 中等 强(差分信号)
典型应用 MCU与板载传感器、调试串口 工业设备调试口、老式工控机 工业现场总线、多设备组网

3.2.1 TTL电平:板级通信的默认选择

TTL(Transistor-Transistor Logic)电平是MCU、传感器、树莓派GPIO等设备直接输出的信号标准。逻辑0对应0V附近,逻辑1对应3.3V或5V。TTL信号是单端信号,依赖共地参考,因此传输距离短,容易受噪声干扰。在Python硬件控制中,使用USB转TTL模块(如CH340、CP2102)连接单片机调试串口时,就是典型的TTL通信场景。

3.2.2 RS232:传统工控设备的“老将”

RS232标准诞生于1962年,采用负逻辑:逻辑1为-3V~-15V,逻辑0为+3V~+15V。这种电压摆幅设计使得RS232比TTL具有更强的抗干扰能力,传输距离可达15米左右。但RS232同样是单端信号,且只能点对点通信。许多老式PLC、工业仪表、路由器控制台仍保留RS232接口。由于MCU输出的是TTL电平,两者之间需要通过MAX232等芯片进行电平转换。

3.2.3 RS485:工业现场总线的主力

RS485采用差分信号传输,使用A、B两根线,逻辑状态由两线之间的电压差决定。这种设计带来了两个显著优势:一是共模噪声被抑制,抗干扰能力大幅提升;二是支持多点组网,一条总线上最多可挂接32个标准节点。RS485的传输距离在9600bps下可达1200米,非常适合工业自动化场景。RS485通常还需要在总线两端并联120Ω终端匹配电阻,以减少信号反射。

选型建议:板级调试优先用TTL;短距离点对点且设备自带RS232口时用RS232;工业现场、长距离、多节点组网时选RS485。Python中通过pyserial操作这三种标准的方式完全一致,差异仅在硬件转换层。

3.3 串口参数详解:波特率、数据位、停止位、校验位

在Python的pyserial库中,打开串口时需要指定一组参数,这些参数必须与对端设备完全一致,否则通信失败。下面逐一拆解每个参数的含义与配置要点。

3.3.1 波特率(Baud Rate)

波特率表示每秒传输的符号数,单位为bps(bits per second)。常见波特率有9600、19200、38400、57600、115200、460800等。波特率越高,传输速度越快,但对线路质量和时钟精度要求也越高。需要注意的是,波特率不仅影响数据位,还影响起始位、停止位和校验位的时长,因此实际有效数据吞吐量需要扣除这些开销。

例如,使用115200bps、8N1格式(8数据位、无校验、1停止位),每帧共10位(1起始+8数据+1停止),实际有效数据速率约为11520字节/秒。如果改用9600bps,则有效速率约为960字节/秒。

3.3.2 数据位(Data Bits)

数据位定义了每个帧中实际承载数据的位数,可选值为5、6、7、8。现代设备几乎都使用8位数据位,因为一个字节正好是8位。7位数据位通常用于ASCII码传输(0~127),在老旧的电传打字机或某些特殊协议中才会用到。Python的pyserial中通过bytesize=serial.EIGHTBITS或serial.SEVENBITS设置。

3.3.3 停止位(Stop Bits)

停止位表示帧结束后的高电平持续时间,可选1、1.5或2位。停止位越长,接收端越容易识别帧边界,但传输效率越低。绝大多数设备使用1位停止位。1.5位停止位仅在某些老式设备中出现,2位停止位常见于低速、噪声较大的环境。pyserial中通过stopbits=serial.STOPBITS_ONE或serial.STOPBITS_TWO设置。

3.3.4 校验位(Parity Bit)

校验位用于检测传输过程中的单比特错误。三种常见模式:

  • 无校验(None):不发送校验位,帧格式为8N1(8数据位、无校验、1停止位),这是最常用的配置。
  • 偶校验(Even):保证数据位+校验位中“1”的总数为偶数。例如数据位为0x53(0101 0011,含4个1),则校验位为0。
  • 奇校验(Odd):保证“1”的总数为奇数。

校验位只能检测奇数个比特错误,无法纠错,也无法检测偶数个比特错误。对于可靠性要求高的场景,建议在应用层增加CRC校验。

常见误区:很多初学者认为“波特率越高越好”。实际上,如果对端设备只支持9600bps,强行设置为115200会导致完全无法通信。另外,USB转串口模块的驱动默认参数通常是9600/8N1,如果设备手册要求其他参数,务必在Python代码中显式指定,不要依赖默认值。

3.4 实战场景:配置USB转串口模块与设备通信

下面通过一个完整的案例,演示如何在实际项目中确定并配置串口参数。假设我们需要连接一台工业称重仪表,仪表背面标注通信参数为“9600, 8, E, 1”(即9600bps、8数据位、偶校验、1停止位)。

第一步:确认硬件连接。使用USB转RS485模块连接仪表,A线接A端,B线接B端,并确认模块供电正常。在设备管理器中查看模块对应的COM口号(如COM5)。

第二步:编写Python测试代码。使用pyserial打开串口,发送读取命令(假设仪表协议要求发送十六进制帧 01 03 00 00 00 02 C4 0B):

import serial
import time

ser = serial.Serial(
    port='COM5',
    baudrate=9600,
    bytesize=serial.EIGHTBITS,
    parity=serial.PARITY_EVEN,
    stopbits=serial.STOPBITS_ONE,
    timeout=2
)

# 发送读取命令
cmd = bytes.fromhex('01 03 00 00 00 02 C4 0B')
ser.write(cmd)

# 读取响应
resp = ser.read(20)
print('响应数据:', resp.hex())

ser.close()

第三步:分析响应数据。如果返回的数据帧符合仪表协议(如 01 03 04 00 01 02 03 xx xx),说明参数配置正确。如果返回空数据或乱码,则依次检查:波特率是否匹配、校验位是否正确、A/B线是否接反、终端电阻是否缺失。

第四步:异常排查。若通信不稳定,使用示波器或逻辑分析仪观察A/B线波形,确认差分信号幅值是否在0.2V以上。同时检查总线两端是否各并联了一个120Ω终端电阻。

案例复盘:在一次实际项目中,某工程师将RS485的A/B线接反,导致通信完全失败。由于RS485是差分信号,A/B反接会使逻辑电平反转,接收端无法解析数据。排查时通过万用表测量A-B电压差,发现空闲时电压为负值,正常应为正值,从而快速定位问题。这个案例说明,硬件接线错误往往比软件参数错误更隐蔽,需要结合电气测量来排查。

3.5 常见误区与总结复盘

在串口通信的学习和实践中,以下误区值得特别注意:

  • 误区一:忽略共地。TTL和RS232都是单端信号,收发双方必须共地。如果两个设备使用独立电源且未连接GND,信号参考点不一致,会导致通信异常甚至损坏端口。
  • 误区二:混淆逻辑电平。TTL的高电平是正电压,而RS232的高电平是负电压。直接用TTL电平连接RS232接口会烧毁设备,必须经过电平转换芯片。
  • 误区三:忽视波特率误差。USB转串口模块的晶振精度通常为±1%,如果对端设备使用劣质晶振,累计误差可能超过2%,导致长数据帧传输出错。
  • 误区四:盲目使用最高波特率。在长线传输或电磁干扰较强的环境中,过高的波特率会显著增加误码率。工业现场建议优先使用9600或19200。