3、RS-485与Modbus:差分信号、帧结构与功能码

各位同学,今天我们来聊聊工业自动化里最经典的一对搭档——RS-485和Modbus。说实话,这两个东西几乎绑在一起出现,你搞自动化,绕不开它们。我最早接触这俩,是在一个污水处理项目上,当时被现场干扰搞得焦头烂额,后来才真正理解了RS-485差分信号的厉害之处。

3.1 RS-485差分信号原理

先说说RS-485。它本质上是一种物理层标准,定义了电气特性。说白了,就是规定信号怎么在线上传输。

RS-485用的是差分信号传输。什么叫差分?就是一根信号用两条线来传,一条叫A(或D+),一条叫B(或D-)。接收端看的是A和B之间的电压差,而不是对地的绝对电压。

  • 逻辑1:A线电压比B线电压高(通常高200mV以上)
  • 逻辑0:A线电压比B线电压低(通常低200mV以上)

为什么用差分?抗干扰能力强。你想想看,外部噪声进来,通常是共模噪声,同时叠加在A和B两条线上。接收端看的是差值,噪声就被抵消掉了。我在一个变频器密集的车间里测过,单端信号(比如RS-232)根本没法用,换成RS-485就稳得很。

关键参数:RS-485支持多点通信,一条总线上最多可以挂32个节点(标准负载),实际中我用过挂到50多个的,但需要加中继器。传输距离最远可达1200米,速率最高10Mbps(距离越短速率越高)。

我的经验:布线时A和B线一定要双绞,绞距越密越好。终端电阻也很关键,长线传输时必须在总线两端各加一个120欧姆电阻,否则信号反射会让你抓狂。

3.2 Modbus RTU帧结构

RS-485只负责把比特流从A点搬到B点,但搬的是什么内容,它不管。Modbus就是定义这个内容的协议。Modbus RTU是其中最常用的模式,用二进制编码,效率高。

一个完整的Modbus RTU帧长这样:

| 地址码 | 功能码 | 数据区 | CRC校验 |
| 1字节  | 1字节  | N字节  | 2字节   |

我来拆开讲讲:

  • 地址码:从站地址,范围1-247。0是广播地址,所有从站都接收但不回复。
  • 功能码:告诉从站要干什么,比如读线圈、写寄存器。
  • 数据区:具体参数,比如起始地址、数据个数、要写入的值。
  • CRC校验:循环冗余校验,保证数据没被篡改。这个很重要,我曾经遇到过CRC算错导致通信时好时坏的情况,排查了一整天。

帧与帧之间必须有至少3.5个字符时间的静默间隔,用来区分不同的帧。这个时间跟波特率有关,9600波特率下大约是3.5ms。嗯,这里要注意,如果间隔太短,接收端会把两帧当成一帧处理,数据就乱了。

避坑指南:我曾经在一个项目中,因为主站发送间隔没控制好,导致从站频繁报错。后来用示波器一量,发现帧间隔只有2ms,不符合3.5字符时间的要求。调整后问题解决。

3.3 功能码详解

功能码是Modbus的核心。常用的就那么几个,我列个表,大家一目了然:

功能码 名称 作用 数据区内容
01 (0x01) 读线圈 读取DO(数字量输出)状态 起始地址 + 数量
02 (0x02) 读离散输入 读取DI(数字量输入)状态 起始地址 + 数量
03 (0x03) 读保持寄存器 读取AO(模拟量输出)或参数 起始地址 + 数量
04 (0x04) 读输入寄存器 读取AI(模拟量输入)值 起始地址 + 数量
05 (0x05) 写单线圈 控制单个DO 线圈地址 + 值(0xFF00/0x0000)
06 (0x06) 写单寄存器 写入单个AO或参数 寄存器地址 + 值
15 (0x0F) 写多线圈 批量控制DO 起始地址 + 数量 + 字节数 + 数据
16 (0x10) 写多寄存器 批量写入AO或参数 起始地址 + 数量 + 字节数 + 数据

我重点说说最常用的03和06功能码。

03功能码(读保持寄存器):这是最常用的读操作。比如你要读一个温度传感器的值,它存在保持寄存器地址100里。主站发:

01 03 00 64 00 01 C5 B5
|  |  |     |     |
地址 功能码 起始地址 数量  CRC
地址100=0x0064  读1个寄存器

从站回复:

01 03 02 01 2C B8 14
|  |  |  |
地址 功能码 字节数 数据(0x012C=300)

你看,温度值是300,如果量程是0-100度,那实际温度就是30.0度。具体怎么换算,得看设备手册。

06功能码(写单寄存器):比如你要把PID参数写入寄存器200:

01 06 00 C8 03 E8 89 2D
|  |  |     |
地址 功能码 地址  值(0x03E8=1000)

从站成功后会原样回复这帧数据,表示写入成功。

我的习惯:调试时先用03功能码读一遍所有寄存器,确认通信正常,再用06写。这样能快速定位问题是出在通信上还是设备本身。

最后说一句,Modbus RTU的CRC计算有点麻烦,但几乎所有编程语言都有现成的库。我早期手算过几次,后来再也不干了,直接用现成的函数。你想想看,人工算CRC,算错一次就得排查半天,何必呢?

好了,RS-485和Modbus RTU的核心内容就这些。下一章我们讲Modbus TCP,看看它跟RTU有什么不同,以及怎么在以太网上跑Modbus。