- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
大家好!我是付工。前面给大家介绍了一系列关于RS485与Modbus的知识.
终于有人把RS485说清楚了 。
终于有人把Modbus说明白了 。
通透!终于把ModbusRTU弄明白了 。
今天跟大家聊聊关于ModbusTCP协议的那些事.
ModbusTCP是一种基于以太网的通信协议.ModbusTCP协议由施耐德公司在1996年推出,它继承了ModbusRTU协议的核心功能,但主要通过TCP/IP以太网进行数据传输,实现了设备之间的主从式通信.
在实际应用中,针对串口ModbusRTU,我们通过采用主站/从站的说明双方的角色,对于ModbusTCP,我们通过使用服务器/客户端来定义双方的角色。
学习通信协议,首先要弄清楚通用报文格式。我们首先来分析一下ModbusTCP与ModbusRTU的区别:
我们可以看出,ModbusTCP在Modbus串行通信的基础上,去除了差错校验和附加地址(即从站地址),然后加上MBAP报文头(7 Bytes).
1. ModbusTCP协议一般用 于TCP或UDP通信,而TCP和UDP本身就具备数据校验,因此不需要再加校验了.
2、ModbusTCP主要用于以太网通信,因此,不再需要通过附加地址(即从站地址) 来区分不同的设备,因为以太网设备一般会使用IP地址来区分.
因此,我们只需要了解MBAP报文头即可,因为功能码和数据部分与ModbusRTU协议是一样的,下面主要针对MBAP报文头进行分析说明.
域 | 长度 | 描述 | 客户机 | 服务器 |
事务处理标识符 | 2字节 | Modbus请求/响应的识别码 | 客户机启动 | 复位响应 |
协议标识符 | 2字节 | 0=Modbus协议 | 客户机启动 | 复位响应 |
长度 | 2字节 | 后续字节的数量 | 客户机启动 | 服务器启动 |
单元标识符 | 1字节 | 串行链路或其它总线上连接的远程从站的识别码 | 客户机启动 | 复位响应 |
【1】事务处理标识符:事务处理标识符可以理解为报文的编号,服务器会复制客户端 的事务处理标识符进行响应,因此事务处理标识符并没有实际意义,一般情况下我们会使用ID自增的方式,事务处理标识符占用2个字节长度.
【2】协议标识符:协议标识符设计时是为了区分不同的协议,但是在实际应用中,只有一个协议Modbus协议,用0来表示,协议标识符占用2个字节长度,所以协议标识符是固定值0x00 0x00.
【3】长度:长度表示它后面有多少个字节,即单元标识符、功能码、数据这三个部分 的字节个数,长度占用2个字节长度.
【4】单元标识符:单元标识符与从站地址是相似的,因为ModbusTCP去除了从站地址, 所以在MBAP报文头中加入单元标识符,防止有些场合需要通过一个标识来区别不同的子设备,比如一个串口服务器下挂了多个串口设备,那么就需要单元标识符来区别不同的串口设备,实际应用中单元标识符的值由服务器决定.
综合来看,ModbusTCP协议的通用报文格式如下所示:
事务处理标识符 | 协议标识符 | 长度 | 单元标识符 | 功能码 | 数据 |
2 bytes | 2 bytes | 2 bytes | 1 byte | 1 byte | N bytes |
下面针对常用的几个功能码进行详细讲解.
读取输出线圈发送报文格式如下:
我们来分析一下这段发送报文:
【1】事务/协议:事务处理标识符和协议标识符都是用的固定值0x00 0x00.
【2】长度:单元标识符、功能码、数据部分总共是6个字节,因此长度是0x00 0x06.
【3】单元标识符:单元标识符默认是0x01.
【4】功能码:0x01表示读取的是输出线圈存储区.
【5】起始地址:十六进制0x00 0x13对应十进制为19,表示从19号线圈开始读取,这个 19对应的Modbus地址为00020.
【6】线圈数量:十六进制 0x00 0x1B对应十进制的27,表示读取线圈数量为27.
这段发送报文表示的含义是客户端想要读取服务器输出线圈存储区,Modbus地址从 00020-00046,共27个线圈的状态值.
当服务器收到这段报文后,响应报文如下:
我们再来分析一下这段响应报文:
【1】事务/协议:事务标识符服务器是复制发送报文的,是固定值0x00 0x00.
【2】长度:单元标识符、功能码、数据部分总共是7个字节,因此长度是0x00 0x07.
【3】单元标识符:单元标识符与发送报文一致.
【4】功能码:0x01表示这帧报文响应的是0x01功能码的报文.
【5】字节计数:0x04表示返回的数据总共有4个字节.
【6】字节1至字节4:返回的具体数据分别为0xCD、0x6B、0xB2、0x05,这4个字节对 应32个线圈值,前面的27个线圈值即对应00020-00046的值.
客户端收到响应报文便获取到了自己要的数据,具体对应关系如下: 0xCD=1100 1101 对应 00027-00020 0x6B=0110 1011 对应 00035-00028 0xB2=1011 0010 对应 00043-00036 0x05=0000 0101 对应 00051-00044至此,就完成了一次Modbus通信交互.
至于读取输入线圈,与读取输出线圈几乎一致,唯一的区别就是功能码从0x01变成了0x02,这里就不做过多赘述了.
读取保持型寄存器发送报文格式如下:
这个与读取输出线圈是相似的,只不过这里的起始地址是寄存器地址.
我们来分析一下这段发送报文:
【1】事务/协议:事务处理标识符和协议标识符都是用的固定值0x00 0x00.
【2】长度:单元标识符、功能码、数据部分总共是6个字节,因此长度是0x00 0x06.
【3】单元标识符:单元标识符默认是0x01.
【4】功能码:0x03表示读取的是保持型寄存器存储区.
【5】起始地址:十六进制0x00 0x6B对应十进制为107,表示从107号寄存器开始读取, 这个107对应的Modbus地址为40108.
【6】寄存器数量:0x00 0x02对应十进制的2,表示读取寄存器数量为2.
客户端发送这段报文是想要读取服务器保持型寄存器存储区,Modbus地址 从40108-40109,共2个寄存器的数据值.
服务器响应报文格式如下:
我们再来分析一下这段响应报文:
【1】事务/协议:事务标识符服务器是复制发送报文的,是固定值0x00 0x00.
【2】长度:单元标识符、功能码、数据部分总共是7个字节,因此长度是0x00 0x07.
【3】单元标识符:单元标识符与发送报文一致.
【4】功能码:0x03表示这帧报文响应的是0x03功能码的报文.
【5】字节计数:0x04表示返回的数据总共有4个字节.
【6】字节1至字节4:返回的具体数据分别为0x00、0xC8、0x01、0x2C,这4个字节对 应2个保持型寄存器的值,即对应40108-40109的值.
客户端收到响应报文便获取到了自己要的数据,具体对应关系如下:
0x00 0xC8对应40108的值,16进制的0x00 0xC8对应十进制的200 。
0x01 0x2C对应40109的值,16进制的0x01 0x2C对应十进制的300 。
读取输入寄存器,与读取保持型寄存器报文格式几乎一致,唯一的区别就是功能码从0x03变成了0x04,这里就不做过多赘述了.
我们对0x05功能码预置单线圈进行说明,发送报文格式如下:
我们来分析一下这段发送报文:
【1】事务/协议:事务处理标识符和协议标识符都是用的固定值0x00 0x00.
【2】长度:单元标识符、功能码、数据部分总共是6个字节,因此长度是0x00 0x06.
【3】单元标识符:单元标识符默认是0x01.
【4】功能码:0x05表示写入单个输出线圈.
【5】线圈地址:十六进制0x00 0x1A对应十进制为26,表示写入26号线圈,这个26对 应的Modbus地址为00027.
【6】断通标志:0xFF 0x00表示置位,就是将该线圈状态设置为True。这段发送报文表示的含义是客户端想要将服务器输出线圈存储区,Modbus地址00027这个线圈置为True.
接收报文格式如下:
预置单线圈接收报文与发送报文一致,原报文返回.
我们对0x06功能码预置单寄存器进行说明,发送报文格式如下:
我们来分析一下这段发送报文:【1】事务/协议:事务处理标识符和协议标识符都是用的固定值0x00 0x00。 【2】长度:单元标识符、功能码、数据部分总共是6个字节,因此长度是0x00 0x06。 【3】单元标识符:单元标识符默认是0x01。 【4】功能码:0x06表示写入单个保持型寄存器。 【5】寄存器地址:十六进制0x00 0x10对应十进制为16,表示写入16号寄存器,这个16 对应的Modbus地址为40017。 【6】写入值:16进制0x03 0x00对应十进制768,就是将该寄存器的值设置为768。这段发送报文表示的含义是主站想要将1号从站保持型寄存器存储区,Modbus地址 40017这个寄存器的值修改为768。接收报文格式如下:
预置单寄存器接收报文与发送报文一致,原报文返回.
0x0F功能码预置多线圈发送报文格式如下:
我们来分析一下这段发送报文:
【1】事务/协议:事务处理标识符和协议标识符都是用的固定值0x00 0x00.
【2】长度:单元标识符、功能码、数据部分总共是6个字节,因此长度是0x00 0x06.
【3】单元标识符:单元标识符默认是0x01.
【4】功能码:0x0F表示写入多个输出线圈.
【5】起始地址:十六进制0x00 0x13对应十进制为19,表示从19号线圈开始写入,这个 19对应的Modbus地址为00020.
【6】数量:十六进制0x00 0x0A对应十进制为10,表示连续写入10个线圈,Modbus地 址从00020到00029.
【7】写入值:0x0F 0x03表示写入的两个字节,第一个字节对应前8个线圈,第二个字节 对应后面的线圈。这段发送报文表示客户端想要对服务器输出线圈存储区,从Modbus地址 00020开始的10个线圈值进行修改,0x0F对应二进制00001111,对应前8个线圈,就是将00020-00027写入11110000,0x03对应二进制00000011,对应后面的线圈,也就是将00028-00029写入11.
接收报文格式如下:
预置多输出线圈接收报文是在发送报文基础上除去字节数及写入值.
0x10功能码预置多寄存器发送报文格式如下:
我们来分析一下这段发送报文:
【1】事务/协议:事务处理标识符和协议标识符都是用的固定值0x00 0x00.
【2】长度:单元标识符、功能码、数据部分总共是6个字节,因此长度是0x00 0x06.
【3】单元标识符:单元标识符默认是0x01.
【4】功能码:0x10表示写入多个保持型寄存器.
【5】起始地址:十六进制0x00 0x10对应十进制为16,表示从16号寄存器开始写入,这 个16对应的Modbus地址为40017.
【6】数量:十六进制0x00 0x02对应十进制为2,表示连续写入2个寄存器,Modbus地 址从40017到40018.
【7】字节数:0x04表示4个字节,因为1个寄存器对应2个字节,2个寄存器对应4个字节.
【8】写入值:0x01 0x0A 0x01 0x10表示写入的4个字节,前2个字节对应第1个寄存器, 后二个字节对应第二个寄存器。这段发送报文表示的含义是客户端想要对服务器1号从站保持型存储区,从Modbus地址40017 开始的2个寄存器值进行修改,0x01 0x0A对应十进制266,对应第1个寄存器,也就是 将40017写入266,0x01 0x10对应十进制272,对应第2个寄存器,也就是将40018写入272.
接收报文格式如下:
预置多寄存器接收报文是在发送报文基础上除去字节数及写入值.
最后此篇关于ModbusTCP通信协议分析的文章就讲到这里了,如果你想了解更多关于ModbusTCP通信协议分析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我刚刚继承了一个旧的 PostgreSQL 安装,需要进行一些诊断以找出该数据库运行缓慢的原因。在 MS SQL 上,您可以使用 Profiler 等工具来查看正在运行的查询,然后查看它们的执行计划。
将目标从Analytics(分析)导入到AdWords中,然后在Analytics(分析)中更改目标条件时,是否可以通过更改将目标“重新导入”到AdWords,还是可以自动选择? 最佳答案 更改目标值
我正在使用google analytics api来获取数据。我正在获取数据,但我想验证两个参数,它们在特定日期范围内始终为0。我正在获取['ga:transactions']和['ga:goalCo
我使用Google API从Google Analytics(分析)获取数据,但指标与Google Analytics(分析)的网络界面不同。 即:我在2015年3月1日获得数据-它返回综合浏览量79
我在我的Web应用程序中使用sammy.js进行剔除。我正在尝试向其中添加Google Analytics(分析)。我很快找到了following plugin来实现页面跟踪。 我按照步骤操作,页面如
当使用 Xcode 分析 (product>analyze) 时,有没有办法忽略给定文件中的任何错误? 例如编译指示之类的? 我们只想忽略第三方代码的任何警告,这样当我们的代码出现问题时,它对我们
目录 EFK 1. 日志系统 2. 部署ElasticSearch 2.1 创建handless服务 2.2 创建s
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
GCC/G++ 是否有可用于输出分析的选项? 能够比较以前的代码与新代码之间的差异(大小、类/结构的大小)将很有用。然后可以将它们与之前的输出进行比较以进行比较,这对于许多目的都是有用的。 如果没有此
我正在浏览 LYAH,并一直在研究处理列表时列表理解与映射/过滤器的使用。我已经分析了以下两个函数,并包含了教授的输出。如果我正确地阅读了教授的内容,我会说 FiltB 的运行速度比 FiltA 慢很
在 MySQL 中可以使用 SET profiling = 1; 设置分析 查询 SHOW PROFILES; 显示每个查询所用的时间。我想知道这个时间是只包括服务器的执行时间还是还包括将结果发送到前
我用 Python 编写了几个用于生成阶乘的模块,我想测试运行时间。我找到了一个分析示例 here我使用该模板来分析我的模块: import profile #fact def main():
前几天读了下mysqld_safe脚本,个人感觉还是收获蛮大的,其中细致的交代了MySQL数据库的启动流程,包括查找MySQL相关目录,解析配置文件以及最后如何调用mysqld程序来启动实例等,有着
1 内网基础 内网/局域网(Local Area Network,LAN),是指在某一区域内有多台计算机互联而成的计算机组,组网范围通常在数千米以内。在局域网中,可以实现文件管理、应用软件共享、打印机
1 内网基础 内网/局域网(Local Area Network,LAN),是指在某一区域内有多台计算机互联而成的计算机组,组网范围通常在数千米以内。在局域网中,可以实现文件管理、应用软件共享、打印机
我有四列形式的数据。前三列代表时间,value1,value 2。第四列是二进制,全为 0 或 1。当第四列中对应的二进制值为0时,有没有办法告诉excel删除时间、值1和值2?我知道这在 C++ 或
我正在运行一个进行长时间计算的 Haskell 程序。经过一些分析和跟踪后,我注意到以下内容: $ /usr/bin/time -v ./hl test.hl 9000045000050000 Com
我有一个缓慢的 asp.net 程序正在运行。我想分析生产服务器以查看发生了什么,但我不想显着降低生产服务器的速度。 一般而言,配置生产盒或仅本地开发盒是标准做法吗?另外,您建议使用哪些程序来实现这一
我目前正在尝试分析 Haskell 服务器。服务器永远运行,所以我只想要一个固定时间的分析报告。我尝试只运行该程序 3 分钟,然后礼貌地要求它终止,但不知何故,haskell 分析器不遵守术语信号,并
是否有工具可以分析 Maven 构建过程本身,以便我可以看到构建花费最多时间的地方? 我们在工作中遇到了关于 Maven 3.0.3 和 3.0b1 的问题。与 3.0.3 (9m00s) 相比,我们
我是一名优秀的程序员,十分优秀!