Modbus协议简介与常用测试指令说明
| Date | Author | Version | Note |
|---|---|---|---|
| 2022.07.19 | Dog Tao | V1.0 | 1. 完成了文档的撰写。 |
| 2023.08.04 | Dog Tao | V1.2 | 1. 修订文档,增加了Modbus协议简介小节。 |
本文档提供ModbusPoll调试软件与官方部署文档合辑资源(CSDN平台)。
文章目录
- Modbus协议简介
- 发展历史
- 主要技术说明
- 基本规范与功能码
- Modbus寄存器地址规则
- Modbus RTU报文基本格式
- 功能码01:读线圈寄存器(开关量输出)
- 功能码02:读离散寄存器(开关量输入)
- 功能码03:读保持寄存器(模拟量输出)
- 功能码04:读输入寄存器(模拟量输入)
- 功能码05:写单线圈(开关量输出)
- 功能码06:写单保持寄存器(模拟量输出)
- 功能码15:写多线圈(开关量输出)
- 功能码16:写多保持寄存器(模拟量输出)
- 读寄存器测试指令
- 线圈寄存器-读命令(0x01)
- 离散寄存器-读命令(0x02)
- 保持寄存器-读命令(0x03)
- 输入寄存器-读命令(0x04)
Modbus协议简介
发展历史
Modbus是一种通信协议,广泛用于工业控制系统之间的通信。它由Modicon(现在的施耐德电气)于1979年开发,用于与其PLC(可编程逻辑控制器)进行通信。Modbus协议主要有两个版本:Modbus RTU和Modbus TCP/IP。
-
Modbus RTU:Modbus RTU是一种串行通信协议,通常在RS-485串行接口上运行。它是二进制协议,数据在总线上以连续字节的形式传输。每条消息都以设备地址开始,由功能代码(指示操作类型)和数据字节(包含操作数据)组成,并以两字节的循环冗余校验(CRC)结束,用于检测消息传输中的错误。
-
Modbus TCP/IP:Modbus TCP/IP是基于以太网的Modbus协议版本。它在Modbus RTU的基础上增加了MBAP(Modbus Application Protocol)头部,以在TCP/IP网络上提供设备寻址和错误检测。Modbus TCP/IP通常在502端口上运行。
主要技术说明
-
寻址:在Modbus协议中,每个设备都有一个唯一的地址。在RS-485网络中,地址范围是0-247。地址0是广播地址,发送到此地址的消息将被网络上的所有设备接收。
-
寄存器:Modbus设备包含四种类型的寄存器:离散输入(只读)、线圈(可读写)、输入寄存器(只读)和保持寄存器(可读写)。每个寄存器都有一个唯一的地址,用于从设备读取或向设备写入数据。
-
功能代码:Modbus协议定义了一组功能代码,用于指示要执行的操作,如读取寄存器(功能代码03或04)或写入寄存器(功能代码06或16)。如果设备不能执行请求的操作,它将返回一个异常响应,包含一个错误码。
-
消息格式:Modbus消息由地址、功能码、数据和错误检查部分组成。在Modbus RTU中,错误检查通过CRC实现,而在Modbus TCP/IP中,通过MBAP头部的协议标识符和长度字段实现。
Modbus协议是一种简单、开放的协议,广泛用于工业自动化和嵌入式系统应用。尽管它已经存在了几十年,但由于其稳定性和易用性,它仍然是工业通信的主要标准之一。
基本规范与功能码
Modbus寄存器地址规则
Modbus协议定义的寄存器地址是5位十进制地址,即:
- 线圈寄存器(Coils Register)地址:00001~09999
- 离散寄存器(Discrete Register)地址:10001~19999
- 输入寄存器(Input Register)地址:30001~39999
- 保持寄存器(Holding Register)地址:40001~49999
由于上述各类地址是唯一对应的,因此有些资料就以其第一个数字区分各类地址,即:0x代表线圈寄存器(CR)类地址,1x代表离散寄存器(DR)类地址、 3x代表输入寄存器(IR)类地址、4x代表保持寄存器(HR)类地址。
在实际编程中,由于前缀的区分作用,所以只需说明后4位数,而且需转换为4位十六进制地址。
Modbus RTU报文基本格式
| 间隔 | 目标站号 | 功能码 | 数据 | CRC16校验 |
|---|---|---|---|---|
| 起始应有不小于3.5个字符的报文间隔 | 1字节 | 1字节 | n字节 | 2字节 |
下面对于各请求命令的“应答格式”的描述是指命令被正确执行时的应答格式。若CPU接收到错误的命令或者命令被执行错误,则返回的应答帧中“功能码”部分变为如下数据:功能码的最高位置1后得到的数据。比如功能码为01,若响应错误,则返回的功能码为0x81。
功能码01:读线圈寄存器(开关量输出)
- 请求格式:
| 目标站号 | 功能码 | 起始地址 高字节 | 起始地址 低字节 | 读取个数 高字节 | 读取个数 低字节 | CRC |
|---|---|---|---|---|---|---|
| 1字节 | 01 | 1字节 | 1字节 | 1字节 | 1字节 | 2字节 |
- 正确应答格式:
| 站号 | 功能码 | 返回数据字节数 | 返回数据字节1 | 返回数据字节2 | … | CRC |
|---|---|---|---|---|---|---|
| 1字节 | 01 | 1字节 | 1字节 | 1字节 | … | 2字节 |
功能码02:读离散寄存器(开关量输入)
- 请求格式:
| 目标站号 | 功能码 | 起始地址 高字节 | 起始地址 低字节 | 读取个数 高字节 | 读取个数 低字节 | CRC |
|---|---|---|---|---|---|---|
| 1字节 | 02 | 1字节 | 1字节 | 1字节 | 1字节 | 2字节 |
- 正确应答格式:
| 站号 | 功能码 | 返回数据字节数 | 返回数据字节1 | 返回数据字节2 | … | CRC |
|---|---|---|---|---|---|---|
| 1字节 | 02 | 1字节 | 1字节 | 1字节 | … | 2字节 |
功能码03:读保持寄存器(模拟量输出)
- 请求格式:
| 目标站号 | 功能码 | 起始地址 高字节 | 起始地址 低字节 | 读取个数 高字节 | 读取个数 低字节 | CRC |
|---|---|---|---|---|---|---|
| 1字节 | 03 | 1字节 | 1字节 | 1字节 | 1字节 | 2字节 |
- 正确应答格式:
| 站号 | 功能码 | 返回数据字节数 | 寄存器1高字节 | 寄存器1低字节 | … | CRC |
|---|---|---|---|---|---|---|
| 1字节 | 03 | 1字节 | 1字节 | 1字节 | … | 2字节 |
功能码04:读输入寄存器(模拟量输入)
- 请求格式:
| 目标站号 | 功能码 | 起始地址 高字节 | 起始地址 低字节 | 读取个数 高字节 | 读取个数 低字节 | CRC |
|---|---|---|---|---|---|---|
| 1字节 | 04 | 1字节 | 1字节 | 1字节 | 1字节 | 2字节 |
- 正确应答格式:
| 站号 | 功能码 | 返回数据字节数 | 寄存器1高字节 | 寄存器1低字节 | … | CRC |
|---|---|---|---|---|---|---|
| 1字节 | 04 | 1字节 | 1字节 | 1字节 | … | 2字节 |
功能码05:写单线圈(开关量输出)
- 请求格式:
| 目标站号 | 功能码 | 线圈地址 高字节 | 线圈地址 低字节 | 强制值 高字节 | 强制值 低字节 | CRC校验码 |
|---|---|---|---|---|---|---|
| 1字节 | 05 | 1字节 | 1字节 | 1字节 | 1字节 | 2字节 |
注:强制值= 0xFF00,则置线圈为ON;强制值=0x0000,则置线圈为OFF。
- 应答格式:若设置成功,原文返回
功能码06:写单保持寄存器(模拟量输出)
- 请求格式:
| 目标站号 | 功能码 | 寄存器地址 高字节 | 寄存器地址 低字节 | 强制值 高字节 | 强制值 低字节 | CRC校验码 |
|---|---|---|---|---|---|---|
| 1字节 | 06 | 1字节 | 1字节 | 1字节 | 1字节 | 2字节 |
- 应答格式:若设置成功,原文返回
功能码15:写多线圈(开关量输出)
- 请求格式:
| 目标 站号 | 功能码 | 起始地址 高字节 | 起始地址低字节 | 数量 高字节 | 数量 低字节 | 强制值字节数 | 强制值 第1字节 | … | CRC |
|---|---|---|---|---|---|---|---|---|---|
| 1字节 | 15 | 1字节 | 1字节 | 1字节 | 1字节 | 1字节 | 1字节 | … | 2字节 |
- 正确应答格式:
| 目标站号 | 功能码 | 起始地址 高字节 | 起始地址低字节 | 数量 高字节 | 数量 低字节 | CRC校验码 |
|---|---|---|---|---|---|---|
| 1字节 | 15 | 1字节 | 1字节 | 1字节 | 1字节 | 2字节 |
功能码16:写多保持寄存器(模拟量输出)
- 请求格式:
| 目标 站号 | 功能码 | 起始地址 高字节 | 起始地址低字节 | 数量 高字节 | 数量 低字节 | 强制值字节数 | 强制值1 高字节 | 强制值1 低字节 | … | CRC |
|---|---|---|---|---|---|---|---|---|---|---|
| 1字节 | 16 | 1字节 | 1字节 | 1字节 | 1字节 | 1字节 | 1字节 | 1字节 | … | 2字节 |
- 正确应答格式:
| 目标站号 | 功能码 | 起始地址 高字节 | 起始地址低字节 | 数量 高字节 | 数量 低字节 | CRC 校验码 |
|---|---|---|---|---|---|---|
| 1字节 | 16 | 1字节 | 1字节 | 1字节 | 1字节 | 2字节 |
读寄存器测试指令
线圈寄存器-读命令(0x01)
| 从机地址 | 寄存器地址 | 寄存器数量 | 网络指令 | modbus指令 | 说明 | 参考回复 |
|---|---|---|---|---|---|---|
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 01 03 E7 00 01 4D B9 | 读取输入寄存器第一个位值 | 01 01 01 00 51 88 |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 01 03 E7 00 02 0D B8 | 读取输入寄存器前二个位值 | |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 01 03 E7 00 04 8D BA | 读取输入寄存器前四个位值 | |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 01 03 E7 00 08 8D BF | 读取输入寄存器前八个位值 |
离散寄存器-读命令(0x02)
| 从机地址 | 寄存器地址 | 寄存器数量 | 网络指令 | modbus指令 | 说明 |
|---|---|---|---|---|---|
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 02 03 E7 00 01 09 B9 | 读取输入寄存器第一个位值 |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 02 03 E7 00 02 49 B8 | 读取输入寄存器前二个位值 |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 02 03 E7 00 04 C9 BA | 读取输入寄存器前四个位值 |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 02 03 E7 00 08 C9 BF | 读取输入寄存器前八个位值 |
保持寄存器-读命令(0x03)
| 从机地址 | 寄存器地址 | 寄存器数量 | 网络指令 | modbus指令 | 说明 |
|---|---|---|---|---|---|
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 03 03 E7 00 02 74 78 | 读取输入寄存器第一个32位数值(浮点数) |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 03 03 E7 00 04 F4 7A | 读取输入寄存器前二个32位数值(浮点数) |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 03 03 E7 00 08 F4 7F | 读取输入寄存器前四个32位数值(浮点数) |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 03 03 E7 00 10 F4 75 | 读取输入寄存器前八个32位数值(浮点数) |
输入寄存器-读命令(0x04)
| 从机地址 | 寄存器地址 | 寄存器数量 | 网络指令 | modbus指令 | 说明 |
|---|---|---|---|---|---|
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 04 03 E7 00 02 C1 B8 | 读取输入寄存器第一个32位数值(浮点数) |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 04 03 E7 00 04 41 BA | 读取输入寄存器前二个32位数值(浮点数) |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 04 03 E7 00 08 41 BF | 读取输入寄存器前四个32位数值(浮点数) |
| 0x01 | 0x999 | 0x02 | 00 32 17 | 01 04 03 E7 00 10 41 B5 | 读取输入寄存器前八个32位数值(浮点数) |
相关文章:
Modbus协议简介与常用测试指令说明
DateAuthorVersionNote2022.07.19Dog TaoV1.01. 完成了文档的撰写。2023.08.04Dog TaoV1.21. 修订文档,增加了Modbus协议简介小节。 本文档提供ModbusPoll调试软件与官方部署文档合辑资源(CSDN平台)。 文章目录 Modbus协议简介发展历史主要技…...
EXCEL里数值列如何显示序号?如何重新排序? 怎么取得排序后的序号?
目录 1 EXCEL里如何显示序号? 2 如何重新排序? 3 怎么取得排序后的序号? 3.1 rank() 的序号可能不连续 3.2 方法2:SUMPRODUCT((C7>C$7:C$12)/COUNTIF(C$7:C$12,C$7:C$12))1 EXCEL里如何显示序号?如何重新排序…...
kubernetes 集群利用 efk 收集容器日志
文章目录 [toc]前情提要制作 centos 基础镜像准备 efk 二进制文件部署 efk 组件配置 namespace配置 gfs 的 endpoints配置 pv 和 pvc部署 elasticsearchefk-cmefk-svcefk-sts 部署 filebeatfilebeat-cmfilebeat-ds 部署 kibanakibana-cmkibana-svckibana-dp使用 nodeport 访问 …...
安防视频监控汇聚平台EasyCVR在移动端火狐浏览器中云台显示的优化
安防监控视频EasyCVR视频融合平台基于云边端一体化架构,具有强大的数据接入、视频监控汇聚、处理及分发能力,平台能对前端接入设备进行统一集中管理,支持采用设备树对设备进行分组、分级管理,支持设备状态监测、云端运维等功能&am…...
selenium官文文档阅读总结(day 3)
1.关联型xpath的用法 driver.find_element(By.XPATH,//a[text()"xxx"]/ancestor::祖先元素的标签名//……) 2.selenium等待 等待的作用 :在系统运行的过程中,等待网页内容的加载显示。需要耗费的时间,与网络速度、接口的复杂程度…...
【pandas百炼成钢】数据预览与预处理
知识目录 前言一、数据查看1 - 查看数据维度2 - 随机查看5条数据3 - 查看数据前后5行4 - 查看数据基本信息5 - 查看数据统计信息|数值6 - 查看数据统计信息|非数值7 - 查看数据统计信息|整体 二、缺失值处理8 - 计算缺失值|总计9 …...
怎么查到企业的供应商和客户?
企业的供应商和客户是什么? 其实不需要过多介绍,我们对供应商和客户都有自己的理解,供应商就是负责企业产品的供应,企业从供应商那里买材料进行加工得到的产品,卖给客户。 官方来说供应商是向企业和竞争对手提供各种…...
智能物流千人俱乐部---行业必备神器
千人俱乐部前两天正式推出了。 智能物流千人俱乐部详情 很多行业内的甲方和乙方的朋友过来问,这个千人俱乐部到底怎么玩?今天再来解释一下。 1、为什么搞这个千人俱乐部? 一个原因是:研习社天天都有甲方粉丝让推荐设备厂家&#x…...
uniapp uview文件上传的文件不是文件流,该如何处理?用了uni.chooseImage预览功能要如何做
在使用uniapp开发,运用的ui是用uview,这边需要做一个身份认证,如下图 使用的是uview的u-upload组件,可是这个组件传给后端的不是文件流 后端接口需要的是文件流格式,后面使用了uniapp的选择图片或者拍照的api&#x…...
pktgen-dpdk arm编译问题 “Platform must be built with RTE_FORCE_INTRINSICS“
编译报错 /usr/include/rte_atomic_32.h:9:4: error: #error Platform must be built with RTE_FORCE_INTRINSICS解决办法: 我是在 arm架构服务器上编译出现这个,要定义 RTE_FORCE_INTRINSICS 在meson.build中 增加gcc编译参数 add_project_arguments(…...
用html+javascript打造公文一键排版系统12:删除附件说明中“附件:”里的空格
如果我们在输入附件说明时在“附件:”之间加入空格,那么排版时就要删除这些空格。 因为string对象replace()支持正则表达式,于是考虑用replace()来完成。 写了一段只有一个多余空格的代码来测试: <!DOCTYPE HTML> <HT…...
容器技术:Docker搭建(通俗易懂)
目录 Docker搭建环境准备Docker安装1、查看服务器是否安装Docker2、卸载Docker3、安装Dokcer依赖环境4、配置Docker国内阿里云镜像5、安装Docker6、查看Docker信息7、配置阿里云镜像加速8、镜像安装10、运行实例11、查看实例状态12、测试 Docker命令集合 Docker搭建 环境准备 …...
Day 16 C++ 友元(friend)
目录 什么是友元(friend) 友元的三种实现 全局函数做友元 类做友元 成员函数做友元 什么是友元(friend) 友元是一种访问控制的机制,它允许一个类或函数访问另一个类的私有成员。通过友元关系,可以在需要…...
步进电机1
引脚说明: VCC:电源输入口 DC:9-42VDC:电源的取值范围 AB组:用于连接电机的四条线 STEP&PUL:脉冲信号接口,用于控制速度。无细分的情况下一个脉冲步进电机走一步。 DIR:方向信号接口&#x…...
PHP-简单项目引起的大麻烦--【白嫖项目】
强撸项目系列总目录在000集 PHP要怎么学–【思维导图知识范围】 文章目录 本系列校训本项目使用技术 首页小插曲小插曲完了么?必要的项目知识PHPThinkPHPThinkPHP的MVCThinkTemplateThinkPHP 6和ThinkPHP 5 phpStudy 设置导数据库展示页面数据库表结构项目目录如图…...
Excel如何把两列互换
第一步:选择一列 打开excel,选中一列后将鼠标放在列后,让箭头变成十字方向。 第二步:选择Shift键 按住键盘上的Shift键,将列往后移动变成图示样。 第三步:选择互换 完成上述操作后,松开鼠标两…...
Java基础面试题2
Java基础面试题 一、IO和多线程专题 1.介绍下进程和线程的关系 进程:一个独立的正在执行的程序 线程:一个进程的最基本的执行单位,执行路径 多进程:在操作系统中,同时运行多个程序 多进程的好处:可以充…...
Typescript 第八章 异步编程,并行和并发(JavaScript事件循环,异步流,多线程类型安全)
Typescript第八章 异步编程,并发和并行 异步API,比如说回调,promise和流。 JavaScript引擎在一个线路中多路复用任务,而其他任务则处于空闲状态。这种事件循环是JavaScript引擎的标准线程模型。 多路复用是指在一个线程中同时处…...
c++ 打印当前时间(精确到毫秒)
打印时间精确到毫秒好实现,但是那种对用户可读性不好,更适合开头记一次结尾记一次,打印中间减出来的程序运行时间。 但是因为一些情况,我开多线程开的不方便打印结束时间,同事跟我说那你把开始时间打印一下࿰…...
mapstruct 错误 java.lang.NoSuchMethodError: Ljava/lang/Double 错误
问题描述 在使用 mapstruct 的过程中遇到错误 java.lang.NoSuchMethodError: Ljava/lang/Double 错误 问题解决 maven clean, 然后 maven install Build -> Rebuild Project 执行 maven install 时, 如果报错 找不到 xxx 类, 但 ctrl鼠标左键 发现可以点进去这个类, 那…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...
