第3章 串口通信基础:RS-232/RS-485标准、串口参数、Python的pySerial库
各位同学,今天我们来聊聊串口通信。说实话,这可能是整个自动化控制领域里最「老」但也是最「硬核」的技术之一。我入行那会儿,串口就像工程师的「第三只手」——调试设备、读取数据、下发指令,哪样都离不开它。哪怕到了今天,工业现场里RS-485总线依然随处可见,很多高端分析仪器也保留着串口作为标配接口。
为什么?因为串口通信简单、可靠、成本低。你想想看,两根线就能搞定双向数据传输,这在很多恶劣的工业环境下简直是救命稻草。好,我们直接进入正题。
3.1 RS-232 与 RS-485:两种经典标准
先说说RS-232。这是最早的个人计算机串口标准,你以前电脑屁股后面那个9针的D型接口,就是它。RS-232的特点是「单端传输」,说白了就是一根信号线对地线,电压差来代表逻辑0和1。
我在项目中遇到过一个问题:用RS-232连接一台老式pH计,距离也就5米,但数据总是丢包。后来发现是线缆屏蔽没做好,工频干扰直接串进去了。RS-232的抗干扰能力确实弱,传输距离一般不超过15米。所以它更适合短距离、一对一通信的场景,比如调试口、配置口。
再来看RS-485。这才是工业现场的「老黄牛」。它采用差分信号传输,两根线(A和B)之间的电压差来判断逻辑状态。抗干扰能力比RS-232强了不止一个档次。传输距离能到1200米,而且支持多点通信——一条总线上可以挂32个设备(现在有些芯片能挂256个)。
我记得有一次给一个水处理项目做改造,现场有20多台在线分析仪,全部通过RS-485总线连到一台工控机上。布线的时候我特意强调了终端电阻和偏置电阻的匹配,结果调试时一次通过。嗯,这里要注意:RS-485总线两端必须各加一个120欧姆的终端电阻,否则信号反射会让你怀疑人生。
| 参数 | RS-232 | RS-485 |
|---|---|---|
| 传输方式 | 单端 | 差分 |
| 最大距离 | 约15米 | 约1200米 |
| 节点数 | 1对1 | 最多256个 |
| 抗干扰 | 弱 | 强 |
| 典型应用 | 调试口、短距通信 | 工业总线、仪器网络 |
核心要点:RS-232适合短距一对一,RS-485适合长距多设备。选型时先看距离和节点数,再看现场干扰情况。
3.2 串口参数:波特率、数据位、停止位、校验位
串口通信就像两个人打电话,必须约定好「语速」「每句话的长度」「句号怎么表示」「要不要纠错」。这些约定就是串口参数。
波特率:说白了就是每秒传输多少个比特。常见的值有9600、19200、38400、115200。我个人的习惯是:能用115200就不用9600,因为速度快意味着采样周期短,实时性更好。但要注意,波特率越高,对线缆质量和距离越敏感。我曾经在一条50米的RS-485线路上试过115200,结果误码率飙升,降到38400就稳了。
数据位:通常是7位或8位。7位用于传输ASCII字符(比如文本数据),8位用于传输二进制数据(比如仪器读数)。现在绝大多数设备都用8位,除非你遇到那种老掉牙的ASCII协议设备。
停止位:表示一个字节传输结束的标志。有1位、1.5位、2位三种。1位最常用,2位用于慢速设备或时钟不准的场景。我建议你默认用1位,除非设备手册明确要求2位。
校验位:用于简单的错误检测。有奇校验、偶校验、无校验三种。奇校验就是让数据位+校验位里1的个数为奇数,偶校验就是偶数。说实话,这个校验能力很弱,只能检测奇数个比特的错误。在工业现场,我更推荐用无校验,然后在应用层做CRC校验,那才叫靠谱。
我的经验:调试串口时,先确认波特率,再检查数据位和停止位。校验位如果拿不准,先设成「无」。很多设备默认是9600、8、1、N(无校验),你可以先试试这个组合。
3.3 Python的pySerial库:让串口编程变得简单
好,理论讲完了,我们来点实际的。Python里操作串口,pySerial是事实上的标准库。它封装了底层的系统调用,你只需要几行代码就能打开串口、收发数据。
先安装:
pip install pyserial
然后看一个最基本的例子:
import serial
# 打开串口
ser = serial.Serial(
port='COM3', # Windows下用COM口,Linux下用/dev/ttyUSB0
baudrate=9600,
bytesize=8,
parity='N', # 'N'无校验, 'E'偶校验, 'O'奇校验
stopbits=1,
timeout=1 # 读取超时,单位秒
)
# 发送数据
ser.write(b'AT\r\n')
# 读取数据
response = ser.read(100) # 读取最多100字节
print(response)
# 关闭串口
ser.close()
你想想看,就这么几行代码,就能和一台分析仪器对话了。我在做水质在线监测项目时,就是用这个库轮询读取20多台仪器的数据,每台仪器一个串口参数配置,存成一个字典,循环遍历。
这里有个坑:timeout参数一定要设。如果不设,read()会一直阻塞,程序就卡死了。我曾经犯过这个错,调试时半天没反应,还以为是硬件坏了。
再来看一个更实用的例子——持续读取:
import serial
import time
ser = serial.Serial('COM3', 9600, timeout=0.5)
while True:
# 检查是否有数据可读
if ser.in_waiting > 0:
data = ser.readline() # 读取一行,直到换行符
print(f"收到: {data.decode('utf-8').strip()}")
time.sleep(0.1)
这个模式在工业现场很常用。仪器会主动上报数据,或者你下发查询指令后等待回复。用readline()可以方便地处理以换行符结尾的文本协议。
注意:串口通信没有「连接」的概念,你打开串口时设备不一定在线。所以一定要做超时处理和重试机制。我曾经见过一个同事的程序,串口线松了之后程序直接卡死,整个产线停了10分钟。
3.4 实战建议:串口调试三板斧
最后,我分享几个调试串口的小技巧,都是血泪换来的:
- 先用串口调试助手验证:不要一上来就写代码。先用SSCOM、Putty之类的工具手动发几个指令,确认设备能正常回复。这一步能排除90%的硬件问题。
- 注意线序:RS-232的2脚是RXD,3脚是TXD,5脚是GND。RS-485的A和B不要接反。我见过有人把A和B接反了,折腾了两天才发现。
- 加日志:在代码里把发送和接收的原始数据都打印出来,用十六进制显示。很多协议问题看ASCII是看不出来的。
好了,这一章的内容就到这里。串口通信看似简单,但它是自动化控制的基石。下一章我们会讲Modbus协议——工业现场最通用的串口应用层协议。到时候你会发现,今天学的这些参数设置,全都能用上。
公众号:蓝海资料掘金营,微信deep3321