Modbus通信协议指令学习记录

  • Modbus协议版本
  • 读取指令格式
  • Modbus RTU
  • Modbus ASCII
  • Modbus TCP
  • 写入指令格式
  • Modbus RTU
  • Modbus ASCII
  • Modbus TCP
  • 后记


Modbus协议版本

Modbus协议目前存在Modbus RTU、Modbus ASCII、Modbus TCP三个版本。

  1. Modbus RTU协议是一种紧凑的,采用二进制表示数据的方式,带有循环冗余校验的校验和;
  2. Modbus ASCII协议是一种人类可读的,冗长的表示方式,采用纵向冗余校验的校验和;
  3. Modbus TCP协议,这种方式不需要校验和计算。
    大多数Modbus设备如:液位计、流量计、智能电表等通过串行通信,采用Modbus RTU和Modbus ASCII协议。
    PLC设备一般通过TCP/UDP连接,采用Modbus TCP协议。
    因为设备的限制和串行通信的需求,也可以采用Modbus RTU over TCP/UDP的通信方式,即通过TCP/UDP连接,但是采用Modbus RTU协议

读取指令格式

下面以同一含义(地址相同,读取数据相同),不同协议对比分析各协议不同。
考虑到使用过程中03功能码比较常用,所以以03读取为例

Modbus RTU

Modbus RTU为传感器类设备、普通智能电表常用的协议一定要弄清楚。
请求:01 03 00 00 00 02 C4 0B
01:设备地址 ,设备地址为1
03:功能码 ,当前为03读取请求
00 00:寄存器起始地址,从00 00寄存器开始读取
00 02:读取寄存器长度 ,读取2个长度,对应回复4个字节
C4 0B:CRC效验和
回复:01 03 04 00 0C 00 02 BB F1
01:设备地址 ,设备地址为1
03:功能码,当前为03读取回复
04:数据长度 ,包含4个字节的数据
00 0C:寄存器1数值
00 02:寄存器2数值
BB F1:CRC效验和

Modbus ASCII

同一条命令用Modbus RTU和Modbus ASCII方式表现出来,虽然在命令长度上有很大区别(ASCII为RTU的两倍),但表达的意思是完全一样的,所以不建议使用。
请求:3A 30 31 30 33 30 30 30 30 30 30 30 32 46 41 0D 0A
3A:起始符
30 31:设备地址
30 33:功能码
30 30 30 30:寄存器起始地址
30 30 30 32:读取寄存器长度
46 41:LRC效验和
0D 0A:结束符
回复:3A 30 31 30 33 30 34 30 30 30 43 30 30 30 32 45 41 0D 0A
3A:起始符
30 31:设备地址
30 33:功能码
30 34:数据长度
30 30 30 43:寄存器1数值
30 30 30 32:寄存器2数值
45 41:LRC效验和
0D 0A: 结束符

Modbus TCP

因为以TCP为连接,有TCP效验保证数据准确,所以协议中取消了效验和。
请求:00 00 00 00 00 06 01 03 00 00 00 02
00 00:事务标识符,当前为第几次通信,回复与一直,可以通过这项判断请求与指令是否匹配
00 00:协议标识符
00 06:剩余长度
01:设备地址
03:功能码
00 00:寄存器起始地址
00 02:读取寄存器长度
回复:00 00 00 00 00 07 01 03 04 00 0C 00 02
00 00:事务标识符
00 00:协议标识符
00 07:剩余长度
01:设备地址
03:功能码
04:数据长度
00 0C:寄存器1数值
00 02:寄存器2数值

写入指令格式

下面以同一含义(地址相同,读取数据相同),不同协议对比分析各协议不同。
考虑到使用过程中10功能码可以写入一个或多个寄存器,所以以10写入为例

Modbus RTU

Modbus RTU为传感器类设备、普通智能电表常用的协议一定要弄清楚。
请求:01 10 00 00 00 02 04 00 00 00 0A 73 A8
01:设备地址 ,设备地址为1
10:功能码 ,当前为10写入请求
00 00:寄存器起始地址,从00 00寄存器开始写入
00 02:写入寄存器长度 ,写入2个长度,对应后面4个字节数据
04:数据长度 ,包含4个字节的数据
00 00:寄存器1数值
00 0A:寄存器2数值
73 A8:CRC效验和
回复:01 10 00 00 00 02 41 C8
01:设备地址 ,设备地址为1
10:功能码,当前为10写入回复
00 00:寄存器起始地址,从00 00寄存器开始写入
00 02:写入寄存器长度 ,写入2个长度
41 C8:CRC效验和

Modbus ASCII

同一条命令用Modbus RTU和Modbus ASCII方式表现出来,虽然在命令长度上有很大区别(ASCII为RTU的两倍),但表达的意思是完全一样的,所以不建议使用。
请求:3A 30 31 31 30 30 30 30 30 30 30 30 32 30 34 30 30 30 30 30 30 30 41 44 46 0D 0A
3A:起始符
30 31:设备地址
31 30:功能码
30 30 30 30:寄存器起始地址
30 30 30 32:写入寄存器长度
30 34:数据长度
30 30 30 30:寄存器1数值
30 30 30 41:寄存器2数值
44 46:LRC效验和
0D 0A:结束符
回复:3A 30 31 31 30 30 30 30 30 30 30 30 32 45 44 0D 0A
3A:起始符
30 31:设备地址
31 30:功能码
30 30 30 30:寄存器起始地址
30 30 30 32:写入寄存器长度
45 44:LRC效验和
0D 0A: 结束符

Modbus TCP

因为以TCP为连接,有TCP效验保证数据准确,所以协议中取消了效验和。
请求:00 00 00 00 00 0B 01 10 00 00 00 02 04 00 00 00 0A
00 00:事务标识符,当前为第几次通信,回复与一直,可以通过这项判断请求与指令是否匹配
00 00:协议标识符
00 0B:剩余长度
01:设备地址
10:功能码
00 00:寄存器起始地址
00 02:写入寄存器长度
04:数据长度
00 00:寄存器1数值
00 0A:寄存器2数值
回复:00 00 00 00 00 06 01 10 00 00 00 02
00 00:事务标识符
00 00:协议标识符
00 06:剩余长度
01:设备地址
10:功能码
00 00:寄存器起始地址
00 02:写入寄存器长度

后记

本文只是记录本人学习过程中的理解,可能有部分内容有纰漏,望各位不吝赐教。