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字节/秒。嗯,这个数要记牢,算通信负荷时经常用。

误码率,说白了就是传错的概率。为什么会出错?三个原因:

  1. 时钟偏差:发送方和接收方的晶振不可能完全一样。我见过用内部RC振荡器的单片机,误差能到5%,跑115200波特率时基本没法用。
  2. 信号衰减:线太长、干扰太大,波形变形了。
  3. 采样点偏移: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,一层一层往上走。

自控系统通信协议栈(本章核心) 应用层:Modbus RTU协议帧 地址码 + 功能码 + 数据区 + CRC校验 数据链路层:UART帧结构 起始位 + 数据位(8bit) + 校验位(无) + 停止位(1bit) 物理层:RS-232 / RS-422 / RS-485 差分信号 / 单端信号 / 抗干扰 / 距离 / 节点数 关键参数:波特率(9600~115200) | 误码率 | 时钟精度 注意:波特率越高,对时钟精度要求越高,误码率越大

说白了,物理层决定了你能不能传得远、抗不抗干扰;数据链路层决定了数据怎么打包、怎么同步;应用层决定了数据怎么解释、怎么交互。三层缺一不可。

我个人习惯,做项目时先定物理层——用RS-485还是RS-422?距离多远?节点多少?然后配UART参数——波特率、数据位、校验位。最后才是写Modbus协议栈。顺序搞反了,后面全是坑。

经验之谈:如果你刚开始接触自控通信,建议从RS-485 + Modbus RTU入手。这是最成熟、资料最多的组合。先跑通一个读寄存器的例子,再慢慢扩展。别一上来就搞自定义协议,那是在给自己挖坑。

好了,这一章的内容就到这儿。物理层和数据链路层是通信的根基,基础不牢,地动山摇。下一章咱们聊聊更高级的协议——但那是后话了。


公众号:蓝海资料掘金营,微信deep3321