2. 物理层与数据链路层:RS-232/RS-485/RS-422标准对比、UART帧结构、波特率与误码率、Modbus RTU协议帧格式
各位工程师朋友,咱们今天聊点实在的。做自控系统,物理层和数据链路层是绕不开的坎。我见过太多项目,协议栈写得天花乱坠,结果现场跑起来全是乱码——最后发现是RS-485的A/B线接反了。嗯,这种坑,踩过一次就忘不了。
2.1 RS-232 / RS-485 / RS-422 标准对比
这三个标准,说白了就是物理层的“方言”。它们定义了电压、线缆、距离这些硬指标。我个人习惯,选型时先看三个参数:传输距离、抗干扰能力、节点数量。
| 特性 | RS-232 | RS-422 | RS-485 |
|---|---|---|---|
| 传输方式 | 单端(不平衡) | 差分(平衡) | 差分(平衡) |
| 最大距离 | 约15米 | 约1200米 | 约1200米 |
| 最大节点数 | 1对1 | 1发10收 | 32个(标准) |
| 电压范围 | ±3V ~ ±15V | ±2V ~ ±6V | ±1.5V ~ ±6V |
| 抗干扰能力 | 弱 | 强 | 强 |
| 典型应用 | 调试口、短距 | 工业长距点对点 | 多节点总线 |
核心结论:RS-232适合桌面级调试,RS-422适合一对多长距,RS-485是工业总线的主力。你想想看,现在哪个PLC不挂个485口?
我在项目中遇到过一件事:一个污水处理厂,用了RS-232连接PLC和触摸屏,距离也就20米,结果数据天天丢包。后来换成RS-422,问题立刻消失。为什么?因为现场有大功率变频器,共模干扰太强了。差分信号天生就能抑制共模噪声,这是物理层的优势。
2.2 UART帧结构
UART是串行通信的“骨架”。不管你是RS-232还是RS-485,底层都是UART在干活。一个标准的UART帧长这样:
起始位(1bit) + 数据位(5~8bit) + 校验位(0/1bit) + 停止位(1/1.5/2bit)
举个例子,最常用的8N1配置:
- 起始位:1个低电平,告诉接收方“我要开始发了”
- 数据位:8位,LSB先发(最低有效位优先)
- 校验位:无(N表示None)
- 停止位:1个高电平,表示“这帧结束”
避坑指南:我曾经调试一个设备,怎么都收不到正确数据。查了半天,发现发送方配的是7位数据位,接收方配的是8位。你想想看,数据位对不上,校验位再对也没用。所以,通信前第一件事:核对UART参数。
这里有个细节:起始位和停止位是硬件自动处理的,你写代码时只需要关心数据位和校验位。但波特率必须两边一致,否则就是鸡同鸭讲。
2.3 波特率与误码率
波特率,就是每秒传输的符号数。对于UART来说,一个符号就是一个bit。所以9600波特率,就是每秒传9600个bit。但注意,这9600个bit里包含了起始位、停止位这些开销。实际有效数据速率要打个折扣。
举个例子:8N1配置,每帧10个bit(1起始+8数据+1停止)。波特率9600时,每秒能传960帧,有效数据是960×8=7680字节/秒。嗯,这个数要记牢,算通信负荷时经常用。
误码率,说白了就是传错的概率。为什么会出错?三个原因:
- 时钟偏差:发送方和接收方的晶振不可能完全一样。我见过用内部RC振荡器的单片机,误差能到5%,跑115200波特率时基本没法用。
- 信号衰减:线太长、干扰太大,波形变形了。
- 采样点偏移:UART在数据位的中间采样,如果时钟偏差大,采样点会滑到边缘,导致误码。
注意:波特率越高,对时钟精度要求越高。9600波特率允许±2%的误差,115200就只能容忍±0.5%了。所以工业现场,我建议别超过38400。稳定第一,速度第二。
2.4 Modbus RTU协议帧格式
Modbus RTU是工业自动化领域的事实标准。它跑在RS-485上,用主从模式通信。一个完整的RTU帧长这样:
地址码(1字节) + 功能码(1字节) + 数据区(N字节) + CRC校验(2字节)
咱们拆开看:
- 地址码:0x01~0xF7,从站地址。0x00是广播地址,所有从站都要响应。
- 功能码:比如0x03读保持寄存器,0x06写单个寄存器,0x10写多个寄存器。
- 数据区:根据功能码不同,长度可变。比如读寄存器时,这里包含起始地址和寄存器数量。
- CRC校验:16位循环冗余校验,低字节在前,高字节在后。
举个例子,读从站1的保持寄存器,从地址0x0000开始读2个寄存器:
请求帧:01 03 00 00 00 02 C4 0B
响应帧:01 03 04 00 01 00 02 79 85
解释一下:请求帧里,01是地址,03是功能码,00 00是起始地址,00 02是数量,C4 0B是CRC。响应帧里,01是地址,03是功能码,04是数据字节数(2个寄存器×2字节=4字节),00 01和00 02是寄存器值,79 85是CRC。
关键点:Modbus RTU帧之间必须有3.5个字符时间的静默间隔。这是协议规定的帧分隔符。我曾经调试一个系统,数据一直粘包,最后发现是主机发送间隔太短,从机来不及区分帧边界。加个延时就好了。
另外,CRC计算是Modbus RTU的难点。很多新手直接抄网上的代码,结果校验不对。我建议自己手算一遍,理解多项式0x8005的移位过程。嗯,这个坑我踩过,所以多说一句。
2.5 知识体系总览
下面这张图,把本章的核心逻辑串起来了。从物理层的RS-485,到数据链路层的UART帧,再到应用层的Modbus RTU,一层一层往上走。
说白了,物理层决定了你能不能传得远、抗不抗干扰;数据链路层决定了数据怎么打包、怎么同步;应用层决定了数据怎么解释、怎么交互。三层缺一不可。
我个人习惯,做项目时先定物理层——用RS-485还是RS-422?距离多远?节点多少?然后配UART参数——波特率、数据位、校验位。最后才是写Modbus协议栈。顺序搞反了,后面全是坑。
经验之谈:如果你刚开始接触自控通信,建议从RS-485 + Modbus RTU入手。这是最成熟、资料最多的组合。先跑通一个读寄存器的例子,再慢慢扩展。别一上来就搞自定义协议,那是在给自己挖坑。
好了,这一章的内容就到这儿。物理层和数据链路层是通信的根基,基础不牢,地动山摇。下一章咱们聊聊更高级的协议——但那是后话了。
公众号:蓝海资料掘金营,微信deep3321