本文主要是介绍Modbus通信协议--RTU,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、RTU介绍
MODBUS协议支持多种功能码,不同的功能码对应不同的操作:
0x01 | 读线圈状态 |
0x02 | 读离散输入状态 |
0x03 | 读保持寄存器 |
0x04 | 读输入寄存器 |
0x05 | 写单个线圈 |
0x06 | 写单个保持寄存器 |
0x0F | 写多个线圈 |
0x10 | 写多个保持寄存器 |
二、实验
1.0x03功能码读单个保持寄存器
1.1 请求帧格式
从站地址 | 功能码 | 起始地址(高位) | 起始地址(低位) | 数量(高位) | 数量(低位) | 校验码(低位) | 校验码(高位) |
---|---|---|---|---|---|---|---|
0x01 | 0x03 | 0x00 | 0x45 | 0x00 | 0x01 | XX | XX |
-
0x01:从地址(Slave Address)。这个值表示这是发送给地址为1的从设备。
-
0x03:功能码(Function Code)。这个值表示这是一个读取保持寄存器(Read Holding Registers)的请求。
-
0x00 0x45:起始地址(Starting Address)。这两个字节一起表示从哪个寄存器地址开始读取。0x0045等于十进制的69。
-
0x00 0x01:寄存器数量(Quantity of Registers)。这两个字节一起表示读取的寄存器数量。0x0001等于十进制的1。
-
XX XX:CRC校验码(CRC Checksum)。这是一个错误检测码,用于验证数据的完整性。实际的值需要根据前面的数据计算得出。
总结:这个Modbus数据帧请求读取从地址为1的设备从地址69开始的1个保持寄存器。
同理这个Modbus数据帧请求读取从地址为1的设备从地址66开始的1个保持寄存器。
1.2 应答帧格式
从站地址 | 功能码 | 字节计数 | 字节一(高位) | 字节一(低位) | 校验码(低位) | 校验码(高位) |
---|---|---|---|---|---|---|
0x01 | 0x03 | 0x02 | 0x00 | 0x00 | YY | YY |
-
0x01:从地址(Slave Address)。这个值表示这是从地址为1的设备发出的响应。
-
0x03:功能码(Function Code)。这个值表示这是一个读取保持寄存器(Read Holding Registers)的响应。
-
0x02:字节数(Byte Count)。这个值表示响应的数据部分包含2个字节。
-
0x00 0x00:数据(Data)。这两个字节表示从指定的寄存器读取到的值。在这个例子中,读取到的值是0x0000,即十进制的0。
-
YY YY:CRC校验码(CRC Checksum)。这是一个错误检测码,用于验证数据的完整性。实际的值需要根据前面的数据计算得出。
总结:这个数据帧表示从地址为1的设备,从地址69开始响应的数据部分包含2个字节(0x02)。 且从这个指定的寄存器读取到的值是0x0000。
同理从地址69开始响应的数据部分包含2个字节(0x02)。 且从这个指定的寄存器读取到的值是0x0001。
2.0x06功能码写入单个保持寄存器
2.1 请求帧格式
从站地址 | 功能码 | 寄存器高 | 寄存器低 | 写入值高 | 写入值低 | 校验码(低位) | 校验码(高位) |
---|---|---|---|---|---|---|---|
0x01 | 0x06 | 0x00 | 0x45 | 0x33 | 0x01 | XX | XX |
-
0x01:从地址(Slave Address)。表示这是发送给地址为1的从设备。
-
0x06:功能码(Function Code)。表示这是一个写单个寄存器的请求。
-
0x00 0x45:寄存器地址(Register Address)。这两个字节表示要写入的寄存器地址。0x0045等于十进制的69。
-
0x33 0x01:寄存器值(Register Value)。这两个字节表示要写入寄存器的值。0x3301可以表示为十进制的13057。
-
XX XX:CRC校验码(CRC Checksum)。这是一个错误检测码,用于验证数据的完整性。实际的值需要根据前面的数据计算得出。
在写入之后,可以用0x03功能码读取0x45地址的数据查看是否写入成功,可以从图中验证看到,0x3301成功写入0x45地址。
2.2 应答帧格式
原报文返回。
3.0x10功能码写入多个保持寄存器
3.1 请求帧格式
从站地址 | 功能码 | 起始地址(高位) | 起始地址(低位) | 数量(高位) | 数量(低位) | 字节数 | 写入数值 | 校验码(低位) | 校验码(高位) |
---|---|---|---|---|---|---|---|---|---|
0x01 | 0x10 | 0x00 | 0x45 | 0x00 | 0x02 | 0x04 | 0x138A 0x1388 | XX | XX |
-
0x01:从地址(Slave Address)。表示这是发送给地址为1的从设备。
-
0x10:功能码(Function Code)。表示这是一个写多个寄存器的请求。
-
0x00 0x45:起始地址(Starting Address)。这两个字节表示要写入的第一个寄存器地址。0x0045等于十进制的69。
-
0x00 0x02:寄存器数量(Quantity of Registers)。这两个字节表示要写入的寄存器数量。0x0002等于十进制的2。
-
0x04:字节计数(Byte Count)。这个值表示接下来要写入的数据字节数。在这个例子中两个寄存器就是是4个字节。
-
0x138A 0x1388:寄存器值(Register Values)。表示要写入寄存器的数据。由于有两个寄存器,每个寄存器占两个字节,所以这里总共4个字节:
- 0x138A
- 0x1388
-
XX XX:CRC校验码(CRC Checksum)。这是一个错误检测码,用于验证数据的完整性。实际的值需要根据前面的数据计算得出。
在写入之后,可以用0x03功能码读取0x45地址的数据查看是否写入成功,可以从图中验证看到,0x138A,0x1388成功写入从0x45开始往后的两个寄存器地址。
3.2 应答帧格式
从站地址 | 功能码 | 起始地址(高位) | 起始地址(低位) | 数量(高位) | 数量(低位) | 校验码(低位) | 校验码(高位) |
---|---|---|---|---|---|---|---|
0x01 | 0x10 | 0x00 | 0x45 | 0x00 | 0x02 | YY | YY |
-
0x01:从地址(Slave Address)。表示这是从地址为1的从设备发出的响应。
-
0x10:功能码(Function Code)。表示这是一个写多个寄存器的响应。
-
0x00 0x45:起始地址(Starting Address)。这两个字节表示写入操作开始的寄存器地址。0x0045等于十进制的69。
-
0x00 0x02:寄存器数量(Quantity of Registers)。这两个字节表示写入的寄存器数量。0x0002等于十进制的2。
-
YY YY:CRC校验码(CRC Checksum)。这是一个错误检测码,用于验证数据的完整性。实际的值需要根据前面的数据计算得出。
4.0x17功能码写入多个保持寄存器并读
4.1 请求帧格式
- 0x01:从地址(Slave Address)。表示这是发送给地址为1的从设备。
- 0x17:功能码(Function Code)。表示这是一个读取/写入多个寄存器的请求。
- 0x00 0x45:读取起始地址(Read Starting Address)。这两个字节表示要读取的寄存器地址。0x0045等于十进制的69。
- 0x00 0x02:读取寄存器数量(Quantity of Registers to Read)。这两个字节表示要读取的寄存器数量。0x0002等于十进制的2。
- 0x00 0x45:写入起始地址(Write Starting Address)。这两个字节表示要写入的寄存器地址。0x0045等于十进制的69。
- 0x00 0x02:写入寄存器数量(Quantity of Registers to Write)。这两个字节表示要写入的寄存器数量。0x0002等于十进制的2。
- 0x04:写入字节计数(Write Byte Count)。表示接下来要写入的数据字节数。在这个例子中是4个字节。
- 0x11 0x22:第一个寄存器的值。表示要写入的值是0x1122。
- 0x13 0x88:第二个寄存器的值。表示要写入的值是0x1388。
- 0xA6 0x1C:CRC校验码(CRC Checksum)。用于错误检测。
4.2 应答帧格式
- 0x01:从地址(Slave Address)。表示这是从地址为1的从设备发出的响应。
- 0x17:功能码(Function Code)。表示这是一个读/写多个寄存器的响应。
- 0x04:字节计数(Byte Count)。表示接下来的数据字节数。在这个例子中是4个字节。
- 0x11 0x22:读取的第一个寄存器的值。表示从请求中读取的值是0x1122。
- 0x13 0x88:读取的第二个寄存器的值。表示从请求中读取的值是0x1388。
- 0x51 0x47:CRC校验码(CRC Checksum)。用于错误检测。
4.3 写入数据问题总结
从图中可见,我在0x46地址写入0x1313之后,在应答帧中读取显示0x1310,并没有写入成功,这是因为有的寄存器地址存放的数值是动态变化的,写入之后,它又被动态变化的数值给覆盖
这篇关于Modbus通信协议--RTU的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!