因在工作中遇到以前的代码读取聚英PLC设备开关状态失败问题,所以就好好研究了一下ModBus协议,在此记录一下ModBus TCP/IP协议
协议的作用
- 规定与PLC交互的指令(数据帧)
- 数据帧包括两部分:数据帧=报文头(MBAP)+帧结构(PDU),下面主要介绍报文头和帧结构的取值及作用
数据帧
报文头(MBAP)
内容 | 解释 | 长度 |
---|
事务处理标识 | 可以理解为报文序列号,一般每次通信之后就要加1以区别不同的通信数据报文 | 2byte | 协议标识符 | 00 00表示ModbusTCP协议 | 2byte | 长度 | 后面数据字节长度(单元标识符字节长度+功能码字节长度+数据域字节长度) | 2byte | 单元标识符 | 可以理解为设备地址 | 1byte | 功能码 | 功能标识 | 1byte | 数据域 | 看具体功能拼接参数 | 不定 |
- 事务处理标识:单线程操作此值可以为常量,多线程操作需要根据标识匹配请求。请求和响应该标识一样。
- 协议标识符:0000表示ModbusTCP协议
- 长度:单元标识符字节长度+功能码字节长度+数据域字节长度
- 单元标识符:软件测试取值01
- 功能码:本人实际测试了0x01,0x02,0x03,0x05
- 0x01 读线圈
- 0x05 写单个线圈
- 0x0F 写多个线圈
- 0x02 读离散量输入
- 0x04 读输入寄存器
- 0x03 读保持寄存器
- 0x06 写单个保持寄存器
- 0x10 写多个保持寄存器
帧结构(PDU)
- 读取线圈的帧结构:两个字节的起始地址+两个字节读取的个数;eg:读取从0开始的10个线圈状态的指令:0000 0000 0006 01 01 0000 000A
- 写单个线圈的帧结构:两个字节的地址+两个字节目标状态;eg:打开地址0线圈的指令:0000 0000 0006 01 05 0000 FF00
- 读取离散输入的帧结构:两个字节的地址+两个字节读取的个数;eg:读取从0开始的10个离散输入状态的指令:0000 0000 0006 01 02 0000 000A
- 读取保持寄存器的帧结构:两个字节的地址+两个字节读取的个数;eg:读取从0开始的10个保持寄存器状态的指令:0000 0000 0006 01 03 0001 000A
ModBus 协议测试软件ModBus Poll使用说明参考:https://blog.csdn.net/dhbfjh/article/details/119002843
|