modbus TCP 协议小记

最近有个项目要用modbus TCP,更详细了解了一下modbus这个协议
首先modbus有两种传输数据的方式一种是RTU一种是ASCII,前者是基于byte的,后者是基于可读的ascii码的。也就是说前者是规定了每个byte数值的特定含义,后者传输的数据则更可以直接看懂。所以前者更像是传输的时候数据压缩后的ascii协议,一般单片机和模块之间通讯的时候用的就是和前者类似的包头+长度+内容+校验的方式。

对于modbus TCP来说,因为tcp本身是有校验功能的,所以取消了RTU里的CRC校验,不过也有会在后面加上校验的。数据包的构成如下

事务处理标识符 协议标识符 长度 从机地址 功能码 数据
2 Byte 2 Byte 2 Byte 1 Byte 1 Byte -
用于标识不同的事件,主机发起事件的时候带一个事件的标识符,从机返回的时候带相同的标识符,这样网络就可以允许同时发生多个未处理的请求 modbus这里都是0x0000 表示这次传输的包有多少个byte,从下一个开始到结束 就是slave address,网络中不同的从机用来区分这个包是不是给自己发的 具体功能码的含义可以看下面 具体的数据

功能码 原文在这里

0类代码

0类代码通常被认为是有用Modbus设备的最低配置,因为它们使主设备能够读取或写入数据模型。

代码 说明
3 读多寄存器
16 写多寄存器

1类代码

1类代码
1类功能代码由访问所有类型的数据模型所需的其他代码组成。 在原始定义中,这个列表包含功能代码7(读取异常)。 但是,此代码由当前规范定义为仅限于串行的代码。

代码 说明
1 读线圈
2 读离散输入
4 读输入寄存器
5 写单线圈
6 写单寄存器
7 读取异常状态(仅限串行)








以下测试都是在ESP32上基于这个库的测试


05-写单个线圈

当功能码为05,即写入单个线圈的时候,如果要打开线圈,数据部分应该是0xFF00,关闭则是0x0000
所以比如 如果要打开100号线圈的话,主机应该发送

事务处理标识符 协议标识符 长度 从机地址 功能码:写单线圈 线圈编号100 的十六进制大端模式 数据:打开线圈 CRC校验码
00 00 00 00 00 08 01 05 00 64 FF' 00 CD E5

返回和发送的数据相同

01-读线圈

读线圈的话应该发送

事务处理标识符 协议标识符 长度 从机地址 功能码:读线圈 线圈编号100 的十六进制大端模式 数据:读取线圈数量 CRC校验码
00 00 00 00 00 08 01 01 00 64 00 01 BC 15

返回的数据是如果正常的话应该是

事务处理标识符 协议标识符 长度 从机地址 功能码:读线圈 不知道是什么。。猜测是表示后面bytes的数量 状态值:01
00 00 00 00 00 04 01 01 01 01

这里最后状态值其实是每一个二进制位代表一个线圈,也就是理论上这一个byte是可以传递8个线圈的,但是因为我们前面值查询了1个线圈,所以只用了最后一个代表开关,如果这个线圈是关闭的,就会返回00

你可能感兴趣的:(modbus TCP 协议小记)