Modbus TCP

Modbus

(👆 百度百科,放心跳转)

起源

Modbus 由 Modicon 公司于 1979 年开发,是一种工业现场总线协议标准。
Modbus 通信协议具有多个变种,支持串口,以太网多个版本,其中最著名的是 Modbus RTU、
Modbus ASCII 和 Modbus TCP 三种。Modbus TCP 是在施耐德收购 Modicon 后 1997 年发布的。

分类

1、Modbus RTU(Remote Terminal Unit)
运行在串口上的协议,采用二进制表现形式以及紧凑的数据结构,通信效率高,应用广泛。
2、Modbus ASCII
运行在串口上的协议,采用 ASCII 码进行传输,并且在每个字节的开始和结束 都有特殊字符作为标志,传输效率远远低于 Modbus RTU,只有传输数据量较小时,才会考虑。
3、Modbus TCP
运行在以太网上的协议。

优势

免费、简单、容易使用。

应用场景

Modbus 协议是现在国内工业领域应用最多的协议,不只 PLC 设备,各种终端设备,比如水控机、水表、电表、工业秤、各种采集设备,都应用此协议。

通信

1、Modbus 采用主从问答式(master / slave)通信;

有一个节点是 master 节点,其他使用 Modbus 协议参与通信的节点是 slave 节点(可多个), 每个 slave 设备都有唯一一个地址。

Modbus TCP

Modbus TCP 协议 和 Modbus RTU 协议非常相似,只要把 RTU 协议中两个字节的校验码去掉,然后在 RTU 协议的开始加上 5 个 0 和 1 个 6,通信时通过 TCP/IP 网络协议发送出去即可。
在这里插入图片描述

特点

1、见“Modbus ——> 通信”;

2、该协议是 应用层的协议,基于传输层的 TCP协议 进行通信;
3、Modbus TCP 默认接收报文的端口号为 502。

协议格式(报文头 + 功能码 + 数据)

Modbus TCP/IP 协议 最大数据帧长度为 260 字节。报文格式如下:
在这里插入图片描述

报文头

在这里插入图片描述

功能码

在这里插入图片描述

寄存器

在这里插入图片描述

线圈寄存器,类比为开关量,每一个 bit 都对应一个信号的开关状态,所以 一个 byte 就可以同时控制8 路的信号。 线圈寄存器支持也支持写,写又分为写单个线圈寄存器和写多个线圈寄存器。
对应功能码:0x01 0x05 0x0f
离散输入寄存器,相当于线圈寄存器的只读模式,也是每个 bit 表示一个开关量,其开关量只能读取输入的开关信号,是不能写的。比如取外部按键的按下还是松开。
对应功能码: 0x02
保持寄存器,单位不再是 bit 而是两个 byte,是可以存放具体的数据量的。比如设置时间年月日,不但可以写入也可以读出。该寄存器并可读写的,写也分为写单个保持寄存器和写多个保持寄存器。
对应功能码: 0x03 0x06 0x10
输入寄存器,和保持寄存器类似,但也只支持读而不能写。一个寄存器也是占据两个 byte 的空间。比如,通过读取输入寄存器获取现在的 AD 采集值。
对应功能码: 0x04

读数据

主机 ——>从机
报文头 + 功能码 + 起始地址 + 数量
7 + 1 + 2 + 2 = 12
从机 ——>主机
报文头 + 功能码 + 字节计数 + 数据
7 + 1 + 1 + n = 9 + n

0x01(读线圈状态)

在这里插入图片描述

0x02(读离散输入状态)

在这里插入图片描述

0x03(读保持寄存器)

在这里插入图片描述

0x04(读输入寄存器)

在这里插入图片描述

写单个

主机 ——>从机
报文头 + 功能码 + 地址 + 断通标志 / 数据
7 + 1 + 2 + 2 = 12
从机 ——>主机
原文返回

0x05(写单个线圈)

在这里插入图片描述

0x06(写单个保持寄存器)

在这里插入图片描述

写多个

主机 ——>从机
报文头 + 功能码 + 起始地址 + 数量 + 字节计数 + 数据
7 + 1 + 2 + 2 + 1 + n = 13 + n
从机 ——>主机
报文头 + 功能码 + 起始地址 + 数量
7 + 1 + 2 + 2 = 12

0x0F(写多个线圈)

在这里插入图片描述

0x10(写多个保持寄存器)

在这里插入图片描述

工具软件的安装与使用

Modbus poll

破解

点击 connection -> connect,输入序列号即可。

使用

先设置,后连接。
在这里插入图片描述

Modbus slave

破解

点击 connection -> connect,输入序列号即可。

使用

先设置,后连接。
在这里插入图片描述

网络调试助手

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Wireshark(Windows 版)

在这里插入图片描述

捕获器选择:
如果连接有线网络,选择本地连接 / 以太网;
如果连接无线网络,选择 WLAN;
如果只是在本机上的通信,可以选择 NPCAP Loopback apdater 或 Adapter for loopback traffic capture。
过滤条件:

1、过滤端口:tcp.port == 502
2、过滤IP:ip.addr == Windows 的IP
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

练习:

1、读传感器数据,读1个寄存器数据,写出主从数据收发协议。
在这里插入图片描述

2、写出控制 IO 设备开关的协议数据,操作1个线圈,置1。
在这里插入图片描述

3、在虚拟机编写客户端,实现 poll 端功能,和 Slave 通信,读保持寄存器的三个值。

    uint8_t hldreg[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, 0x03};send(sockfd, hldreg, sizeof(hldreg), 0);uint8_t buf[32] = {};recv(sockfd, buf, sizeof(buf), 0);for (int i = 0; i < buf[8]; i++)printf("%#x ", buf[9+i]);putchar(10);

运行结果如下:
在这里插入图片描述
在这里插入图片描述

4、编写客户端程序,实现对 Slave 单个线圈的控制(置一)。

    uint8_t coil[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x05, 0x00, 0x00, 0xff, 0x00};send(sockfd, coil, sizeof(coil), 0);

运行结果如下:
在这里插入图片描述

5、封装函数:设置单元标识符(从机地址)

void set_slave_id(uint8_t *p, int slave_id){p[6] = slave_id;
}

6、封装函数:读保持寄存器

void read_hldreg(int addr, int num, uint8_t *hldreg, uint8_t *dest){hldreg[5] = 0x06;hldreg[7] = 0x03;hldreg[8] = addr >> 8;hldreg[9] = addr & 0xff;hldreg[10] = num >> 8;hldreg[11] = num & 0xff;send(sockfd, hldreg, 12, 0);			// 指针类型,不能 sizeof(hldreg)recv(sockfd, dest, 64, 0);				// 64 为数组 dest 的长度,sockfd 为全局变量
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【每日OJ —— 20.有效的括号(栈)】

每日OJ —— 20.有效的括号&#xff08;栈&#xff09; 1.题目&#xff1a;20.有效的括号&#xff08;栈&#xff09;2.方法讲解2.1.解法2.1.1.算法讲解2.1.2.代码实现2.1.3.提交通过展示 1.题目&#xff1a;20.有效的括号&#xff08;栈&#xff09; 2.方法讲解 2.1.解法 利用…

Bean基本注解开发

Commponent 使用Component注解代替<bean>标签 <!--注解扫描:扫描指定的基本包及其子包下的类&#xff0c;识别使用了Component注解的文件--><context:component-scan base-package"org.xfy"></context:component-scan> package org.xfy.Dao.…

PHP中间件实现

目录 1、简单中间实现 2、使用闭包函数实现中间件 在PHP中&#xff0c;中间件是一种常用的设计模式&#xff0c;用于处理请求和响应&#xff0c;它可以在请求到达目标处理程序之前或响应发送给客户端之前执行一些特定的逻辑。中间件提供了一种灵活的方式来修改或扩展应用程序的…

初识JVM(简单易懂),解开JVM神秘的面纱

目录 一、什么是JVM&#xff08;Java虚拟机&#xff09;&#xff1f; 二、JVM的功能 三、JVM的功能-即时编译 四、常见的JVM 五、JVM的组成 五、JVM的工作流程 参考资料 一、什么是JVM&#xff08;Java虚拟机&#xff09;&#xff1f; 在Java的世界里&#xff0c;Java虚…

ImportError: cannot import name ‘contextfilter‘ from ‘jinja2‘解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【如何学习Python自动化测试】—— 多层窗口定位

6 、 多层窗口定位 多层窗口指的是在操作系统图形界面中&#xff0c;一个窗口被另一个窗口覆盖的情况。在多层窗口中&#xff0c;如何定位需要操作的窗口&#xff1f; 一种常见的方法是使用操作系统提供的AltTab快捷键&#xff0c;可以在打开的所有窗口中快速切换焦点。如果需要…

RT-Thread 线程间同步【信号量、互斥量、事件集】

线程间同步 一、信号量1. 创建信号量2. 获取信号量3. 释放信号量4. 删除信号量5. 代码示例 二、互斥量1. 创建互斥量2. 获取互斥量3. 释放互斥量4. 删除互斥量5. 代码示例 三、事件集1. 创建事件集2. 发送事件3. 接收事件4. 删除事件集5. 代码示例 简单来说&#xff0c;同步就是…

Spark---集群搭建

Standalone集群搭建与Spark on Yarn配置 1、Standalone Standalone集群是Spark自带的资源调度框架&#xff0c;支持分布式搭建&#xff0c;这里建议搭建Standalone节点数为3台&#xff0c;1台master节点&#xff0c;2台worker节点&#xff0c;这虚拟机中每台节点的内存至少给…

控制论与科学方法论

《控制论与科学方法论》&#xff0c;真心推荐。 书籍原文电子版PDF&#xff1a;https://pan.quark.cn/s/aa40d59295df&#xff08;分类在学习目录下&#xff09; 备用链接&#xff1a;https://pan.xunlei.com/s/VNgj2vjW-Hf_543R2K8kbaifA1?pwd2sap# 控制论是一种让系统按照我…

JVM垃圾回收相关算法

目录 一、前言 二、标记阶段&#xff1a;引用计数算法 三、标记阶段&#xff1a;可达性分析算法 &#xff08;一&#xff09;基本思路 &#xff08;二&#xff09;GC Roots对象 四、对象的finalization机制 五、MAT与JProfiler的GC Roots溯源 六、清除阶段&#xff1a;…

【Unity细节】Default clip could not be found in attached animations list.(动画机报错)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 &#x1f636;‍&#x1f32b;️收录于专栏&#xff1a;unity细节和bug &#x1f636;‍&#x1f32b;️优质专栏 ⭐【…