modbus-TCP协议详解

modbus-TCP协议详解

1996年施耐德公司推出基于以太网TCP/IP的modbus协议:modbus-TCP。

MODBUS-TCP使MODBUS-RTU协议运行于以太网,MODBUS-TCP使用TCP/IP以太网在站点间传送MODBUS报文,MODBUS-TCP结合了以太网物理网络和网络标准TCP/IP以及以MODBUS作为应用协议标准的数据表示方法。MODBUS-TCP通信报文包在以太网TCP/IP数据包中。与传统的串口方式,MODBUS-TCP插入一个标准的MODBUS报文到TCP报文中,不再带有数据校验和地址。

MODBUS报文解析

| MBAP Header | Function code | Data |
| Header | PDU |

MBAP header包含下面几个部分:

  • Transaction ID
  • Protocol ID
  • Length
  • UnitID
id名称长度说明
1Transaction ID 事务处理标识2字节报文的序列号,一般每次通讯加1,用于区别不同的报文
2Protocol ID 协议标识2字节00 00 代表modbus-Tcp
3Length2字节Unit长度 + PDU的长度
4UnitID单元标识符1

下面的这一串MBAP header|00 01| 00 00|00 06| 01 |, 其含义如下:

事务标识为1,协议是modbus-tcp协议,数据长度是:6,从站号是1。

需要注意的是MODBUS协议是一个大端的协议,前两个byte 00 01代表0x1 , 因此Transaction ID=1。而长度字段00 06代表0x6, 即UnitID和PDU的长度总和为6。

PDU部分相对复杂一些,主要是对一些寄存器进行读写操作。

modbus的操作对象有四种:线圈寄存器离散输入寄存器输入寄存器保持寄存器

寄存器种类数据类型访问类型功能码
线圈寄存器bit读写01H 05H 0FH
离散输入寄存器bit只读02H
输入寄存器2 bytes(word)只读04H
保持寄存器2 bytes(word)读写03H 06H 10H

线圈寄存器和离散输入寄存器是以bit为单位的寄存器,只能存储开关量,线圈寄存器可读可写,而离散输入寄存器只可读。

输入寄存器和保持寄存器以为2个byte为单位的寄存器,可以存储离散的变量, 保持寄存器可读可写, 输入寄存器只读。

常用的功能码作用如下:

功能码功能
0x01读单个或者多个线圈寄存器
0x02读离散量输入寄存器
0x03读保持寄存器
0x04读输入寄存器
0x05写单个线圈寄存器
0x06写单个保持寄存器
0x10写多个保持寄存器
0x0F写多个线圈寄存器

常用功能码详解

功能码0x1:读线圈寄存器

每个线圈寄存器可以存储一个bit的信息, 功能码0x01就是用于读取slave中线圈寄存器的状态,可以是单个线圈寄存器,也可以是多个连续的线圈寄存器

发送报文

发送报文由下面几个部分组成,总共12字节:

MBAP header(7字节) + 功能码(1字节) + 线圈寄存器起始地址的高位(1字节) + 线圈寄存器起始地址的低位(1字节) + 线圈寄存器数量的高位(1字节) + 线圈寄存器数量的低位(1字节)

下面是一个用Modbus-Poll和Modbus-Slave测试的实际的例子,其含义是读取线圈寄存器的起始地址是0x0, 读取数量为 0x0a(十进制10)个。

0x1-request

MBAP header功能码起始地址高字节起始地址低字节寄存器数量的高位寄存器数量的低位
01 66 00 00 00 06 01010000000a

其中:

TransanctionID = 358, Length = 6。

功能码为0x1,代表读取线圈寄存器。

读取的线圈寄存器的起始地址为0。

读取的线圈寄存器的数量为0xa(十进制10)个。

响应报文

响应报文的长度不是固定的,长度和用户请求的数据长度有关,由下面几个部分组成:

MBAP header(7字节) + 功能码(1字节) + 线圈寄存器的值

下面是一个实际的响应报文的内容:

0x1-request

MBAP header功能码字节数请求的数据1请求的数据2
01 66 00 00 00 05 0101022102

返回的第一个字节21,转化为二进制为00100001, 其中bit0代表00寄存器,bit7代表07寄存器。

0x70x60x50x40x30x20x10x0
00100001

返回的第二个字节02,转化为二进制为00000010, 其中bit0代表08寄存器,bit1代表09寄存器。

0x90x8
10

功能码0x5: 写单个线圈寄存器0x05:

功能码0x5的作用是对单个线圈寄存器写值ON/OFF。

发送报文

发送报文由下面几个部分组成,总共12字节:

MBAP header(7字节) + 功能码(1字节) + 线圈寄存器起始地址的高位(1字节) + 线圈寄存器起始地址的低位(1字节) + 要写的值的高位(1字节) + 要写的值的低位(1字节)

将从站中的一个输出写成ON或OFF,0xFF00代表为ON,0x0000代表为OFF。

下面是一个实际的例子:

0x5-request

MBAP header功能码起始地址高字节起始地址低字节写的值的高位写的值的低位
00 6f 00 00 00 06 01050004ff00

在这个例子中,对从站01的0x4号线圈执行ON操作。

响应报文

可以看到,如果写单个线圈成功,返回报文的值和发送报文的值相同:

0x5-request

功能码0x0F:写多个线圈寄存器

将一个从站中的多个线圈寄存器的写为ON或OFF,数据域中置1的位请求相应输出位ON,置0的位请求响应输出为OFF。

发送报文

发送报文由下面几部分组成:

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

其总长度为 13 + (修改的线圈寄存器数量/8 + 1)。

下面是一个实际的例子

0xF-request

按照协议进行对应的结果如下:

MBAP header功能码线圈寄存器起始位置线圈寄存器的数量字节数第一个byte的值第二个byte的值
01 71 00 00 00 09 010f00 0000 0a027000

其中第一个byte的值是0x70, 转换为二进制是01110000,其中低位bit0代表00寄存器,bit7代表07寄存器。

0x70x60x50x40x30x20x10x0
01110000

第二个byte的值是0x0, 转换为二进制是00000000,其中低位bit0代表08寄存器,bit1代表09寄存器。

0x90x8
00

该请求的作用起始就是将04 05 06寄存器的状态改为ON。

返回报文

返回的报文相对比较简单,由下面几个部分组成:

MBAP header + 功能码 + 起始地址H 起始地址L + 输出数量H 输出数量L

下面是一个实际的例子:

0xF-response

按照协议对应各部分的内容如下:

MBAP header功能码线圈寄存器起始位置线圈寄存器的数量
01 71 00 00 00 06 010f00 0000 0a

功能码0x02:读离散量输入寄存器

功能码0x2和0x1是比较类似的。只是操作的离散量输入寄存器是只读的,没有写操作的接口。

每个离散量输入寄存器可以存储一个bit的信息, 功能码0x02就是用于读取slave中离散量输入寄存器的状态,可以是单个线圈寄存器,也可以是多个连续的线圈寄存器

发送报文

发送报文由下面几个部分组成,总共12字节:

MBAP header(7字节) + 功能码(1字节) + 离散量输入寄存器起始地址的高位(1字节) + 离散量输入寄存器起始地址的低位(1字节) + 离散量输入寄存器数量的高位(1字节) + 离散量输入寄存器数量的低位(1字节)

下面是一个用Modbus-Poll和Modbus-Slave测试的实际的例子,其含义是读取线圈寄存器的起始地址是0x0, 读取数量为 0x0a(十进制10)个。

0x2-request

MBAP header功能码起始地址高字节起始地址低字节寄存器数量的高位寄存器数量的低位
01 b9 00 00 00 06 01010000000a

其中:

TransanctionID = 441, Length = 6。

功能码为0x1,代表读取线圈寄存器。

读取的线圈寄存器的起始地址为0。

读取的线圈寄存器的数量为0xa(十进制10)个。

响应报文

响应报文的长度不是固定的,长度和用户请求的数据长度有关,由下面几个部分组成:

MBAP header(7字节) + 功能码(1字节) + 离散量输入寄存器的值

下面是一个实际的响应报文的内容:

0x2-request

MBAP header功能码字节数请求的数据1请求的数据2
01 b9 00 00 00 05 0101021202

返回的第一个字节12,转化为二进制为00010010, 其中bit0代表00寄存器,bit7代表07寄存器。

0x70x60x50x40x30x20x10x0
00010010

返回的第二个字节02,转化为二进制为00000010, 其中bit0代表08寄存器,bit1代表09寄存器。

0x90x8
10

功能码0x03:读保持寄存器

功能码0x03用于读取保持寄存器的值,从远程设备中读保持寄存器连续块的内容。

发送报文

请求报文的结构如下:

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

下面是一个实际的例子:

0x3-request

按照协议对照如下:

MBAP header功能码起始地址寄存器数量
05 f1 00 00 00 06 010300 0000 0a

响应报文

响应报文的结构由下面几个部分组成:

MBAP header + 功能码 + 数据长度 + 寄存器数据

数据总长度 = 9 + 寄存器数量 × 2

下面是一个response的结构:

0x3-response

从中我们可以提取出下面的对应关系:

MBAP header功能码字节数第0byte值第1byte值第2byte值第3byte值第4byte值第5byte值第6byte值第7byte值第8byte值第9byte值
05 f1 00 00 00 17 01031401 2c00 0000 0000 3700 0000 0000 6400 0000 3c00 00

由上面的对应关系,我们可以提取出我们想要读取的保持寄存器的值:

第0个寄存器第1个寄存器第2个寄存器第3个寄存器第4个寄存器第5个寄存器第6个寄存器第7个寄存器第8个寄存器第9个寄存器
3000055001000600

功能码0x04:读输入寄存器

功能码0x4用于读取输入寄存器的值,输入寄存器是只读的,因此没有功能码可以写输入寄存器。

发送报文

请求报文格式如下:

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

下面是一个实际的例子:

0x4-request

MBAP header功能码起始地址寄存器数量
0b f8 00 00 00 06 010400 0000 0a

该请求的含义是读取0-9号寄存器的值。

响应报文

响应报文的结构由下面几个部分组成:

MBAP header + 功能码 + 数据长度 + 寄存器数据

数据总长度 = 9 + 寄存器数量 × 2

下面是一个response的结构:

0x4-response

从中我们可以提取出下面的对应关系:

MBAP header功能码字节数第0byte值第1byte值第2byte值第3byte值第4byte值第5byte值第6byte值第7byte值第8byte值第9byte值
0b f8 00 00 00 17 01041400 0000 0000 c800 0001 2c00 0000 0000 0000 4200 00

由上面的对应关系,我们可以提取出我们想要读取的保持寄存器的值:

第0个寄存器第1个寄存器第2个寄存器第3个寄存器第4个寄存器第5个寄存器第6个寄存器第7个寄存器第8个寄存器第9个寄存器
002000300000660

功能码0x06:写单个保持寄存器

在一个远程设备中写一个保持寄存器。

发送报文

请求报文格式如下:

MBAP header + 功能码 + 寄存器地址H 寄存器地址L + 寄存器值H 寄存器值L(共12字节)

下面是一个实际的例子:

0x6-request

MBAP header功能码保持寄存器地址保持寄存器的值
1F 97 00 00 00 06 010600 0400 64

该请求的含义是向地址为0x4的寄存器写入100。

响应报文

响应报文如下:

MBAP header + 功能码 + 寄存器地址H 寄存器地址L + 寄存器值H 寄存器值L(共12字节)

成功响应的报文与发送报文格式相同。

0x6-response

功能码0x10:写多个保持寄存器

在一个远程设备中写连续寄存器块(1~123个寄存器)

发送报文

请求报文格式如下:

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

0x10-request

MBAP header功能码起始地址长度字节数字节0数据字节1数据字节2数据字节3数据字节4数据字节5数据字节6数据字节7数据字节8数据字节9数据
00 26 00 00 00 1b 011000 0000 0a14 0000 0000 0000 0000 0000 c800 0000 0000 6400 0000 64

响应报文

响应报文如下:

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

0x10-response

MBAP header功能码起始地址长度
00 26 00 00 00 1b 011000 0000 0a

实用调试工具

在研究modbus的过程中, 大量的使用了modbus poll和 modbus slave软件,这个软件可以很好的帮助理解modbus-tcp协议。

modbus poll: modbus客户端工具(主站)

modbus slave: modbus服务端工具(从站)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/129954.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

春江天玺89㎡三室两厅,现代轻奢丨不止风格更是一种生活态度。福州中宅装饰,福州装修

空间在格局上并没做太多改动,在满足基本的室内功能基础上,用相对简洁的手法来做立面整体的统筹与演绎,在提亮整个空间感的情况下,进行合理的动线分区,提高空间利用率,成为本案的设计要点。 Part 1 在客厅的…

JVM中jhat虚拟机堆转储快照分析工具

jhat虚拟机堆转储快照分析工具 1、jhat jhat也是jdk内置的工具之一。主要是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对 象的数量,大小等等,并支持对象查询语言。 使用jmap等方法生成java的堆文件后&a…

HHDESK端口转发监控服务

端口转发是一种网络技术,用于将外部网络请求转发到内部网络中的特定设备或服务。它允许通过公共网络访问内部网络中的资源,提供了灵活性和便利性。 传统的端口转发方式是通过配置路由器的端口映射,但这需要具备网络知识和一定的技术操作&…

lesson4-C++内存管理

个人主页:Lei宝啊 愿所有美好如期而遇 目录 C/C内存分布 C语言中动态内存管理方式 C中动态内存管理 operator new与operator delete函数 new和delete的实现原理 定位new表达式(placement-new) 常见面试题 C/C内存分布 我们先来看一段代码: int…

SpringBoot上传与下载文件

使用SpringBoot的虚拟路径映射。 Config中的类 import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import o…

收单外包机构评级等级为何获D、E级及其影响分析

孟凡富 中国支付清算协会发布2022年度收单外包服务机构评级等级。本次评级工作,共有包括银行和非银行支付机构在内的134家收单机构对13000家外包机构进行了评价,参评外包机构数量较上一年度增长35.59%,评级工作覆盖面继续扩大。评级等级在C级…

中波发射机概述

一、简介 1.1 中波发射机简介 中波发射机是一种用于广播电台传输中波频率信号的设备。它们是广播电台系统的重要组成部分,用于发送声音、音乐和其他信息到广泛的地理区域。中波频率范围一般介于530kHz至1700kHz之间,具有较好的传播性能,可以…

社区街道治安智慧监管方案,AI算法赋能城市基层精细化治理

一、背景需求分析 随着城市建设进程的加快,城市的管理也面临越来越多的挑战。例如,在城市街道的管理场景中,机动车与非机动车违停现象频发、摊贩占道经营影响交通、街道垃圾堆积影响市容市貌等等,都成为社区和街道的管理难点。这…

yo!这里是STL::unordered系列简单模拟实现

目录 前言 相关概念介绍 哈希概念 哈希冲突与哈希函数 闭散列 框架 核心函数 开散列 框架 核心函数 哈希表(开散列)的修改 迭代器实现 细节修改 unordered系列封装 后记 前言 我们之前了解过map和set知道,map、set的底层结构是…

集合贴4——QA机器人设计与优化

基础课21——知识库管理-CSDN博客文章浏览阅读342次,点赞6次,收藏2次。知识库中有什么信息内容,决定了智能客服机器人在回答时可以调用哪些信息内容,甚至可以更简单地理解为这是智能客服机器人的话术库。https://blog.csdn.net/22…

Leetcode-2 两数相加

不知道为什么有些测试用例通不过,思路很明晰,改不明白了,求大佬指点!!!! /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNo…

写一下关于部署项目到服务器的心得(以及遇到的难处)

首先要买个服务器(本人的是以下这个) 这里我买的是宝塔面板的,没有宝塔面板的也可以自行安装 点击登录会去到以下页面 在这个界面依次执行下面命令会看到账号和密码和宝塔面板内外网地址 sudo -s bt 14点击地址就可以跳转宝塔对应的内外网页面 然后使用上述命令提供的账号密…

《006.Springboot+vue之旅游信息推荐系统》【有文档】

《006.Springbootvue之旅游信息推荐系统》【有文档】 项目简介 [1]本系统涉及到的技术主要如下: 推荐环境配置:DEA jdk1.8 Maven MySQL 前后端分离; 后台:SpringBootMybatis; 前台:vueElementUI; [2]功能模块展示: …

计算机是如何进行工作的+进程和线程

一)计算机是如何工作的? 指令是如何执行的?CPU基本工作过程? 假设上面有一些指令表,假设CPU上面有两个寄存器A的编号是00,B的编号是01 1)第一个指令0010 1010,这个指令的意思就是说把1010地址上面的数据给他读取到A寄存器里面 2…

数据结构-图的应用

最小生成树(最小代价树) 对于一个带权连通无向图G(V,E),生成树不同,每棵树的权(即树中所有边上的权值之和)也可能不同。设R为G的所有生成树的集合,若T为R中边的权值之和最小的生成树,则T称为G的…

商城免费搭建之java商城 java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

1. 涉及平台 平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

工业级环网交换机:高效过滤和转发数据包的网络设备

环形网络是一种网络拓扑结构,其特点是将每个设备连成一个连续的环形。它可以确保一台设备发出的信号可以被环上所有其他设备接收到。环网冗余是指工业级环网交换机是否能够应对网络线缆连接中断的情况。当出现连接中断时,工业级环网交换机会接收到此消息…

常见排序算法之快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法。 基本思想为∶任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,…

【Pytest】跳过执行之@pytest.mark.skip()详解

一、skip介绍及运用 在我们自动化测试过程中,经常会遇到功能阻塞、功能未实现、环境等一系列外部因素问题导致的一些用例执行不了,这时我们就可以用到跳过skip用例,如果我们注释掉或删除掉,后面还要进行恢复操作。 1、skip跳过成…

nodejs express multer 保存文件名为中文时乱码,问题解决 originalname

nodejs express multer 保存文件名为中文时乱码,问题解决 originalname 一、问题描述 用 express 写了个后台,在接收文件并保存的时候 multer 接收到的文件名为乱码。 二、解决 找了下解决方法,在 github 的 multer issue 中找到了答案 参…