Modbus是一种串行通信协议,由Modicon公司(现在的施耐德电气Schneider Electric)于1979年发布,用于可编程逻辑控制器(Programmable logic controllers,PLCs)。Modbus事实上已经成为工业领域通信协议的业界标准,并且现在是工业电子设备之间常用的连接方式。 在工业应用场景中使用Modbus的主要原因是:
Modbus支持多个设备连接到同一网络上进行通信,例如,一个能测量温度和湿度并将结果传送给计算机的装置。在数据采集与监视控制(Supervisory control and data acquisition, SCADA)系统中,Modbus常用于连接监控计算机与远程终端设备(Remote terminal unit,RTU)。许多数据类型是根据梯形逻辑及其驱动继电器在工业上的使用而得名的:单比特物理输出称为线圈,单比特物理输入称为离散输入或触点。
自2004年4月施耐德电气将权利转让给Modbus组织以来,该组织一直管理着Modbus协议的开发和更新。[1] Modbus组织是一个倡导持续使用该技术的协会,其由兼容Modbus设备的用户和供应商组成。[2]
以下是Modbus主机访问从机的对象类型表:
对象类型 | 权限 | 数据大小 |
---|---|---|
线圈 | 读写 | 1位 |
离散输入 | 只读 | 1位 |
输入寄存器 | 只读 | 16位 |
保持寄存器 | 读写 | 16位 |
Modbus协议目前存在多个用于串行端口、以太网和其他支持互联网协议套件的网络版本。Modbus协议有许多变体:
对于协议的前4个变体,在数据模型和函数调用上都是相同的;只有封装方式不同。然而,变体是不可互操作的,帧格式也是如此。
每个打算使用Modbus通信的设备都将分配一个唯一的地址。在串行和MB+网络中,只有被指定为主节点的节点可以发起命令。在以太网上,任何设备都可以发出一个Modbus命令,尽管通常也只有一个主设备会这样做。一个Modbus命令包含该设备的Modbus地址(1到247)。即使其他设备可能都会接收到该命令,也只有指定位置的设备会执行指令(发送到节点0的特定广播命令除外,所有收到指令的设备都会运行,但不回应指令。这些命令已被操作但未被确认)。所有Modbus命令都包含了校验和信息,以允许接收方检测传输错误。基本Modbus命令可以指示RTU改变其一个寄存器中的某个值,控制或读取一个输入/输出端口,并命令设备发送回其寄存器中的一个或多个数据。
有许多调制解调器和网关支持Modbus,因为它是一个非常简单且经常被复制的协议。其中一些是专门为此协议设计的。有使用有线、无线通信,例如在ISM频段,甚至是短消息服务(SMS)或通用分组无线服务(GPRS)。无线网络的一种更常见的设计是利用网状网络。设计师必须克服包括高延迟和时序在内的典型问题。
Modbus框架由一个应用数据单元(ADU)组成,它包含一个协议数据单元(PDU):[7]
所有Modbus变体都选择以下帧格式之一。[8]
名称 | 长度(位) | 功能 |
---|---|---|
开始 | 28 | 至少3个字符的静默时间(标记条件) |
地址 | 8 | 站地址 |
功能 | 8 | 指示功能代码;例如读取线圈/保持寄存器 |
数据 | n × 8 | 数据+长度将根据消息类型进行填充 |
循环冗余码校验 | 16 | 循环冗余校验 |
截止 | 28 | 帧间至少3个字符的静默时间 |
关于循环冗余校验的说明:
名称 | 长度(字节) | 功能 |
---|---|---|
开始 | 1 | 以冒号开头:(ASCII十六进制值为3A) |
地址 | 2 | 站地址 |
功能 | 2 | 指示功能代码,如读取线圈/输入 |
数据 | n × 2 | 数据+长度将根据消息类型进行填充 |
纵向冗余校验 | 2 | 校验和(纵向冗余校验) |
截止 | 2 | 回车–换行(CR/LF)对(ASCII值为0D,0A) |
地址、函数、数据和纵向冗余校验都是代表8位值(0–255)的大写十六进制可读字符对。例如,122 (7 × 16 + 10)将被表示为7A。
纵向冗余校验计算为8位值之和,求反(二进制补码)并编码为8位值。例如:如果地址、函数和数据编码为247、3、19、137、0和10,它们的和就是416。被调整到8位的二进制补码(-416)是96(例如256 × 2 − 416),以十六进制表示则为60。因此如下框架::F7031389000A60<CR><LF >。
名称 | 长度(字节) | 功能 |
---|---|---|
传输标识符 | 2 | 用于服务器和客户端消息之间的同步 |
协议标识符 | 2 | Modbus/TCP为0 |
长度字段 | 2 | 此帧中剩余的字节数 |
单位标识符 | 1 | 从机地址(255,如果不使用) |
操作码 | 1 | 与其他变型一样的功能代码 |
操作码 | n | 作为响应或命令的数据 |
单元标识符与由几个Modbus设备组合而成的Modbus/TCP装置一起使用,,例如用在Modbus/TCP到Modbus RTU网关上。在这种情况下,单元标识符告诉网关后面设备的从机地址。本机支持Modbus/TCP的设备通常忽略单元标识符。
Modbus数据帧中值的字节顺序是大端字节(MSB,首先接收的值的最高有效字节)。
各种读取、写入和其他操作分类如下。[8] 最原始的读写以粗体显示。许多来源使用替代术语,例如:标准使用“写入单线圈”的替代“强制单线圈”。[9]
Modbus从机中的主要实体有:
功能类型 | 函数名 | 功能类型 | ||
---|---|---|---|---|
数据存取 | 位访问 | 物理离散输入 | 读取离散输入 | 2 |
内部位或物理线圈 | 读取线圈 | 1 | ||
写入单线圈 | 5 | |||
写入多个线圈 | 15 | |||
16位访问 | 物理输入寄存器 | 读取输入寄存器 | 4 | |
内部寄存器或物理输出寄存器 | 读取多个保持寄存器 | 3 | ||
写入单个保持寄存器 | 6 | |||
写入多个保持寄存器 | 16 | |||
读/写多个寄存器 | 23 | |||
屏蔽写寄存器 | 22 | |||
屏蔽写寄存器 | 24 | |||
屏蔽写寄存器 | 读取文件记录 | 20 | ||
写入文件记录 | 21 | |||
异常诊断 | 读取异常状态 | 7 | ||
异常诊断 | 8 | |||
获取通讯事件计数器 | 11 | |||
获取Com事件日志 | 12 | |||
报告从属标识 | 17 | |||
读取设备标识 | 43 | |||
其他的 | 封装接口传输 | 43 |
请求和响应遵循上述帧格式。本节详细介绍了最常用功能代码的数据格式。
请求:
正常响应:
每个线圈/离散输入的值是二进制的(0表示关,1表示开)。第一个请求的线圈/离散输入被存储为第一字节的最低有效位作为响应。
如果线圈/离散输入的数量不是8的倍数,最后一个字节的最高有效位将填充零。
例如,如果请求11个线圈,则需要两个字节的值。假设这些连续线圈的状态是开、关、开、关、关、开、开、开、关、开、开,那么响应将是十六进制的02 E5 06。
由于回复消息中返回的字节数仅为8位宽,协议开销为5字节,因此一次最多可以读取2008 (251 x 8)个离散输入或线圈。
请求:
正常响应:与请求相同。
请求:
每个线圈的值是二进制的(0表示关,1表示开)。第一个请求线圈作为请求中第一个字节的最低有效位存储。
如果线圈数量不是8的倍数,最后一个字节的最高有效位应该由零填充。
正常响应:
请求:
正常响应
因为寄存器值的字节数为8位宽,最大modbus消息大小为256字节,所以一次只能读取Modbus RTU的125个寄存器和Modbus TCP的123个寄存器。[10]
请求:
正常响应:与请求相同。
请求:
因为寄存器值为2字节宽,只能发送127字节的值,所以一次只能预置/写入63个保持寄存器。
正常响应:
对于正常响应,从机重复功能代码。如果从机想要报告错误,它将使用请求的功能代码加128(十六进制0x80) (3变换131 =十六进制0x83)进行回复,并且将只包括一个字节的数据,称为异常代码。
代码 | 文本 | 详细信息 |
---|---|---|
1 | 非法功能 | 从机无法识别或不允许查询中接收的功能代码 |
2 | 非法数据地址 | 某些或所有必需实体的数据地址在从机中不被允许或不存在 |
3 | 非法数据值 | 从机不接受该值 |
4 | 从属设备故障 | 从机尝试执行请求的操作时出现不可恢复的错误 |
5 | 应答 | 从机已接受请求并正在处理,但需要很长时间。返回此响应是为了防止主机发生超时错误。主机接下来可以发出“轮询程序完成”的消息,以判断处理是否完成 |
6 | 从属设备忙 | 从机参与处理长时间的命令。主机应稍后重试 |
7 | 否定应答 | 从机不能执行编程功能。主机应向从机请求诊断或错误信息 |
8 | 内存奇偶校验错误 | 从机在内存中检测到奇偶校验错误。主设备可以重试请求,但从设备可能需要服务 |
10 | 网关路径不可用 | 专门用于Modbus网关。表示网关配置错误 |
11 | 网关目标设备未能响应 | 专门用于Modbus网关。当从机未能响应时发送 |
一些约定控制如何引用Modbus实体(线圈、离散输入、输入寄存器、保持寄存器)的访问。
区分实体编号和实体地址非常重要:
在传统标准中,这些实体的数字以一个数字开始,然后是1–9999范围内的4个数字:
这转换成数据帧中0到9,998之间的地址。例如,为了从编号40001开始读取保持寄存器,数据帧中的相应地址将为0,功能代码为3(如上所示)。对于从编号40100开始的保持寄存器,地址将是99。等等。
这将每个实体的地址数量限制在9999个。业内标准将此扩展到最大值65536。[11] 它只包括在前一个列表中添加一个数字:
使用扩展引用时,所有数字引用必须正好是6位数。这避免了线圈和其他实体之间的混淆。例如,为区分保持寄存器#40001和线圈#40001,如果线圈#40001是目标,它必须显示为#040001。
另一个与Modbus密切相关的业内标准协议出现在它之后出现,其由PLC品牌April Automates定义。这是法国雷诺自动化公司和梅林·格林等人1985年合作努力的结果,该协议名为:JBUS。当时Modbus和JBUS之间的差异(实体数量、从站数量)现在已经无关紧要了,因为该协议几乎随着AEG施耐德自动化公司1994年收购的April系列PLC而消失,随后被废弃。然而JBUS这个名字在某种程度上幸存了下来。
JBUS支持功能代码1、2、3、4、5、6、15和16,因此支持上述所有实体。但是JBUS的编号不同:
几乎所有的实现都是官方标准的某种变体。不同的协议类型可能无法在不同供应商的设备之间正常通信。一些最常见的变化是:
^"Modbus FAQ". Modbus. Modbus Organization, Inc. Retrieved 1 November 2012..
^"About Modbus Organization". Modbus. Modbus Organization, Inc. Retrieved 8 November 2012..
^Modbus Messaging on TCP/IP Implementation Guide V1.0b (PDF), Modbus Organization, Inc., October 24, 2006, retrieved 2017-01-07.
^"Java Modbus Library - About". 2010. Retrieved 2017-02-07..
^"What is the difference between Modbus and Modbus Plus?". Schneider Electric. Retrieved 2017-02-07..
^"Simply Modbus - About Enron Modbus". Simply Modbus. Retrieved 2017-02-07..
^"Modbus Messaging On TCP/IP Implementation Guide" (PDF). Modbus Organization. Modbus-IDA..
^Drury, Bill (2009). Control Techniques Drives and Controls Handbook (PDF) (2nd ed.). Institution of Engineering and Technology. pp. 508–..
^Clarke, Gordon; Reynders, Deon (2004). Practical Modern Scada Protocols: Dnp3, 60870.5 and Related Systems. Newnes. pp. 47–51. ISBN 0-7506-5799-5..
^https://web.archive.org/web/20221028211856/http://modbus.org/docs/PI_MBUS_300.pdf.
^"Modbus 101 – Introduction to Modbus". Control Solutions, Inc..
^Palmer; Shenoi, Sujeet, eds. (23–25 March 2009). Critical Infrastructure Protection III. Third IFIP WG 11. 10 International Conference. Hanover, New Hampshire: Springer. p. 87. ISBN 3-642-04797-1..
^"Modbus home page". Modbus. Modbus Organization, Inc. Retrieved 2 August 2013..
暂无