一、Modbus协议概述

各位工程师朋友,大家好。我是老张,在工业自动化这行摸爬滚打了十几年。今天咱们开始聊Modbus协议,这是咱们调试仪表时绕不开的东西。说实话,我刚入行那会儿也被这协议搞得一头雾水,后来踩了不少坑才慢慢摸清门道。这一章,我就把Modbus协议的来龙去脉、应用场景和协议栈结构给大家捋清楚。

1.1 Modbus协议发展史

Modbus协议是1979年由Modicon公司(就是现在的施耐德电气)发明的。你想想看,那会儿个人电脑都还没普及呢。当时Modicon为了让自己家的PLC能互相通信,就搞了这么个简单实用的协议。

我记得第一次接触Modbus是在2008年,调试一个水处理项目。那会儿设备说明书上写着"支持Modbus RTU",我心想这什么玩意儿?后来一查才知道,这协议已经快30岁了。

Modbus协议的发展有几个关键节点:

  • 1979年:Modicon公司发布Modbus协议,最初用于PLC之间的串行通信
  • 1990年代:随着工业自动化发展,Modbus成为事实上的工业通信标准
  • 2000年:施耐德电气将Modbus协议公开,成为免费开放的协议
  • 2007年:Modbus TCP/IP标准发布,适应以太网通信需求
  • 至今:Modbus依然是工业仪表、PLC、DCS系统最常用的通信协议之一

为什么Modbus能活这么久?说白了就三个字:简单、开放、可靠。我见过不少号称"更先进"的协议,最后都死在了复杂性和封闭性上。Modbus就像工业界的"普通话",谁都能用,谁都会用。

1.2 Modbus协议在工业自动化中的应用场景

Modbus协议的应用场景,我给大家归纳成三类:

1.2.1 现场设备数据采集

这是最常见的场景。比如你有一堆传感器、变送器、执行器,需要把数据传到PLC或上位机。Modbus RTU通过RS-485总线,一根线就能挂载247个设备。我在一个污水处理厂项目中,就用Modbus RTU挂了30多台仪表,包括pH计、流量计、液位计,跑了好几年没出过问题。

1.2.2 控制系统与仪表通信

PLC、DCS、SCADA系统跟现场仪表之间的"对话",基本都靠Modbus。举个例子,你有一个西门子S7-1200 PLC,要读取一个E+H的电磁流量计数据。只要两边都支持Modbus,配置一下寄存器地址,数据就过来了。

1.2.3 设备调试与维护

这个我特别有感触。现场调试时,用笔记本电脑接个USB转RS-485转换器,打开Modbus调试工具(比如ModScan),就能直接读写仪表内部参数。我曾经用这个方法,帮一个客户远程排查了300公里外的仪表故障,省了一大笔差旅费。

我的经验:调试时一定要带一个USB转RS-485转换器,最好选FTDI芯片的,兼容性好。便宜的CH340芯片有时候会掉线,现场出问题很麻烦。

1.3 Modbus协议栈结构

Modbus协议栈分为三层:物理层、数据链路层、应用层。我画了一张图,大家一看就明白。

Modbus协议栈结构 应用层 (Application Layer) Modbus应用协议:功能码、寄存器地址、数据格式 数据链路层 (Data Link Layer) 报文封装、地址寻址、差错校验(CRC/LRC) 物理层 (Physical Layer) RS-232 / RS-485 / 以太网 OSI第7层 OSI第2层 OSI第1层

1.3.1 物理层

物理层决定了数据怎么在线上传输。Modbus支持三种物理接口:

接口类型 传输介质 最大距离 最大节点数 典型速率
RS-232 双绞线(点对点) 15米 2个 19.2 kbps
RS-485 双绞线(总线型) 1200米 32个(可扩展至247) 9.6 kbps ~ 115.2 kbps
以太网 网线(星型) 100米(交换机级联可扩展) 理论无限制 10/100 Mbps

注意:RS-485总线一定要接终端电阻!我曾经在一个项目中,因为没接120欧姆终端电阻,信号反射导致通信时断时续,排查了两天才找到原因。嗯,从那以后我每次布线都会检查终端电阻。

1.3.2 数据链路层

数据链路层负责把数据打包成"帧",然后发出去。Modbus RTU的帧结构是这样的:

Modbus RTU 报文帧格式:
+----------+----------+----------+----------+----------+
| 地址码   | 功能码   | 数据区   | CRC低字节 | CRC高字节 |
| 1字节    | 1字节    | N字节    | 1字节     | 1字节     |
+----------+----------+----------+----------+----------+

示例:读取从站地址为1的保持寄存器
请求帧:01 03 00 00 00 02 C4 0B
  - 01:从站地址
  - 03:功能码(读取保持寄存器)
  - 00 00:起始寄存器地址(0x0000)
  - 00 02:读取2个寄存器
  - C4 0B:CRC校验

这里有个关键点:Modbus RTU的报文之间要有3.5个字符时间的静默间隔。如果间隔太短,从站会认为报文还没结束;间隔太长,从站会认为总线空闲。我调试时经常用示波器看波形,确认帧间隔是否合规。

1.3.3 应用层

应用层定义了"读什么"和"写什么"。Modbus定义了四种基本数据对象:

对象类型 访问方式 数据大小 典型用途
线圈 (Coil) 读写 1位 开关量输出(继电器、指示灯)
离散输入 (Discrete Input) 只读 1位 开关量输入(按钮、限位开关)
输入寄存器 (Input Register) 只读 16位 模拟量输入(温度、压力、流量)
保持寄存器 (Holding Register) 读写 16位 参数设置、累计量、控制指令

常用的功能码就那么几个:

  • 01 (0x01):读取线圈状态
  • 02 (0x02):读取离散输入
  • 03 (0x03):读取保持寄存器(最常用)
  • 04 (0x04):读取输入寄存器
  • 05 (0x05):写单个线圈
  • 06 (0x06):写单个保持寄存器
  • 15 (0x0F):写多个线圈
  • 16 (0x10):写多个保持寄存器

避坑指南:我曾经遇到一个仪表,手册上写寄存器地址是40001,但用Modbus工具读出来却是0。后来才明白,PLC的地址是从1开始编号的,而Modbus协议里的地址是从0开始的。40001对应协议地址0x0000。这个坑很多新手都会踩,大家注意一下。

好了,这一章的内容就到这里。Modbus协议看似简单,但实际调试中会遇到各种问题。下一章我会详细讲Modbus RTU和Modbus TCP的区别,以及怎么根据现场情况选择合适的通信方式。咱们下章见。


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