一口气入门Modbus协议
0.前言:
我将以初学者的角度以问答的方式带大家去深入了解Modbus。
1.问题一:诞生以及意义
问:我是初学modbus的小白,刚刚学完rs485,但是不太精通,能介绍一下其诞生的意义,它们两个之间有什么联系,为什么要用modbus协议,用其他的不行吗?
答:
第一部分:它们诞生的意义和联系(就像“修路”和“定交通规则”)
想象一下,你们学校里有很多班级(很多设备),每个班都想给其他班传纸条(交换数据)。
1. RS485 —— 它就像是“修了一条专门传纸条的高速公路”
在没有这条路之前,大家传纸条得靠人跑(比如早期的RS232串口),距离稍远一点、人多了就乱套,容易撞上,速度还慢。
RS485 这项技术的伟大之处在于:它**修了一条非常牛逼的公路**。这条路:
抗干扰强:纸条在路上不容易被风吹走(电气噪声干扰小)。
传得远:可以从教学楼传到操场上(传输距离长,可达千米级)。
载量大:一条路上可以同时跑很多辆车(一条总线可以挂很多个设备,32个甚至更多)。
所以,RS485解决的是“物理层面”的问题:怎么把数据可靠地、从一个设备物理地传输到另一个设备。
2. Modbus —— 它就像是“为这条高速公路制定的交通规则和纸条书写格式”
现在路修好了,大家都能上来开车传纸条了。但问题来了:
A班写了一句“你好吗?”,B班可能以为是问“你吃了吗?”,完全看不懂。
C班同时给D班和E班发纸条,结果纸条混在一起,谁也不知道该谁看。
万一好几个班同时往路上扔纸条,不就撞车了?
Modbus协议就是为了解决这些混乱而诞生的!它规定了一套所有设备都必须遵守的“语言”和“行为准则”:
纸条格式(协议帧):它规定了一张纸条必须包含哪些信息。比如:
收件人地址(从站地址):第一个数字代表这个纸条是传给哪个班的(哪个设备的)。地址为0是广播,所有班都要听。
操作指令(功能码):是让你“读作业”还是“写答案”?比如01号指令是“读开关状态”,05号指令是“强制某个开关打开”。
数据内容:具体要读哪个开关?要把它写成什么值?
查错码(CRC校验):就像是一个暗号,接收方也算一遍这个暗号,对上了才说明纸条在路上没被篡改或损坏。
通信规则:它规定了任何时候只能有一个设备在“说话”(发送数据),其他设备只能“听”。这就避免了撞车。
它们俩的联系一句话总结:
RS485是“修路”,Modbus是“交规”。 我们通常用RS485这条物理高速公路来跑Modbus这套交通规则。它们是非常经典的“黄金搭档”,一个管硬件,一个管软件。
第二部分:为什么用Modbus?用其他的不行吗?
当然可以用其他的!** 就像交通规则除了中国的,还有美国的、日本的。世界上有上百种工业通信协议。
但Modbus之所以如此流行,主要是因为它有几个“学霸”级的优点:
1. 简单易懂,容易开发(学渣友好)
它的协议格式非常简单,就是“地址+功能码+数据+校验”,几乎没有复杂的概念。一个高中生稍微学一下都能看懂一串Modbus数据代表什么意思。这对于工程师来说,开发和调试都非常容易。
2. 完全公开免费(不要钱!)
这是它火爆的最关键原因。它是由一家公司发明的,但后来被公开了,任何人都可以免费使用,不需要缴纳任何版权费或授权费。对于设备厂家来说,免费的东西谁不爱用呢?
3. 应用广泛,生态强大(大家都在用)
因为它出现得早、又简单免费,导致几乎所有的工业设备(PLC、变频器、电表、传感器、仪器仪表...)都支持Modbus协议。
这就形成了一个巨大的“生态”。你买一个支持Modbus的温度传感器,可以轻松地和甲厂的PLC、乙厂的上位机软件、丙厂的触摸屏连接起来,因为它们都“会说”Modbus这门普通话。
那为什么还有其他协议呢?
因为Modbus不是万能的,它也有“短板”:
速度慢:它的规则比较简单,效率不高,不适合需要极高速通信的场景。
功能单一:它主要就是用来“读数据”和“写数据”,没有更高级的功能(比如文件传输、设备描述等)。
安全性差:它诞生于工厂内部网络时代,没有考虑网络安全,报文都是明文的,很容易被窃听和篡改。
所以,在需要高速、安全、复杂功能的场合,大家就会用其他更高级的协议,比如 Profinet, EtherCAT, EtherNet/IP 等(这些你可以理解为是基于以太网的“更高级的高速铁路网和规则”)。
总结:
RS485:是硬件,是路,决定了数据能传多远、多稳、带多少设备。
Modbus:是软件协议,是交规,规定了数据的具体格式和传输规则,让设备之间能听懂对方的话。
为什么用Modbus:因为它简单、免费、用的人最多,是工业领域里的“普通话”。学会了它,你就能和市场上绝大部分的工业设备“对话”了。
你先掌握了Modbus+RS485这个黄金组合,就打下了工业通信的坚实基础,以后再学其他更复杂的协议就容易多了!
2.问题二:Modbus只能和RS485结合吗?
答:绝对不是!Modbus 完全可以和其他“路”一起跑。
可以把 Modbus 协议想象成一种语言(比如英语),而 RS485、RS232、TCP/IP 这些就像是不同的交通工具。
**Modbus + RS485**:就像用大货车在工厂内部的道路上运货。稳定、可靠、成本低,非常适合工厂车间这种环境。这是**最经典、最常见**的组合。
**Modbus + RS232**:就像**用一辆小轿车在两个设备之间点对点运货**。距离短,只能连接两个设备,但简单直接。
**Modbus + TCP/IP**:就像**把货物打包后,通过互联网用快递发往全球**。速度快、距离远,可以跨网络通信,是现代工业互联网的主流。
为什么大家总觉得它俩是一对?
因为它们俩的结合实在是太经典、太成功了!
1. **优势互补**:RS485 解决了工业现场远距离、多设备、抗干扰的通信硬件问题,而 Modbus 解决了这些设备之间“说什么、怎么说”的软件问题。它们俩一拍即合,成为了工业控制领域的“黄金标准”。
2. **成本低廉**:相比其他更复杂的工业总线系统,RS485+Modbus 的方案实现起来非常便宜,极大地推动了自动化技术的普及。
3. **历史原因**:Modbus 协议诞生的时候,RS485 是当时最合适、最先进的物理层技术之一。
总结给你:
Modbus 是一种协议,是规则,是语言。
RS485 是一种物理接口,是硬件,是道路。
这门语言(Modbus)既可以在省道(RS485)上说,也可以在人行道(RS232)上说,更可以在高速公路(以太网)上说。**
所以,你现在学习 **Modbus over RS485** 是在学习最经典、最基础的一套系统。掌握了这个,你再去看 **Modbus TCP**( over Ethernet)就会觉得非常简单,因为它们的协议本质是一样的,只是“打包”和“运输”的方式变了。
---------------------------------------------------------------------------------------------------------------------------------
功能码所对应的物理层寄存器介绍
---------------------------------------------------------------------------------------------------------------------------------
3.问题三:什么是线圈寄存器,保持寄存器?为什么叫线圈寄存器,保持寄存器?
答:
粗略解释:
线圈寄存器
实际上就可以类比为开关量(继电器状态),每一个bit对应一个信号的开关状态。所以一个byte就可以同时控制8路的信号。比如控制外部8路io的高低。 线圈寄存器支持读也支持写,写在功能码里面又分为写单个线圈寄存器和写多个线圈寄存器。对应上面的功能码也就是: 0x01 0x05 0x0f
保持寄存器
这个寄存器的单位不再是bit而是两个byte,也就是可以存放具体的数据量的,并且是可读写的。一般对应参数设置,比如我我设置时间年月日,不但可以写也可以读出来现在的时间。写也分为单个写和多个写,所以功能码有对应的三个: 0x03 0x06 0x10。
离散输入寄存器
如果线圈寄存器理解了这个自然也明白了。离散输入寄存器就相当于线圈寄存器的只读模式,他也是每个bit表示一个开关量,而他的开关量只能读取输入的开关信号,是不能够写的。比如我读取外部按键的按下还是松开。所以功能码也简单就一个读的0x02。
输入寄存器
这个和保持寄存器类似,但是也是只支持读而不能写,一般是读取各种实时数据。一个寄存器也是占据两个byte的空间。类比我我通过读取输入寄存器获取现在的AD采集值。对应的功能码也就一个 0x04。
精细解释:
核心比喻:一家奇怪的“超市”
想象一下,Modbus设备(比如一个PLC控制的智能电箱)就是一家超市,你要去买东西(读写数据)。这家超市为了管理方便,把所有商品分门别类,放在了两种不同的货架上:
1. 线圈寄存器 -> 【开关货架】
-
卖的是什么? 这个货架上只卖一种商品:开关。而且是那种最简单的、只有两种状态的开关:ON(开/1) 和 OFF(关/0)。
-
商品例子:
-
灯是开还是关?
-
电机是启动还是停止?
-
报警器是触发还是没触发?
-
-
为什么叫“线圈”? 这个名字来源于物理世界!在传统的继电器和控制电路中,就是用一个真实的电磁线圈的通电和断电,来吸合或释放开关触点的。Modbus协议诞生的时候,就直接用了这个硬件名字来代表这种“开关量”状态。
-
特点: 每个“线圈”就像一个小灯泡,要么亮要么灭,非常直观。
你可以对这个货架做的事:
-
读:看看某个开关现在是开还是关。(功能码
01) -
写:强行把某个开关打开或关闭。(功能码
05- 写一个,15- 写多个)
2. 保持寄存器 -> 【数据货架】
-
卖的是什么? 这个货架上卖的是各种“数据”。这些数据通常是一个个的数字(16位二进制数,相当于0-65535的整数)。
-
商品例子:
-
当前的温度值(比如 25°C)
-
目标压力值(比如 100 kPa)
-
设备运行的时间(比如 3600 秒)
-
甚至可以是更复杂的、由多个寄存器拼起来的大数或浮点数
-
-
为什么叫“保持”? 因为存在这里的数据是会被设备记住的(保持住),即使设备断电再重启,这些数据通常也不会丢失(如果设备有电池备份或存到flash里)。你可以把它想象成超市的仓库,里面的东西相对固定。
-
特点: 每个“寄存器”就像一个小盒子,里面可以放一个数字。
你可以对这个货架做的事:
-
读:看看某个盒子里存的数字是多少。(功能码
03) -
写:往某个盒子里放入一个新的数字。(功能码
06- 写一个,16- 写多个)
为什么要分两种?合在一起不行吗?
问得好!这其实是Modbus协议设计聪明和实用的地方:
-
语义清晰,不易出错:你绝对不会想用“写开关”的指令去修改一个温度值,也不会想用“写数据”的指令去启动一台电机。分开两种寄存器,从指令上就避免了这种误操作,让程序更安全。
-
符合硬件实际情况:在底层硬件上,控制开关(线圈)的电路和存储数据(保持寄存器)的内存区域本来就是分开的。协议这样设计正好匹配了硬件结构。
-
效率更高:对于只需要知道开关状态的请求,设备只需要去查询开关货架,速度快,回复的数据包也小。
总结与记忆窍门:
| 特性 | 线圈寄存器 | 保持寄存器 |
|---|---|---|
| 类比 | 开关货架 | 数据货架 |
| 存的东西 | 状态 (开/关, 是/否) | 数值 (温度、速度、设定值) |
| 数据类型 | 1个比特 (Bit) , 0或1 | 16比特 (Word) , 一个数字 |
| 功能码(读/写) | 01 / 05, 15 |
03 / 06, 16 |
| 记忆口诀 | “开关线圈,控制通断” | “保持数据,记录数值” |
所以,下次你看到这两个词,就立刻想到:
-
线圈 -> 开关 -> Do something (做什么动作)
-
保持寄存器 -> 数字 -> Know something (知道某个值)
Modbus协议就是定义了如何去这家“超市”的这两个不同货架上正确读写商品的规则。这样设计是不是非常清晰和巧妙?
4.问题四:什么是离散输入寄存器,输入寄存器?为什么叫离散输入寄存器,输入寄存器?
粗略解释:
离散输入寄存器
如果线圈寄存器理解了这个自然也明白了。离散输入寄存器就相当于线圈寄存器的只读模式,他也是每个bit表示一个开关量,而他的开关量只能读取输入的开关信号,是不能够写的。比如我读取外部按键的按下还是松开。所以功能码也简单就一个读的0x02。
输入寄存器
这个和保持寄存器类似,但是也是只支持读而不能写,一般是读取各种实时数据。一个寄存器也是占据两个byte的空间。类比我我通过读取输入寄存器获取现在的AD采集值。对应的功能码也就一个 0x04。
精细解释:
我们继续用 “超市” 这个比喻来解释,现在这家超市的货架增加到四个了,分为两个大区:
-
【可读写区】:你既可以看,也可以动手修改。这就是我们上次讲的:
-
线圈寄存器-> 开关货架 -
保持寄存器-> 数据货架
-
-
【只读监控区】:这个区的货架是用玻璃封起来的,你只能看里面的商品,但绝对不允许动手修改。它们反映的是设备最真实的、实时的工作状态。
-
离散输入寄存器-> 只读开关状态橱窗 -
输入寄存器-> 只读数据展示屏
-
3. 离散输入寄存器 -> 【只读开关状态橱窗】
-
卖的是什么? 这个橱窗里展示的也是开关状态,和线圈寄存器一样,只有 ON(1) 和 OFF(0) 两种状态。
-
关键区别:只读! 这里的开关状态不是由你来控制的,而是由外部物理世界决定的。你只能透过玻璃看,但不能伸手进去拨动它。
-
商品来源例子:
-
一个真实的物理按钮有没有被按下?
-
限位开关有没有被触发?
-
门磁传感器检测到门是开还是关?
-
故障报警信号有没有到来?
-
-
为什么叫“离散输入”? “离散”就是指不连续的、分开的状态(0或1)。“输入”意味着信号是从外部“输入”到设备里的。
-
功能码: 只能读 (
02)
记忆口诀:离散输入 就是 只读的线圈,用来反映外部开关的真实状态。
4. 输入寄存器 -> 【只读数据展示屏】
-
卖的是什么? 这个展示屏上显示的是各种只读的数据数值,和保持寄存器一样,是16位的数字。
-
关键区别:只读! 这里的数据不是你能设置的,而是设备从传感器采集来的实时数据。你只能看屏幕上的读数,但不能修改它。
-
商品来源例子:
-
温度传感器测到的当前温度值。
-
压力传感器传来的实时压力。
-
流量计测到的瞬时流量。
-
设备当前的电压、电流值。
-
-
为什么叫“输入寄存器”? 因为里面的数据是从外部传感器“输入”进来的测量值。
-
功能码: 只能读 (
04)
记忆口诀:输入寄存器 就是 只读的保持寄存器,用来存放传感器采集来的实时数据。
终极总结:为什么要分得这么细?
这完全是出于安全和实际需求的考虑,设计得非常精妙:
-
权限分离,保证安全:
-
想象一下,如果你能随便修改温度传感器的读数,那整个控制系统就乱套了。所以必须把“可以修改的参数”(保持寄存器)和“只能读取的实时数据”(输入寄存器)从物理概念和协议指令上就彻底分开。
-
同样,把“我能控制的开关”(线圈)和“只能查看的外部状态”(离散输入)分开,避免了误操作。
-
-
符合硬件设计:
-
在PLC和单片机里,连接物理按钮和传感器的接口(输入点),与控制继电器和灯泡的接口(输出点),在硬件电路上本来就是分开的。Modbus协议完美地映射了这种硬件结构。
-
四大寄存器全家福(一张表搞定)
| 寄存器类型 | 类比 | 数据类型 | 操作 | 功能码(读/写) | 例子 |
|---|---|---|---|---|---|
| 线圈寄存器 | 可读写的开关货架 | 1比特 (Bit) | 读/写 | 01 / 05, 15 |
控制灯开关、启动电机 |
| 离散输入寄存器 | 只读的开关状态橱窗 | 1比特 (Bit) | 只读 | 02 / 无 |
查看按钮是否按下、门磁状态 |
| 输入寄存器 | 只读的数据展示屏 | 16比特 (Word) | 只读 | 04 / 无 |
读取温度、压力等传感器值 |
| 保持寄存器 | 可读写的数据货架 | 16比特 (Word) | 读/写 | 03 / 06, 16 |
设置目标温度、读取设备运行时间 |
最简单的记忆方法:
-
名字里有 “输入” 的,都是 只读 的。
-
名字里有 “线圈” 或 “离散” 的,都是处理 开关状态 的。
-
名字里有 “保持” 的,是唯一一个可以 读写数值 的。
现在,你是不是对这四种寄存器一目了然了?Modbus协议的精髓就在于此!
问题五:明明线圈寄存器就具备读的特性 ,为什么还要离散输入寄存器?
核心答案:为了绝对的安全和真实的反映世界
线圈寄存器的“读”,读的是“你下的命令”;
离散输入寄存器的“读”,读的是“世界的真实情况”。
它们俩根本就不是在读同一个东西!
终极比喻:电灯开关 vs. 灯泡状态传感器
想象一个智能灯系统:
-
线圈寄存器 -> 你手里的【智能开关】
-
你“写”线圈:就是你用手指去按开关,命令灯“开”或“关”。
-
你“读”线圈:读的是你最后下的那个命令是什么。是“开”还是“关”?
-
关键点:读线圈只是告诉你开关的指令状态,它无法告诉你灯泡实际亮了没有!
-
-
离散输入寄存器 -> 安装在灯泡旁边的【光敏传感器】
-
这个传感器谁也控制不了,它只做一件事:如实检测光线并报告。
-
你“读”离散输入:读的就是这个传感器的报告。它告诉你一个铁一般的事实:“灯现在到底是亮着的,还是灭着的?”
-
它只读,且反映绝对真实。
-
现在,让问题出现!
假如没有离散输入寄存器,只有线圈寄存器,会发生什么?
-
你在手机上(通过写线圈)命令卧室的灯“打开”。
-
你想确认一下灯是不是真的亮了,于是你(读线圈)。线圈告诉你:“命令已收到,状态是‘开’”。
-
但是! 有可能灯泡坏了!或者有人把灯的电源线拔了!
-
灯其实根本没亮,但你读线圈,它依然会告诉你“开”,因为它只知道你下过“开”的命令,它根本不知道灯泡的真实状态。
这下就出大事了! 你的控制系统得到了一个错误的信息,以为一切正常,但实际上已经出了故障。
为什么必须分开?—— 设计哲学的胜利
Modbus这样设计,是基于工业控制中一个至关重要的原则:“控制”和“反馈”必须分离。
-
线圈寄存器 (控制通道):负责下发指令,是“输出”。这是你希望设备达到的状态。
-
离散输入寄存器 (反馈通道):负责监测状态,是“输入”。这是设备实际的状态。
这种分离带来了巨大的好处:
-
安全与可靠性:你能发现上述的“灯泡坏了”这种故障。你可以对比“命令”(线圈)和“实际状态”(离散输入),如果不一致,立刻就能知道设备出问题了。
-
权限管理:在复杂的系统中,可能允许一个操作员查看所有设备的状态(读离散输入),但只允许工程师有权限去控制设备(写线圈)。从协议层面就天然支持了这种权限分离。
-
符合硬件 reality:在PLC(可编程逻辑控制器)上,“输出点”(Q点,对应线圈)和“输入点”(I点,对应离散输入)在物理接线和内部电路上就是完全分开的。Modbus协议完美地映射了这种硬件结构。
总结与记忆
别再把它们想成“两个都能读开关的东西”,而要把它们看成完全不同的两个概念:
| 线圈寄存器 | 离散输入寄存器 | |
|---|---|---|
| 本质 | ****输出(Output) | ****输入(Input) |
| 你写它 | 下发一个命令 | 绝对不可以 |
| 你读它 | 查看你下过的命令 | 查看真实的物理状态 |
| 类比 | 你手机上的智能开关APP | 灯泡旁边的摄像头 |
| 关键词 | 控制、命令、期望 | 监测、反馈、现实 |
所以,你的问题答案就是:必须要有离散输入寄存器。因为没有它,你就成了一个“瞎子”,你只能发号施令,却永远无法真切地知道外部世界是否按你的指令做出了改变。在工业控制中,这种“不知道”是绝对不允许的,它会导致严重的故障甚至事故。
---------------------------------------------------------------------------------------------------------------------------------
举例
---------------------------------------------------------------------------------------------------------------------------------
1.Modbus协议
Modbus 串行链路协议是一个主-从协议。在同一时刻,只有一个主节点连接于总线,一个或多个
子节点 连接于同一个串行总线。 Modbus 通信总是由主节点发起。子节点在没有收到来自主节点的请求时,从不会发送数据。子节点之间从不会互相通信。主节点在同一时刻只会发起一Modbus 事务处理。
两种传输方式:
RTU传输模式
ASCII传输模式
RTU模式在Modbus总线上进行通讯时,信息中的每8位字节分成2个4位16进制的字符,每
个信息必须连续传输,传输方式是一个信息帧内一系列独立的数据结构以及用于传输数据的
有限规则。
2.RTU传输模式
数据规范:
- 1个起始位
- 8个数据位,最小的有效位先发送
- 1个奇偶校验位,无校验则无
- 1个停止位(有校验时), 2个Bit(无校验时)(协议规范)
写多个保持寄存器(10H)
下发指令: 01 10 01 8E 00 01 02 00 00 69 BE(向寄存器0x018E写入一个数值为0的数据)

01是设备地址
10是指令代码
018E是起始地址
00 01是元件个数(寄存器的个数)
02是2^n,n=1
00 00是数据
69 BE是校验码
正确回应指令: 01 10 01 8E 00 01 60 1E(向寄存器地址0x018E写操作一个寄存器)
错误回应指令: 01 90 01 8D C0(写操作非法功能,可能是向输入寄存器写数据)
更多推荐
所有评论(0)