MODBUS协议整理
- 1. Modbus协议
Modbus通信协议由Modicon公司(现已经为施耐德公司并购,成为其旗下的子品牌)于1979年发明的,是全球最早用于工业现场的总线规约。由于其免费公开发行,使用该协议的厂家无需缴纳任何费用,Modbus通信协议采用的是主从通信模式(即Master/Slave通信模式),其在分散控制方面应用极其广泛,从而使得Modbus协议在全球得到了广泛的应用。
Modbus通信协议具有多个变种,其具有支持串口(主要是RS-485总线),以太网多个版本,其中最著名的是Modbus RTU,Modbus ASCII和Modbus TCP三种。其中Modbus RTU与Modbus ASCII均为支持RS-485总线的通信协议,其中Modbus RTU由于其采用二进制表现形式以及紧凑数据结构,通信效率较高,应用比较广泛。而Modbus ASCII由于采用ASCII码传输,并且利用特殊字符作为其字节的开始与结束标识,其传输效率要远远低于Modbus RTU协议,一般只有在通信数据量较小的情况下才考虑使用Modbus ASCII通信协议,在工业现场一般都是采用Modbus RTU协议,一般而言,大家说的基于串口通信的Modbus通信协议都是指Modbus RTU通信协议。
在此我们着重讨论Modbus RTU协议,而Modbus TCP协议则是在RTU协议上加一个MBAP报文头,由于TCP是基于可靠连接的服务,RTU协议中的CRC校验码就不再需要,所以在Modbus TCP协议中是没有CRC校验码,用一句比较通俗的话说就是:Modbus TCP协议就是Modbus RTU协议在前面加上五个0以及一个6,然后去掉两个CRC校验码字节就OK.虽然这句话说得不是特别准确,但是也基本上把RTU与TCP之间的区别说得比较清楚了。
RTU协议中的指令由地址码(一个字节),功能码(一个字节),起始地址(两个字节),数据(N个字节),校验码(两个字节)五个部分组成,其中数据又由数据长度(两个字节,表示的是寄存器个数,假定内容为M)和数据正文(M乘以2个字节)组成,而RTU协议是采用3.5个字节的空闲时间作为指令的起始和结束,一般而言,只有当从机返回数据或者主机写操作的时候,才会有数据正文,而其他时候比如主机读操作指令的时候,没有数据正文,只需要数据长度即可。(本章的讨论只涉及寄存器的读写,其他比如线圈的读写指令我们暂时不涉及)。在此我们通过两个指令(0x03H:读多个寄存器指令以及0x10H:写多个寄存器指令)来解释Modbus RTU协议。在此我们使用的RTU设备是深圳市国科伟业通信技术有限公司的ND-1084型485总线I/O模块。
ND-1084型485总线I/O模块采用RS-485总线通信,支持四路开关量输出以及八路开关量输入,我们只讲述读取开关量输出的状态以及通过写指令控制开关量的输出。其中储存开关量输出状态的四个寄存器分别:0x18E,0x18F,0x190,0x191。在此我们假设模块的地址为默认的0x01,当我们要去读取开关量输出对应的四个寄存器的状态的时候,我们下发的十六进制的指令为:“01 03 01 8E 00 04 25 DE”,其中“01”为模块的地址码,“03”为功能码,即表示读寄存器,“01 8E”为寄存器地址,即从该寄存器地址开始读取数据,“00 04”则表示读取4个寄存器,而“25 DE”则为前面“01 03 01 8E 00 04”的CRC校验码,该数值通过CRC16校验算法计算出来的,我们会在其他文章中阐述。该指令的完整解读就是,在地址码为“01”的模块中,从“01 8E”寄存器开始,读取4个寄存器的数据返回至主机。在此,我们可以看到,读取指令中并没有什么数据正文,因为它只是读取相应数量的寄存器,并不需要数据正文,而写操作指令则相反,我们会在后面讲到。
模块返回的指令是:“01 03 08 00 01 00 01 00 01 00 01 28 D7”,返回的指令内容解读就是:“01”表示模块的地址码,“03”表示该指令是读操作返回的指令,“08”表示数据长度,在此表示的是8个字节数据正文(即4个寄存器,每个寄存器两个字节表示),“00 01 00 01 00 01 00 01”是数据正文,表示四个寄存器的状态,“28 D7”就是CRC16校验码。
同样的当我们执行写操作的是,我们举例写第一个开关量输出,即寄存器“0x18E”,主机下发的指令为:“01 10 01 8e 00 01 02 00 00 A8 7E”,该指令的解读就是:“01”表示模块的地址,“10”表示该指令为写寄存器,“01 8E”表示从该寄存器地址开始执行写操作指令“00 01”表示写多少个寄存器,在此为写1个寄存器,“02”表示数据长度,表示数据长度为两个字节,“00 00”表示写入寄存器的数据,在此表示连通,“A8 7E”为CRC校验码。模块返回的指令和读取寄存器的返回的指令类似。
前文所述,Modbus TCP协议是在RTU协议前面添加MBAP报文头,共七个字节长度,其分别的意义是:1.传输标志,两个字节长度,标志Modbus询问/应答的传输,一般默认是00 00。2.协议标志,两个字节长度,0表示是Modbus,1表示UNI-TE协议,一般默认也是00 00。3.后续字节计数,两个字节长度,其实际意义就是后面的字节长度,具体情况详见下文。4.单元标志,一个字节长度,一般默认为00,单元标志对应于Modbus RTU协议中的地址码,当RTU与TCP之间进行协议转换的时候,特别是Modbus网关转换协议的时候,在TCP协议中,该数据就是对应RTU协议中的地址码,具体情况详见下文。
通过上面的描述我们差不多能够理解Modbus RTU协议,我们再说说Modbus TCP通信协议,前面就已经说过TCP协议就是在RTU协议的基础上去掉校验码以及加上五个0和一个6,当是读取相关寄存器的时候,该说法是没有错的,比如上文的“01 03 01 8E 00 04 25 DE”读取指令,用TCP协议来表述的话,指令是“00 00 00 00 00 06 00 03 01 8E 00 04”,由于TCP是基于TCP连接的,不存在所谓的地址码,所以06后面一般都是“00”(当其作为Modbus网关服务器挂接多个RTU设备的时候,数值从01-FF).即“00 03 01 8E 00 04”对应的是RTU中去掉校验码的指令,前面则是五个0以及一个6。其中6表示的是数据长度,即“00 03 01 8E 00 04”有6个字节长度。而当其为写操作指令的时候,其指令是“00 00 00 00 00 09 01 10 01 8e 00 01 02 00 00”,其中“00 09”表示后面有9个字节。
Modbus RTU与Modbus TCP读指令对比
|
MBAP报文头 |
地址码 |
功能码 |
寄存器地址 |
寄存器数量 |
CRC校验 |
Modbus RTU |
无 |
01 |
03 |
01 8E |
00 04 |
25 DE |
Modbus TCP |
00 00 00 00 00 06 00 |
无 |
03 |
01 8E |
00 04 |
无 |
指令的涵义:从地址码为01(TCP协议单元标志为00)的模块0x18E(01 8E)寄存器地址开始读(03)四个(00 04)寄存器。
Modbus RTU与Modbus TCP写指令对比
|
MBAP报文头 |
地址码 |
功能码 |
寄存器地址 |
寄存器数量 |
数据长度 |
正文 |
CRC校验 |
RTU |
无 |
01 |
10 |
01 8E |
00 01 |
02 |
00 00 |
A8 7E |
TCP |
00 00 00 00 00 09 00 |
无 |
10 |
01 8E |
00 01 |
02 |
00 00 |
无 |
指令的涵义:从地址码为01(TCP协议单元标志为00)的模块0x18E(01 8E)寄存器地址开始写(10)一个(00 01)寄存器,具体数据长度为2个字节(02),数据正文内容为00 00(00 00)。
功能码表
|
数据类型 |
功能描述 |
功能码 |
功能码(十六进制) |
异常功能码 |
|
比特访问 |
物理离散量输入 |
读输入离散量 |
02 |
0x02 |
0x82 |
|
内部比特或者物理线圈 |
读线圈 |
01 |
0x01 |
0x81 |
|
|
写单个线圈 |
05 |
0x05 |
0x85 |
|
||
写多个线圈 |
15 |
0x0F |
0x8F |
|
||
|
||||||
16比特访问 |
输入存储器 |
读输入寄存器 |
04 |
0x04 |
0x84 |
|
内部存储器或物理输出存储器(保持寄存器) |
读多个寄存器 |
03 |
0x03 |
0x83 |
|
|
写单个寄存器 |
06 |
0x06 |
0x86 |
|
||
写多个寄存器 |
16 |
0x10 |
0x90 |
|
||
读/写多个寄存器 |
23 |
0x17 |
0x97 |
|
||
屏蔽写寄存器 |
22 |
0x16 |
0x96 |
|
||
|
||||||
文件记录访问 |
读文件记录 |
20 |
0x14 |
|
|
|
写文件记录 |
21 |
0x15 |
|
|
其中物理离散量输入和输入寄存器只能有I/O系统提供的数据类型,即只能是由I/O系统改变离散量输入和输入寄存器的数值,而上位机程序不能改变的数据类型,在数据读写上表现为只读,而内部比特或者物理线圈和内部寄存器或物理输出寄存器(保持寄存器)则是上位机应用程序可以改变的数据类型,在数据读写上表现为可读可写。
错误代码表
代码 |
名称 |
含义 |
01 |
非法功能 |
对于服务器(或从站)来说,询问中接收到的功能码是不可允许的操作,可能是因为功能码仅适用于新设备而被选单元中不可实现同时,还指出服务器(或从站)在错误状态中处理这种请求,例如:它是未配置的,且要求返回寄存器值。 |
02 |
非法数据地址 |
对于服务器(或从站)来说,询问中接收的数据地址是不可允许的地址,特别是参考号和传输长度的组合是无效的。对于带有100个寄存器的控制器来说,偏移量96和长度4的请求会成功,而偏移量96和长度5的请求将产生异常码02。 |
03 |
非法数据值 |
对于服务器(或从站)来说,询问中包括的值是不可允许的值。该值指示了组合请求剩余结构中的故障。例如:隐含长度是不正确的。modbus协议不知道任何特殊寄存器的任何特殊值的重要意义,寄存器中被提交存储的数据项有一个应用程序期望之外的值。 |
04 |
从站设备故障 |
当服务器(或从站)正在设法执行请求的操作时,产生不可重新获得的差错。 |
05 |
确认 |
与编程命令一起使用,服务器(或从站)已经接受请求,并且正在处理这个请求,但是需要长持续时间进行这些操作,返回这个响应防止在客户机(或主站)中发生超时错误,客户机(或主机)可以继续发送轮询程序完成报文来确认是否完成处理。 |
07 |
从属设备忙 |
与编程命令一起使用,服务器(或从站)正在处理长持续时间的程序命令,当服务器(或从站)空闲时,客户机(或主站)应该稍后重新传输报文。 |
08 |
存储奇偶性差错 |
与功能码20和21以及参考类型6一起使用,指示扩展文件区不能通过一致性校验。服务器(或从站)设备读取记录文件,但在存储器中发现一个奇偶校验错误。客户机(或主机)可重新发送请求,但可以在服务器(或从站)设备上要求服务。 |
0A |
不可用网关路径 |
与网关一起使用,指示网关不能为处理请求分配输入端口值输出端口的内部通信路径,通常意味着网关是错误配置的或过载的。 |
0B |
网关目标设备响应失败 |
与网关一起使用,指示没有从目标设备中获得响应,通常意味着设备未在网络中。 |
我们以Modbus RTU协议为例,地址码为0x01,写操作0x10,寄存器地址为0x018E,CRC校验。如寄存器可读写的话,返回正常,如寄存器只读,返回异常。
下发指令:01 10 01 8E 00 01 02 00 00 69 BE(向寄存器0x018E写入一个数值为0的数据)
正确回应指令:01 10 01 8E 00 01 60 1E(向寄存器地址0x018E写操作一个寄存器)
错误回应指令:01 90 01 8D C0(写操作非法功能,可能是向输入寄存器写数据)
在大家通读Modbus协议时,总是会碰到一些容易混淆的名词,从而导致对于协议的解读出现问题,在本文中,我们对于Modbus协议中可能会给大家造成困惑的名词作相关的解释。
1.功能码:功能码在modbus协议用于表示信息帧的功能,常用的功能码有03,04,06,16等,其中03功能码的作用是读保持寄存器内容,04功能码的作用是读输入寄存器内容(输入寄存器和保持寄存器的区别看下文),06功能码的内容是预置单个保持寄存器,16功能码的内容则是预置多个保持寄存器。
2.输入寄存器和保持寄存器:04功能码的作用就是读输入寄存器,而03功能码的作用则是读保持寄存器,很多人在看到这两个功能码的时候总是希望找到这两个功能码的区别,保持寄存器和输入寄存器到底是什么区别,modbus协议最开始是用来解决PLC的通信协议问题的,主要用于输入输出数字量信号以及模拟量信号,所谓的输入寄存器就是从模拟量信号输入引申出来的,即输入寄存器只能从模拟量信号输入端改变寄存器,而主机则不能通过下发指令改变输入寄存器的数据,而保持寄存器则是用于输出模拟量信号的,主机是可以改变寄存器数据,也就是说对于主机而言,输入寄存器是只读的,而保持寄存器是可以读写的,当主机用06,16功能码的指令去预置输入寄存器的时候,设备会返回一个代码为0x81的错误代码,即企图写只读寄存器。
3.Modbus中的数据地址格式:在Modbus协议中,经常会出现类似于3xxxx,4xxxx寄存器,这个表示的是寄存器支持的数据类型。我们用列表来说明,还有Modbus数据地址格式是从0开始,比如以下一个寄存器40009,即表示保持寄存器,寄存器地址为00 08,类似的数据地址格式经常在组态软件以及PLC系统中用到。
映射地址 |
使用的功能码 |
地址类型 |
存取方式 |
描述 |
0XXXX |
01,05,15 |
离散输出 |
读写 |
每个卷表示单个开关位 |
1XXXX |
02 |
离散输入 |
只读 |
每个卷表示单个开关位 |
2XXXX |
03,04,06,16 |
浮点寄存器 |
只读/读写 |
两个连续16位寄存器表示一个浮点数 |
3XXXX |
04 |
输入寄存器 |
只读 |
每个寄存器表示一个16位无符号整数 |
4XXXX |
03,06,16 |
保持寄存器 |
读写 |
每个寄存器表示一个16位无符号整数 |
5XXXX |
03,04,06,16 |
ASCII字符 |
读写 |
每个寄存器表示两个ASCII码 |
4.Modbus RTU/ASCII/TCP:Modbus协议最开始是用于可编程逻辑控制器(PLC)之间的通讯,由于其具有的开放性,大量的用于现场智能仪表。Modbus协议有多个变种,其中最著名的是Modbus RTU/Modbus ASCII和Modbus TCP通信协议。其中RTU/ASCII协议是基于串行口通信,而TCP协议则是基于以太网通信。他们之间的区别和联系请参考本站其他页面内容:Modbus RTU/TCP协议解析以及Modbus RTU/ASCII通信协议异同点。
5.Modbus错误代码表,modbus有功能码,校验码,异常功能码和错误代码,其中异常功能码和错误代码非常容易混淆,一般来说异常功能码指的是某个功能码执行的时候出现的相应异常功能码,一般都是在功能码的基础上加上0x80,比如03功能码出现的异常码是0x83异常功能码,16功能码对应出现的异常功能码则是0x90,而错误代码则是表示出现错误的具体情况,比如寄存器地址不存在,不管是读还是写,如果该寄存器地址不存在的话,错误代码为02。具体情况请参阅本站其他页面文章。
- 2. Modbus常用功能码协议详解
01H-读线圈状态
1)描述:读从机线圈寄存器,位操作,可读单个或者多个;
2)发送指令:
假设从机地址位0x01,寄存器开始地址0x0023,寄存器结束抵制0x0038,总共读取21个线圈。协议图如下:
3)响应:
返回数据的每一位对应线圈状态,1-ON,0-OFF,如下图;
上表中data1表示0x0023-0x002a的线圈状态,data1的最低位代表最低地址的线圈状态,可以理解为小端模式;
data2表示地址0x002b-0x0033的线圈状态,如下表:
data3表示地址0x0034-0x0038的线圈状态,不够8位,字节高位填充为0,如下表:
02H-读离散输入状态
1):读离散输入寄存器,位操作,可读单个或多个,协议类似功能码0X01协议,此处省;
03H-读保持寄存器
1)描述:读保持寄存器,字节指令操作,可读单个或者多个;
2)发送指令:
从机地址0x01,保持寄存器起始地址0x0032,读2个保持寄存器
3)响应:
数据存储顺序
04H-读输入寄存器
1)描述:读输入寄存器,字节指令操作,可读单个或者多个;
2)发送指令:同03H;
3)响应:同03H;
05H-写单个线圈
1)描述:写单个线圈,位操作,只能写一个,写0xff00表示设置线圈状态为ON,写0x0000表示设置线圈状态为OFF
2)发送指令:
设置0x0032线圈为ON;
3)响应:
同发送指令;
06H-写单个保持寄存器
1)描述:写单个保持寄存器,字节指令操作,只能写一个;
2)发送指令:
写0x0032保持寄存器为0x1232;
3)响应:同发送指令;
0FH-写多个线圈
1)描述:写多个线圈寄存器。若数据区的某位值为“1”表示被请求的相应线圈状态为ON,若某位值为“0”,则为状态为OFF。
2)发送指令:
线圈地址为0x04a5,写12个线圈,
上图中DATA1为0x0c,表示:
DATA2为0x02,不够8位,字节高位填充0:
3)响应:
10H-写多个保持寄存器
1)描述:写多个保持寄存器,字节指令操作,可写多个;
2)发送指令:
保持寄存器起始地址为0x0034,写2个寄存器4个字节的数据;
3)响应:
- 3. MODBUS指令说明
2.1 读线圈寄存器01H
1) 描述:
读MODBUS从机线圈寄存器当前状态。
2) 查询:
例如从机地址为11H,线圈寄存器的起始地址为0013H,结束地址为0037H。该次查询总共访问37个线圈寄存器。
表2.1.1 读线圈寄存器-查询
|
Hex |
从机地址 |
11 |
功能码 |
01 |
寄存器起始地址高字节 |
00 |
寄存器起始地址低字节 |
13 |
寄存器数量高字节 |
00 |
寄存器数量低字节 |
25 |
CRC校验高字节 |
0E |
CRC校验低字节 |
84 |
3) 响应
响应负载中的各线圈状态与数据内容每位相对应。1代表ON,0代表OFF。若返回的线圈数不为8的倍数,则在最后数据字节未尾使用0代替。
表2.1.2 读线圈寄存器-响应
|
Hex |
从机地址 |
11 |
功能码 |
01 |
返回字节数 |
05 |
数据1(线圈0013H-线圈001AH) |
CD |
数据2(线圈001BH-线圈0022H) |
6B |
数据3(线圈0023H-线圈002AH) |
B2 |
数据4(线圈0032H-线圈002BH) |
0E |
数据5(线圈0037H-线圈0033H) |
1B |
CRC校验高字节 |
45 |
CRC校验低字节 |
E6 |
线圈0013H到线圈001AH的状态为CDH,二进制值为11001101,该字节的最高字节为线圈001AH,最低字节为线圈0013H。线圈001AH到线圈0013H的状态分别为ON-ON-OFF-OFF-ON-ON-OFF-ON。
表2.1.3 线圈0013H到001A状态
001AH |
0019H |
0018H |
0017H |
0016H |
0015H |
0014H |
0013H |
ON |
ON |
OFF |
OFF |
ON |
ON |
OFF |
ON |
最后一个数据字节中,线圈0033H到线圈0037状态为1BH(二进制00011011),线圈0037H是左数第4位,线圈0033H为该字节的最低字节,线圈0037H至线圈0033H的状态分别为ON-ON-OFF-ON-ON,剩余3位使用0填充。
表2.1.4 线圈0033H到线圈0037状态
003AH |
0039H |
0038H |
0037H |
0036H |
0035H |
0034H |
0033H |
填充 |
填充 |
填充 |
ON |
ON |
OFF |
ON |
ON |
2.2 读离散输入寄存器 02H
1) 说明
读离散输入寄存器状态。
2) 查询
从机地址为11H。离散输入寄存器的起始地址为00C4H,结束寄存器地址为00D9H。总共访问32个离散输入寄存器。
表 2.2.1 读离散输入寄存器——查询
|
Hex |
从机地址 |
11 |
功能码 |
02 |
寄存器地址高字节 |
00 |
寄存器地址低字节 |
C4 |
寄存器数量高字节 |
00 |
寄存器数量低字节 |
16 |
CRC校验高字节 |
BA |
CRC校验低字节 |
A9 |
3) 响应
响应各离散输入寄存器状态,分别对应数据区中的每位值,1 代表ON;0 代表OFF。第一个数据字节的LSB(最低字节)为查询的寻址地址,其他输入口按顺序在该字节中由低字节向高字节排列,直到填充满8位。下一个字节中的8个输入位也是从低字节到高字节排列。若返回的输入位数不是8的倍数,则在最后的数据字节中的剩余位至该字节的最高位使用0填充。
表2.2.1 读输入寄存器-响应
|
Hex |
从机地址 |
11 |
功能码 |
02 |
返回字节数 |
03 |
数据1(00C4H-00CBH) |
AC |
数据2(00CCH-00D3H) |
DB |
数据3(00D4H-00D9H) |
35 |
CRC校验高字节 |
20 |
CRC校验低字节 |
18 |
离散输入寄存器00D4H到00D9H的状态为35H (二进制00110101)。输入寄存器00D9H为左数第3位,输入寄存器00D4为最低位,输入寄存器00D9H到00D4H的状态分别为ON-ON-OFF-ON-OFF-ON。00DBH寄存器和00DAH寄存器被0填充。
表2.2.2 离散输入寄存器00C4H到00DBH状态
00CBH |
00CAH |
00C9H |
00C8H |
00C7H |
00C6H |
00C5H |
00C4H |
0 |
0 |
1 |
1 |
0 |
1 |
0 |
1 |
00D3H |
00D2H |
00D1H |
00D0H |
00CFH |
00CEH |
00CDH |
00CCH |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
1 |
00DBH |
00DAH |
00D9H |
00D8H |
00D7H |
00D6H |
00D5H |
00D4H |
填充 |
填充 |
1 |
1 |
0 |
1 |
0 |
1 |
2.3 读保持寄存器 03H
1) 说明
读保持寄存器。可读取单个或多个保持寄存器。
2) 查询
从机地址为11H。保持寄存器的起始地址为006BH,结束地址为006DH。该次查询总共访问3个保持寄存器。
表2.3.1 读保持寄存器-查询
|
Hex |
从机地址 |
11 |
功能码 |
03 |
寄存器地址高字节 |
00 |
寄存器地址低字节 |
6B |
寄存器数量高字节 |
00 |
寄存器数量低字节 |
03 |
CRC高字节 |
76 |
CRC低字节 |
87 |
3) 响应
保持寄存器的长度为2个字节。对于单个保持寄存器而言,寄存器高字节数据先被传输,低字节数据后被传输。保持寄存器之间,低地址寄存器先被传输,高地址寄存器后被传输。
表2.3.2 读保持寄存器-响应
|
Hex |
从机地址 |
11 |
功能码 |
03 |
字节数 |
06 |
数据1高字节(006BH) |
00 |
数据1低字节(006BH) |
6B |
数据2高字节(006CH) |
00 |
数据2 低字节(006CH) |
13 |
数据3高字节(006DH) |
00 |
数据3低字节(006DH) |
00 |
CRC高字节 |
38 |
CRC低字节 |
B9 |
表2.3.3 保持寄存器006BH到006DH结果
006BH 高字节 |
006BH 低字节 |
006CH 高字节 |
006CH 低字节 |
006DH 高字节 |
006DH 低字节 |
00 |
6B |
00 |
13 |
00 |
00 |
2.4 读输入寄存器 04H
1) 说明
读输入寄存器命令。该命令支持单个寄存器访问也支持多个寄存器访问。
2) 查询
从机地址为11H。输入寄存器的起始地址为0008H,寄存器的结束地址为0009H。本次访问访问2个输入寄存器。
表2.4.1 读输入寄存器-查询
|
Hex格式 |
从机地址 |
11 |
功能码 |
04 |
寄存器起始地址高字节 |
00 |
寄存器起始地址低字节 |
08 |
寄存器个数高字节 |
00 |
寄存器个数低字节 |
02 |
CRC高字节 |
F2 |
CRC低字节 |
99 |
3) 响应
输入寄存器长度为2个字节。对于单个输入寄存器而言,寄存器高字节数据先被传输,低字节数据后被传输。输入寄存器之间,低地址寄存器先被传输,高地址寄存器后被传输。
表2.4.2 读寄存器-响应
|
Hex格式 |
从机地址 |
11 |
功能码 |
04 |
字节数 |
04 |
数据1高字节(0008H) |
00 |
数据1低字节(0008H) |
0A |
数据2高字节(0009H) |
00 |
数据2低字节(0009H) |
0B |
CRC高字节 |
8B |
CRC低字节 |
80 |
表2.4.3 输入寄存器0008H到0009H结果
006BH 高字节 |
006BH 低字节 |
006CH 高字节 |
006CH 低字节 |
00 |
0A |
00 |
0B |
2.5 写单个线圈寄存器 05H
1) 说明
写单个线圈寄存器。FF00H值请求线圈处于ON状态,0000H值请求线圈处于OFF状态。05H指令设置单个线圈的状态,15H指令可以设置多个线圈的状态,两个指令虽然都设定线圈的ON/OFF状态,但是ON/OFF的表达方式却不同。
2) 查询
从机地址为11H,线圈寄存器的地址为00ACH。使00ACH线圈处于ON状态,即数据内容为FF00H。
表2.5.1 写单个线圈-查询
|
Hex |
从机地址 |
11 |
功能码 |
05 |
寄存器地址高字节 |
00 |
寄存器地址低字节 |
AC |
数据1高字节 |
FF |
数据2低字节 |
00 |
CRC校验高字节 |
4E |
CRC校验低字节 |
8B |
3) 响应
2.5.1强制单个线圈——响应
|
Hex |
从机地址 |
11 |
功能码 |
05 |
寄存器地址高字节 |
00 |
寄存器地址低字节 |
AC |
寄存器1高字节 |
FF |
寄存器1低字节 |
00 |
CRC校验高字节 |
4E |
CRC校验低字节 |
8B |
2.6 写单个保持寄存器 06H
1) 说明
写保持寄存器。注意06指令只能操作单个保持寄存器,16指令可以设置单个或多个保持寄存器。
2) 查询
从机地址为11H。保持寄存器地址为0001H。寄存器内容为0003H。
表2.6.1 写单个保持寄存器——查询
|
Hex |
从机地址 |
11 |
功能码 |
06 |
寄存器地址高字节 |
00 |
寄存器地址低字节 |
01 |
数据1高字节 |
00 |
数据1低字节 |
01 |
CRC校验高字节 |
9A |
CRC校验低字节 |
9B |
3) 响应
表2.6.2 写单个保持寄存器——响应
|
Hex |
从机地址 |
11 |
功能码 |
06 |
寄存器地址高字节 |
00 |
寄存器地址低字节 |
01 |
寄存器数量高字节 |
00 |
寄存器数量低字节 |
01 |
CRC校验高字节 |
1B |
CRC校验低字节 |
5A |
2.7 写多个线圈寄存器 0FH
1) 说明
写多个线圈寄存器。若数据区的某位值为“1”表示被请求的相应线圈状态为ON,若某位值为“0”,则为状态为OFF。
2) 查询
从机地址为11H,线圈寄存器的起始地址为0013H,线圈寄存器的结束地址为001CH。总共访问10个寄存器。寄存器内容如下表所示。
表2.7.1 线圈寄存器0013H到001CH
001AH |
0019H |
0018H |
0017H |
0016H |
0015H |
0014H |
0013H |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
0022H |
0021H |
0020H |
001FH |
001EH |
001DH |
001CH |
001BH |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
传输的第一个字节 CDH 对应线圈为0013H到001AH,LSB(最低位)对应线圈0013H,传输第二个字节为 01H,对应的线圈为001BH到001CH,LSB 对应线圈001CH,其余未使用位使用0 填充。
表2.7.1 写多个线圈寄存器——查询
|
Hex |
从机地址 |
11 |
功能码 |
0F |
寄存器地址高字节 |
00 |
寄存器地址低字节 |
13 |
寄存器数量高字节 |
00 |
寄存器数量低字节 |
0A |
字节数 |
02 |
数据1(0013H-001AH) |
CD |
数据2(001BH-001CH) |
01 |
CRC校验高字节 |
BF |
CRC校验低字节 |
0B |
3) 响应
表2.7.1 写多个线圈寄存器——响应
|
Hex |
从机地址 |
11 |
功能码 |
0F |
寄存器地址高字节 |
00 |
寄存器地址低字节 |
13 |
寄存器数量高字节 |
00 |
寄存器数量低字节 |
0A |
字节数 |
02 |
CRC校验高字节 |
99 |
CRC校验低字节 |
1B |
2.8 写多个保持寄存器10H
1) 说明
写多个保持寄存器。
2) 查询
从机地址为11H。保持寄存器的其实地址为0001H,寄存器的结束地址为0002H。总共访问2个寄存器。保持寄存器0001H的内容为000AH,保持寄存器0002H的内容为0102H。
表2.8.1 写多个保持寄存器——请求
|
Hex |
从机地址 |
11 |
功能码 |
10 |
寄存器起始地址高字节 |
00 |
寄存器起始地址低字节 |
01 |
寄存器数量高字节 |
00 |
寄存器数量低字节 |
02 |
字节数 |
04 |
数据1高字节 |
00 |
数据1低字节 |
0A |
数据2高字节 |
01 |
数据2低字节 |
02 |
CRC校验高字节 |
C6 |
CRC校验低字节 |
F0 |
表2.8.2 保持寄存器0001H到0002H内容
地址 |
0001H高字节 |
0001H低字节 |
0002H高字节 |
0003H低字节 |
数值 |
00 |
0A |
01 |
12 |
3) 响应
表2.8.3 写多个保持寄存器——响应
|
Hex |
从机地址 |
11 |
功能码 |
10 |
寄存器起始地址高字节 |
00 |
寄存器起始地址低字节 |
01 |
寄存器数量高字节 |
00 |
寄存器数量低字节 |
02 |
CRC校验高字节 |
12 |
CRC校验低字节 |
98 |