Modbus协议详解

简介:

Modbus 协议是一种通信协议,允许设备通过各种类型的介质进行通信,如串行线和以太网。它是由生产可编程逻辑控制器(PLC)的 Modicon 公司于 1979 年开发的,旨在使这些设备能够相互通信。

Modbus 协议提供了一种消息传递结构,用于以主从通信方式在智能设备之间传递消息。主设备 A 发送的 Modbus 消息会触发从设备 B 的回应。Modbus 协议规定了通信内容、信息的封装方式和消息的发送和接收顺序。

Modbus 协议简单而强大,是工业控制系统的热门选择。作为一个开放标准,任何人都可以自由地使用和修改,这使得它在整个行业中得到了广泛应用。

MODBUS对应OSI模型:

Modbus的协议格式

解释:
ADU: 应用数据单元
PDU:协议数据单元
地址域:通信的设备的ID号 1字节
功能码:执行的操作/指令 1字节
数据:发送或者接受的有效数据 252字节
差错校验(CRC):判断数据传输是否正确 2字节

modbus协议通信框图

正确的响应:

错误的响应:

modbus协议执行流程:

modbus数据模型

如果是只需要读数据选择输入寄存器
既要读数据也要写数据选择保持寄存器

Modbus功能码详解

Modbus功能码是Modbus消息帧(报文)的重要组成部分,是Modubs协议中通信事务处理的基础,代表消息将要执行的动作。

功能码概要

简而言之,Modbus功能码占用一个字节,取值范围是1127,之所以127以上不能使用,是因为Modbus规定出现异常时,功能码+0x80(十进制128)代替异常状态,因此129(1+128)255(127+128)的取值代表异常码。

Modbus标准协议中规定了由3类Modbus功能码,分别是:

  1. 公共功能码

    1. 被明确定义的功能码
    2. 保证唯一性
    3. 由Modbus协会确认,并提供公开的文档;
    4. 可进行一致性测试
    5. 包括协议定义的功能码和保留将来使用的功能码
  2. 用户自定义功能码

    1. 有两个用户自定义功能码区域,分别是65110;

      72和100

    2. 用户自定义,不保证唯一性。

  3. 保留功能码

    保留功能码是因为历史遗留原因,某些公司的传统产品上现行使用的功能码不作为公共使用。

功能码可分为位操作和字操作两类。位操作的最小单位为一位(bit),字操作的最小单位为两个字节。

  • 位操作指令:读线圈状态功能码01,读(离散)输入状态功能码02,写单个线圈功能码06和写多个线圈功能码15.
  • 字操作指令:读保持寄存器功能码03,读输入寄存器功能码04,写单个保持寄存器功能码06,写多个保持寄存器功能码16.

01(0x01)读取线圈/离散量输出状态

功能说明

读取从设备的线圈或离散量输出的状态,即各DO的ON/OFF状态。消息帧中指定了需读取的线圈起始地址和线圈数目。需要注意的一点是,在Modbus协议规定的PDU中,规定所有线圈或寄存器地址从0开始计算。

查询报文

查询帧的消息里,定义了从设备地址为3,并读取从设备的Modbus地址0001900055(线圈地址0002000056)共计37个状态值。起始线圈地址为0x13(即十进制00019),因为线圈地址从0开始计数。

Modbus协议规定,起始地址由2个字节构成,取值范围为0x00000xFFFF;线圈数量由2个字节构成,取值范围为0x00010x07D0(即十进制1~2000).

ASCII模式中直接按每4个位拆分为对应的字符表示。

响应报文

响应报文的数据字段中,每一个线圈占用1个位(bit),状态被表示为1=ON和0=OFF两种类型。第1个数据字节的LSB(最低有效位)标识查询报文中的起始地址线圈的状态值,其他线圈依次类推,一直到这个字节的MSB(最高有效位)位置,并在后续字节中按照同样的方式(由低到高)排列。

一个字节可以表示8个线圈的状态,如果最后的数据字节中不能填满8个线圈的状态,则由0填充。对应于查询报文中需要读取37个线圈的状态,则共需要5个字节保存状态值。

02(0x02)读取离散量输入值

功能说明

该功能码用于读取从设备的离散输入即DI的ON/OFF状态。消息帧中制定了需读取的离散输入寄存器起始地址和数目,可读取1~2000个连续的离散量输入状态。如果从设备接受主设备的请求则回复功能码02,并返回离散量输入各离散量的当前状态。如果返回的离散输入数量的个数不是8的整数倍,将用0填充最后数据字节的剩余位。

03(0x03)读取保持寄存器值

功能说明

用于读取从设备保持寄存器的内容,不支持广播模式。消息帧中指定了需读取的保持寄存器的起始地址和数目。而保持寄存器中各地址的具体内容和意义,则由设备开发者自行规定。

查询报文

在查询报文中,必须指定保持寄存器的开始地址和需读取的寄存器数量。起始位置由2个字节构成,取值范围为0x00000xFFFF;寄存器数量由2个字节构成,取值范围为0x00010x007D(即十进制1~255),即最多可以连续读取125个寄存器。

有一点特别需要注意,Modbus的保持寄存器和输入寄存器是以字(Word)为基本单位的(1Word=2byte),所以,如果读取保持寄存器地址为40001开始的一个16位(bit)的无符号数,那么返回2个字节(byte),并可以从40002开始读取下一个16位的无符号数。如果需读取寄存器地址40001开始的是一个32位浮点数,则需要返回4个字节,即必须连续读取40001和40002的内容,而且下一个32位浮点数必须从40003开始读取。对于浮点数(或者32位的整数)而言,连续读取的两个寄存器之间存在字节序和大小端的问题,这一点在开发时必须引起注意。