工业协议解析——Modbus

1 Modbus 概述

1.1 模式——ASCII、RTU

1、对于modbus ASCII 模式,使用的是高位字节在前,低位字节在后。使用LRC校验。又称作命令行实现
2、对于modbus rtu 模式,使用的是低位字节在前,高位字节在后。使用CRC校验。又称作代码实现

1.2 单主/多从

Modbus协议是一种单主/多从的通信协议,其特点是在同一时间,总线上只能有一个主设备,但可以有一个或者多个(最多247个 ip地址1-247)从设备,每一个从设备一个ip地址。

  • 在请求的报文中请求的地址为0则为广播模式,248-255保留
  • 请求方为主设备,应答方为从设备
  • 从设备之间是不能直接通信的,原因是协议不支持
主设备通过两种方式向从设备发送请求报文,即单播模式和广播模式
  • 单播模式:主设备仅仅寻址单个从设备,从设备返回一个响应报文。

  • 广播模式:主设备向所有的从设备发送请求指令,从设备收到指令后,各自处理,不要求返回应答;
    这种模式下,请求指令必须是Modbus标准功能中的写指令;比如 0x06 指令 (写单个保持寄存器)

1.3 Modbus 通用帧

在这里插入图片描述
ADU: 应用数据单元
PDU: 协议数据单元

  • 第一个是地址域,每一个从机都有一个地址,主机在访问从机的时候依靠这个唯一的地址识别,多个从机接收到主机的数据的时候,匹配接收到的数据和自身的地址,匹配上的那个从机作出响应,其他的都忽略。

  • 第二个是功能码,决定这一帧数据主要是干嘛的,输入数据,输出数据,读取控制量等。

  • 第三是数据,可以有也可以没有。

  • 第四是差错校验,用来对之前发送的数据校验,防止发送过程中因为电磁干扰,数据出错。

1.4 功能码

当主机向从句发送信息时,功能代码向从机说明应执行的动作。
当从机响应主机时,功能代码可说明从机正常响应或出现错误(即不正常响应),正常响应时,从句简单返回原始功能代码;
不正常响应时,从机返回与原始代码相等效的一个码,并把最高有效位设定为“1”。

如,主机要求从机读一组保持寄存器时,则发送信息的功能码为:

0000 0011 (十六进制03)

若从机正确接收请求的动作信息后,则返回相同的代码值作为正常响应。发现错时,则返回一个不正常响信息:

1000 0011(十六进制83)
在这里插入图片描述
不正常代码
在这里插入图片描述
在这里插入图片描述

2 示例

2.1 01X 读取一组逻辑线圈的当前状态(ON/OFF)

请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)

响应:MBAP 功能码 数据长度 数据(一个地址的数据为1位)

发送包
在这里插入图片描述

byte[0] byte[1] 00 02 为消息号,随便指定,服务器返回的数据的前两个字和这个一样

byte[2] byte[3] 00 00 为modbus标识,强制为0即可

byte[4] byte[5] 00 06 值在06 之后所有字节的个数,大家也可以数一数哈

byte[6] 01 为站号、随便指定。

byte[7] 01 为功能码(这个是决定了要干什么事)

byte[8] byte[9] 00 00为起始地址,比如我们我们想读地址0的数据就为00,读1000地址为03 E8

byte[10] byte[11] 00 80为指定读取数据的长度,跟地址规则一样

回包
在这里插入图片描述
byte[0] byte[1] 消息号,我们之前写发送指令的时候,是多少,这里就是多少。

byte[2] byte[3] 同上

byte[4] byte[5] 指后面的字节数

byte[6] 站号

byte[7] 功能码

byte[8] 指示在byte[8]后面的字节数量 在byte[8]后面就是真实数据

byte[9] 到结尾都是我们读取到的数据 因为字节是8位所以是16(0-127所占了128个bit 128/8 得出16)

列子:

读5个线圈状态

发送:00 00 00 00 00 06 01 01 00 00 00 05

接收:00 00 00 00 00 04 01 01 01 1F

2.2 0x02 读取一组开关输入的当前状态(ON/OFF)

请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)

响应:MBAP 功能码 数据长度 数据(长度:9+ceil(数量/8))

发包
在这里插入图片描述
其实大家自己看与0x01是基本一样的。只是多了个Bit Count这一个

Bit Count所代表的意思就是 读取十个数据 即 10bit 但需要占用2byte

回包
在这里插入图片描述
例子
读5个输入状态

发送:00 00 00 00 00 06 01 02 00 00 00 05

接收:00 00 00 00 00 04 01 02 01 15

2.3 0x03 读取一个或多个保持寄存器的数值

请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)

响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)

2.4 0x04 读取一个或多个输入寄存器的数值

请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)

响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)

2.5 0x05 强置一个逻辑线圈的通断状态

请求:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)

响应:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)
在这里插入图片描述
05 是功能码, 00 00是我们指定的地址,如果我们想写地址1000,那么就为 03 E8,后四位是规定线圈的通断状态。

那么上面发包的意思就是 在00 00这个位置 指定线圈通断状态为 断开。

举个例子:

写入地址100为通: 00 00 00 00 00 06 FF 05 00 64 FF 00

写入地址1000为断:00 00 00 00 00 06 FF 05 03 E8 00 00

2.6 0x06 写单个保持寄存器

请求:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)

响应:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)

发包
在这里插入图片描述
在00 00位置 写入 00 00
回包 与发包一致,服务器重复发送

2.7 0x10 写多个保持寄存器

请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L 字节长度 寄存器值(13+寄存器数量×2)

响应:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)

发送
在这里插入图片描述
Word count为 要写的个数

Byte count 为 要写入的数目 1个word等于2个bytes

后面 00 00 每组为写入的数值

2.8 0x2b 读取设备ID

回包发包一致
在这里插入图片描述
byte[0]byte[1] 消息号 随便指定

byte[2]byte[3] modbus的标识

byte[4]byte[5] 在此之后的长度

byte[6] 站号

byte[7] 功能码

byte[8] 功能类型 这里是读取设备ID

byte[9] 读什么 这里是读设备标识

byte[10] 设备名称.

3 Modbus 模拟器

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值