现在网上有很多类似的文章、其实这一篇也借鉴了很多其他博主的文章。

写这篇文章的重点是在于解析功能和报文、对Modbus这个协议并不会做很多介绍。

好了,我们开始吧。

常用的功能码其实也没多少、我也就按照大小逐个介绍吧。

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为指定读取数据的长度,跟地址规则一样

回包

注:bit是一直到127的 因为图片太大无法截到

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、0x02 读取一组开关输入的当前状态(ON/OFF)

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

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

发送包

其实大家自己看与0x01是基本一样的。只是多了个Bit Count这一个

Bit Count所代表的意思就是 读取十个数据。

回包

跟0x01的回包也是一样的,可能大家伙会有些迷茫,我发包的时候是读取十个数据回包的时候Byte Count怎么会给我回复了个2呢?

细心的朋友可能也发现了、这两个单词是不一样的~一个是Bit Count 一个是Byte Count,哈哈哈哈小小的幽默 。

那这个Byte Count代表的是什么意思呢。还是字节有关。

一个字节是8位、但是10个位超过了1个字节但是不满2个字节所以占用2个字节。还有很多跟这个情况相同。

列子:

读5个输入状态

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

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

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

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

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

发包

这边Modbus/TCP我就不再展开了、都是一样的。

这个发包也很好去理解、根据Reference这一栏还有Word Count这一栏说明是起始位置是400读取6个保持寄存器数值。

一通百通、Modbus在功能报文上基本都是一致的。

回包

大家伙可能有迷茫了 怎么会是12呢 这个可怎么计算呢

我把这个Register这一栏专门的点开了,大家也都能看出来了吧。

这样就跟明了了吧,Register是占了两个位所以呢 读寄存器的个数6乘2  那不就是12了吗

列子:

读取连续三个保持寄存器的数值

发送:00 00 00 00 00 06 01 03 00 00 00 03

接收:00 00 00 00 00 09 01 03 06 03 E8 13 88 02 8A

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

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

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

发送

这个意思也就是 从0的位置读取10个输入寄存器的数值。

一通百通、有时候这些协议的原理我们没必要去搞明白,我们只要是知道这一块代表什么有什么用处我该如何去利用这一块这样就足够。

没必要去研究它如何工作如何交互(其实说白了  万变不离其宗 大部分的协议交互还是 挥手 握手)

看每个人的需求吧,可能有些工作是必须要吃透协议那只能硬着头皮去看了。

扯远了。

回包

这个也很好看明白了,还是跟0x03一样。没有变化。

列子:

读5个输入寄存器的数值

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

接收:00 00 00 00 00 0D 01 04 0A 00 00 00 01 00 02 00 03 00 04

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

回包

 

各位也发现了,回包和发包是一样的,因为在你写入的操作中,是不带读取数据的,所以服务器会直接复制一遍你的指令并返回。

例子:强置一个逻辑线圈的通断状态

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

接收:00 00 00 00 00 06 01 05 00 00 FF 00

6、0x06 写单个保持寄存器

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

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

发包

这个也不用过多的介绍了吧。在00 00位置 写入 00 00

回包

也是一样的,服务器会直接复制一遍你的指令并返回。

7、0x0f 强置多个逻辑线圈的通断状态

请求:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L 字节长度 输出值H 输出值L

响应:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L

发送

Bit Count 10是要写的个数

 回包

都一样,直接说例子吧。

例子:强置一串连续逻辑线圈的通断

发送:00 00 00 00 00 0B 01 0F 00 00 00 02 04 FF 00 00 00

发送:00 00 00 00 00 06 01 0F 00 00 00 02

8、0x10 写多个保持寄存器

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

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

发送

Word count为 要写的个数

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

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

回包

也是一样的,写了十个那么就返回十。

列子:

向起始地址为0x0000,数量为0x0001的寄存器写入数据,数据长度为0x02,数据为0x000F

发送 00 01 00 00 00 09 01 10 00 00 00 01 02 00 0F

接收 00 01 00 00 00 06 01 10 00 00 00 01

9、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]  设备名称.

回包

跟发包一样。

附录:Modbus功能码表

功能码

名称

作用

01

读取线圈状态

取得一组逻辑线圈的当前状态(ON/OFF)

02

读取输入状态

取得一组开关输入的当前状态(ON/OFF)

03

读取保持寄存器

在一个或多个保持寄存器中取得当前的二进制值

04

读取输入寄存器

在一个或多个输入寄存器中取得当前的二进制值

05

强置单线圈

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

06

预置单寄存器

把具体二进值装入一个保持寄存器

07

读取异常状态

取得8个内部线圈的通断状态,这8个线圈的地址由控制器决定,用户逻辑可以将这些线圈定义,以说明从机状态,短报文适宜于迅速读取状态

08

回送诊断校验

把诊断校验报文送从机,以对通信处理进行评鉴

09

编程(只用于484)

使主机模拟编程器作用,修改PC从机逻辑

10

控询(只用于484)

可使主机与一台正在执行长程序任务从机通信,探询该从机是否已完成其操作任务,仅在含有功能码9的报文发送后,本功能码才发送

11

读取事件计数

可使主机发出单询问,并随即判定操作是否成功,尤其是该命令或其他应答产生通信错误时

12

读取通信事件记录

可是主机检索每台从机的ModBus事务处理通信事件记录。如果某项事务处理完成,记录会给出有关错误

13

编程(184/384 484 584)

可使主机模拟编程器功能修改PC从机逻辑

14

探询(184/384 484 584)

可使主机与正在执行任务的从机通信,定期控询该从机是否已完成其程序操作,仅在含有功能13的报文发送后,本功能码才得发送

15

强置多线圈

强置一串连续逻辑线圈的通断

16

预置多寄存器

把具体的二进制值装入一串连续的保持寄存器

17

报告从机标识

可使主机判断编址从机的类型及该从机运行指示灯的状态

18

(884和MICRO 84)

可使主机模拟编程功能,修改PC状态逻辑

19

重置通信链路

发生非可修改错误后,是从机复位于已知状态,可重置顺序字节

20

读取通用参数(584L)

显示扩展存储器文件中的数据信息

21

写入通用参数(584L)

把通用参数写入扩展存储文件,或修改之

22~64

保留作扩展功能备用

 

65~72

保留以备用户功能所用

留作用户功能的扩展编码

73~119

非法功能

 

120~127

保留

留作内部作用

128~255

保留

用于异常应答

好了,基本上也就这些比较常见,文章写得比较简陋也比较懒省事。

日后有时间了话再进行补充吧。

ModbusTCP协议解析 —— 利用Wireshark对报文逐字节进行解析详细解析Modbus所含功能码的更多相关文章

  1. 欧姆龙FinsTCP与FinsUDP协议解析 —— 利用Wireshark对报文逐字节进行解析详细解析附含报文模拟器等

    前言 – Fins欧姆龙这个协议网上极少有相关的模拟器.Tcp的这一块倒是有但是Udp的基本都是不可用 1. Fins协议结构也很简单 协议分为两种 一种tcp一种udp 2. Tcp比Udp的报文会 ...

  2. DNP3协议解析 —— 利用Wireshark对报文逐字节进行解析详细解析Modbus所含功能码

    现在网上有很多类似的文章.其实这一篇也借鉴了很多其他博主的文章. 写这篇文章的重点是在于解析功能和报文.对Dnp3这个协议并不会做很多介绍. 那我们就开始吧 上图则为dnp3协议整体的报文模型(点击红 ...

  3. 西门子S7comm协议解析 —— 利用Wireshark对报文逐字节进行解析详细解析S7comm所含功能码以及UserData功能

    又一次成为懒蛋了,标题就这么改了改又是一篇新文章. 网上也有很多S7comm协议的解析,但还是如同我上一篇一样我只是做报文的解析对于S7comm的原理并进行阐述. 有些地方有错误的地方尽请大家指出,共 ...

  4. 哈工大 计算机网络 实验四 利用 Wireshark 进行协议分析

    计算机网络实验代码与文件可见github:计算机网络实验整理 实验名称 利用 Wireshark 进行协议分析 实验目的: 本次实验的主要目的. 熟悉并掌握Wireshark的基本操作,了解网络协议实 ...

  5. TCP\IP协议实践:wireshark抓包分析之链路层与网络层

    目录 TCP\IP协议实践:wireshark抓包分析之链路层与网络层 从ping开始 链路层之以太网封装 ip首部 开启ping程序,开始抓包 由一个ping的结果引出来的两个协议ARP ICMP ...

  6. 利用Wireshark抓取并分析OpenFlow协议报文

    OpenFlow 交换机与控制器交互步骤 1. 利用Mininet仿真平台构建如下图所示的网络拓扑,配置主机h1和h2的IP地址(h1:10.0.0.1,h2:10.0.0.2),测试两台主机之间的网 ...

  7. IoTClient开发3 - ModBusTcp协议客户端实现

    前言 进过前面两章的介绍,今天开始正式的实战. 进制转换 很多朋友对于进制转换可能是在刚学计算机的时候有接触,后来做高级语言开发可能就慢慢忘记了.我们做工控开发的时候需要经常进行进制转换,这里和大家一 ...

  8. IoTClient开发4 - ModBusTcp协议服务端模拟

    前言 上篇我们实现了ModBusTcp协议的客户端读写,可是在很多时候编写业务代码之前是没有现场环境的.总不能在客户现场去写代码,或是蒙着眼睛写然后求神拜佛不出错,又或是在办公室部署一套硬件环境.怎么 ...

  9. ModbusTCP协议

    简介 Modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准.1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP. Modbus协议是一项应用层 ...

随机推荐

  1. [洛谷P4097] [HEOI2013] Segment

    Description 要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第 \(i\) 条被插入的线段的标号为 \(i\) 2.给定一个数 \(k\) ,询问与直线 \(x = k\ ...

  2. 【javaScript】获取某年某月的的最后一天(即当月天数) 妙用

    javaScript里 面的new Date("xxxx/xx/xx")这个日期的构造方法有一个妙处,当你传入的是"xxxx/xx/0"(0号)的话,得到的日期 ...

  3. 【java面试】框架篇之Spring

    1.你如何理解Spring? 具体来说Spring是一个轻量级的容器,用于管理业务相关对象的.核心功能主要为:IOC,AOP,MVC. IOD:控制反转,将对象的创建过程交给容器,让容器管理对象的生命 ...

  4. ValidationAttribute特性的截图

  5. cssSelector定位写法大全(适用于selenium、robotframework)

    1.定位weibo登录框 输入框的元素信息如下 css的写法(可以看到name属性的属性值是“username”,class属性的值“W_input" driver.findElement( ...

  6. ASP.NET Core下Ocelot的简单使用

    一.创建demo项目 1.新建webapi项目,命名为“DemoProject”,去掉HTTPS勾选 using Microsoft.AspNetCore.Mvc; using System.Coll ...

  7. Electron使用electron-packager打包记录

    1.使用 JavaScript, HTML 和 CSS 构建跨平台的桌面应用 2.下载https://github.com/electron/electron-quick-start中的示例 3.在示 ...

  8. 二、Django学习之增删改查

    增加数据 第一种方式 def index(request): #创建记录方式1 #实例化要添加的记录(对象) student_obj = models.Student( name='dazhuang' ...

  9. VC运行时库/MD、/MDd、/MT、/MTd说明

    http://blog.csdn.net/holybin/article/details/26134153 VC运行时库设置:VC项目属性->配置属性->C/C++->代码生成-&g ...

  10. C语言的体系结构--main函数存在的必然性(听杨力祥老师的课)

    注:不是原创,课堂上听来的,防止遗忘,所以记下来! C语言包括两个部分:数据和函数,当然最终这两个部分都是要进入到计算机的内存中去. 函数在编译后生成可执行代码,存放在代码区:数据分为几种:局部与全局 ...