我算了一下,今年是我和我在一起Modbus认识的第10年,从最初的简单应用到协议理解,从协议开发到协议解释,陪伴了10年的协议没有改变,只是我对它的理解和理解。
我一直认为Modbus协议的存在有其历史意义,即即使没有Modbus,也可能有一个ABUS、DBUS由于控制器与控制器之间的通信,一个标准协议将大大提供开发效率。
Modbus该协议必须具备以下特点:
免费:这是最大的前提,任何产品都是一样的,只有免费才能获得早期最大的使用。
2、简单:Modbus协议帧格式简单紧凑,用户易于理解,制造商易于集成。
3、接口:Modbus协议只是一种规定,属于应用层的协议,不仅可以应用于串口(485/232/422),还可以在以太网、光纤、蓝牙传输。
我一般介绍Modbus在达成协议时,我喜欢站在协议上Modbus对于很多人来说,规约制定者的角度,结合一些事情来比较解释,可能会更容易理解。
假设没有Modbus如果我们想制定协议,我们必须首先明确协议的目的是传输数据。因此,为了更好地存储不同类型的数据,我们将分别存储布尔和非布尔的数据。因此,有线圈和寄存器的概念。
线圈和寄存器,这个经常被很多人诟病,认为不应该这么翻译,感觉不容易理解。从电气的角度来看,在电气控制电路中,接触器或中间继电器通常被接触器或中间继电器控制,接触器或中间继电器最终通过线圈的电源和断电来控制接触点的闭合和断开,因此用线圈表示布尔量;在计算机中,寄存器用于存储数据,因此非布尔数据放置在寄存器中。
这个可以跟PLC比较西门子的存储区I/Q/M都是线圈,V/T/C/DB都是寄存器,三菱X/Y都是线圈,D/W/H都是寄存器,欧姆龙CIO是线圈,D/W/H是寄存器。
以西门子为例,虽然I和Q都说线圈,但分工不同,I表示输入,Q表示输出,输入意味着存储区域的值必须由外部设备连接,只读取,输出表示输出结果可读可写。
因此,Modbus线圈和寄存器也应根据只读和读写进一步细分,从而形成Modbus如下表所示:
序号 | 读写 | 存储类型 | 存储区名称 |
1 | 只读 | 线圈 | 输入线圈 |
2 | 读写 | 线圈 | 输出线圈 |
3 | 只读 | 寄存器 | 输入寄存器 |
4 | 读写 | 寄存器 | 保持寄存器 |
然而,上表中的存储区域名称是全名,在开发和使用中使用全名会更麻烦,所以你需要给他们取个别名称,就像西门子一样I/Q/M同样,这些都是西门子给存储区取的代号,所以Modbus还要给这些存储区域取代号,简单直接使用数字,因此,有以下规定:
存储区名称 | 存储区代号 |
输入线圈 | 1区 |
输出线圈 | 0区 |
输入寄存器 | 3区 |
保持寄存器 | 4区 |
事实上,这和我们的名字和昵称一样。名字在正式场合使用。在日常场合,我们通常可以使用昵称。
无论存储区是什么,都会有一个范围的限制,就像西门子的M区可能最大到8192,三菱的X区最大到2048,Modbus每个存储区也应规定一个范围,不能无限制使用。
Modbus每个存储区的最大范围是65536,这是非常大的。
以三菱X区为例,如果最大范围是2048,那就意味着我们只能访问X0-X这里说的2047这些地址X0、X2047,就是我们常说的PLC地址,那么这个地址是怎么形成的呢?它由存储区编号和地址索引组成,我们将这样做PLC地址,理解为绝对地址,以下地址索引,理解为相对地址。 VX:thingerzj
所谓绝对地址,就是我们可以通过一个地址名来知道存储区域的数据是什么,这是我们所说的相对地址,所以绝对地址是唯一的,每个存储区域都有相对地址。
那么对于Modbus我们的绝对地址和相对地址是什么?
我们仍然遵循公式:绝对地址=区号 相对地址。
但是也会有一些不一样的地方,以保持型寄存器为例,第一个绝对地址是400001,这个地方不是400000,这个是由Modbus由规定决定的其他存储区也类似。
因此,Modbus如下图所示下图所示:
正如上面所说,65536的范围很大,但在实际使用中,我们通常不能使用这么多地址。一般来说,我们在1万以内使用它就足够了。因此,为了方便起见,我们有一个短地址模型,如下图所示:
功能代码的概念,我们可以理解,回到我们的初衷,协议的目的是数据传输,即读取数据和写入数据,我们已经确定了四个存储区域,存储不同的数据类型,然后我们将读写这些存储区域,所以可能会产生许多不同的行为,如读取输入线圈存储区域,读取输出线圈存储区域,这是两种不同的行为,同样,如果读取输入线圈存储区和读取输出线圈存储区会更麻烦,那么我们只是为每个形成指定的代码,那么这个代码就是功能代码。
让我们讨论一下有多少不同的行为?
读写是两种行为,存储区有四种,但我们知道输入线圈和输入寄存器只读,所以不能写,除了这两种,应该产生六种不同的行为,如下图所示:
行为序号 | 具体行为 |
1 | 读取输入线圈 |
2 | 读取输出线圈 |
3 | 读取输入寄存器 |
4 | 读取保持寄存器 |
5 | 写入输出线圈 |
6 | 写入寄存器 |
然而,Modbus该规定将写入输出线圈和保持寄存器,并进一步细分,包括单个和多个。因此,原来的六种行为变成了八种行为。同时,为每种行为设置代码,形成下图所示的功能代码列表:
功能码 | 功能说明 |
0x01 | 读取输出线圈 |
0x02 | 读取输入线圈 |
0x03 | 读取保持寄存器 |
0x04 | 读取输入寄存器 |
0x05 | 写入单个线圈 |
0x06 | 写入单个寄存器 |
0x0F | 写入多个线圈 |
0x10 | 写入多个寄存器 |
Modbus规约中的功能码其实不止这8个,还有一些功能码是用于诊断或异常码,但是一般很少使用,这8种功能码是最主要的核心功能码。
Modbus严格来说,是一个标准化的规约,而不是一个具体协议。我们常说的设备A和设备B之间通过Modbus协议来通信,这句话其实是不严谨的。
Modbus规约上有三种不同的协议,分别是ModbusRtu、ModbusAscii、ModbusTcp。
一般来说,ModbusRtu和ModbusAscii是运行在串口上的协议,ModbusTcp是运行是以太网上的协议,但是这并非绝对的,我们也可以将ModbusRtu、ModbusAscii运行在以太网或光纤上使用,同样的,在串口网络里,我们也可以使用ModbusTcp的协议,因为协议只是一种规范,领资料+VX:thingerzj,并不限制通信介质。
前面我们说了Modbus有三种不同的协议,分别是ModbusRtu、ModbusAscii、ModbusTcp,那么这三种协议的报文格式也是不同的,下面分别对这三种协议的报文格式进行说明:
- ModbusRtu的报文格式如下:
第一部分:从站地址,占1个字节
第二部分:功能码,占1个字节
第三部分:数据部分,占N个字节
第四部分:校验部分,CRC校验,占2个字节
2. ModbusAscii的报文格式如下:
第一部分:开始字符(:)
第二部分:从站地址,占2个字节
第三部分:功能码,占2个字节
第四部分:数据部分,占N个字节
第五部分:校验部分,LRC校验,占2个字节
第六部分:结束字符(CR LF)
3. ModbusTcp的报文格式如下:
第一部分:事务处理标识符,占2个字节
第二部分:协议标识符,占2个字节
第三部分:长度,占2个字节
第四部分:单元标识符,占1个字节
第五部分:功能码,占1个字节
第六部分:数据部分,占N个字节
Modbus学习成本很低,因为协议是公开免费的,我们可以直接获取到《Modbus中文协议文档》。
同时,也有很多调试软件可以进行仿真调试,因此我们可以在不购买任何硬件的情况下,就把Modbus协议学好。
。
Modbus 学习必须要配合相关的调试软件,可以达到事半功倍的效果,Modbus
学习必备的三大神器分别是 ModbusPoll、ModbusSlave 及 VSPD,ModbusPoll 软件主要用于仿真 Modbus主站或 Modbus 客户端,ModbusSlave 软件主要用于仿真 Modbus 从站或 Modbus 服务器,而 VSPD 全称 Configure Virtual Serial Port Driver,是用来给电脑创建虚拟串口使用的。
即使我们想要结合硬件,支持Modbus协议的设备也有很多,各种品牌PLC、各种品牌的仪表、各种温湿度传感器、流量计等都可以很好地支持Modbus协议。
纸上得来终觉浅,绝知此事要躬行。
想要更多了解Modbus协议,可以私信我,咱们一起交流。