1、简介
Modbus TCP是一种应用于工业自动化领域的通信协议,它是Modbus协议的一个变种,采用TCP/IP协议进行数据传输。Modbus TCP使得Modbus协议可以通过以太网网络运行,允许设备之间在IP网络上交换数据。
在Modbus TCP协议中,通信通常由一个客户端(通常称为Master)和一个或多个服务器(Slave)进行。客户端发出请求,服务器响应这些请求。这些请求和响应包括读取或写入服务器中存储的数据。这些数据可以是输入/输出状态、保持寄存器、模拟输入等。
Modbus TCP常用于工业环境中,用于连接控制系统和现场设备,如传感器、执行器、变频器等。它特别适用于那些需要在设备之间进行快速、可靠通信的场景。
2、modbus TCP常用功能码
功能码
Hex表示
功能
备注
1
0x01
读取线圈
可读写开关量 接受05、15写入
2
0x02
读取离散输入
只读开关量
3
0x03
读取保持寄存器
可读性模拟量 接受06、16写入
4
0x04
读取输入寄存器
只读模拟量
5
0x05
写入单线圈
0xFF00表示ON(True) 0x0000表示OFF(False)
6
0x06
写入单个寄存器
只能操作1个寄存器(2字节)
15
0x0F
写入多个线圈
每个字节只能存储一个线圈的值
16
0x10
写入多个寄存器
操作的基本单位是字节
3、常用功能码及名词解释
线圈(Coils)
线圈在Modbus协议中可以类比为布尔类型的变量。每个线圈代表一个单一的二进制位,通常用于控制或指示某个功能的开/关状态。例如,在编程中,你可能会用一个布尔变量来控制一个循环是否继续执行或判断一个条件是否满足,类似地,在Modbus中,线圈可以用来控制一个电机的启停或检测某个开关是否被激活。
寄存器(Registers)
寄存器则可以类比为程序中的整数变量。在Modbus中,寄存器是16位的,这意味着它可以存储从0到65535的整数值。寄存器根据其用途可分为保持寄存器和输入寄存器:
- 保持寄存器(Holding Registers):这些寄存器可以读写,类似于普通的变量。它们可用于保存可更改的设置或中间计算结果。
- 输入寄存器(Input Registers):这些寄存器仅供读取,类似于常量或只读变量。它们常用于保存从设备如传感器获取的不可更改数据。
4、常用数据类型
英文描述
简易表示
转换过程
目标顺序
中文描述
go类型
占用字节
字节序
字节交换
Signed
int16
有符号整数
int16
2
Unsigned
uint16
无符号整数
uint16
2
Float little-endian byte swap
float32CDAB
ABCD->DCBA->CDAB
CDAB
浮点数
float32
4
小端
√
Float big-endian
float32ABCD
ABCD
ABCD
浮点数
float32
4
大端
×
Float little-endian
float32DCBA
ABCD->DCBA
DCBA
浮点数
float32
4
小端
×
Float big-endian byte swap
float32BADC
ABCD->BADC
BADC
浮点数
float32
4
大端
√
32-bit Signed big-endian byte swap
int32BADC
ABCD->BADC
BADC
有符号整数
int32
4
大端
√
32-bit Unsigned big-endian
uint32ABCD
ABCD
ABCD
无符号整数
uint32
4
大端
×
32-bit Unsigned little-endian byte swap
uint32CDAB
ABCD->DCBA->CDAB
CDAB
无符号整数
uint32
4
小端
√
32-bit Unsigned big-endian byte swap
uint32BADC
ABCD->BADC
BADC
无符号整数
uint32
4
大端
√
32-bit Unsigned little-endian
uint32DCBA
ABCD->DCBA
DCBA
无符号整数
uint32
4
小端
×
32-bit Signed little-endian byte swap
uint32CDAB
ABCD->DCBA->CDAB
CDAB
有符号整数
uint32
4
小端
√
32-bit Signed big-endian
int32ABCD
ABCD
ABCD
有符号整数
int32
4
大端
×
32-bit Signed little-endian
uint32DCBA
ABCD-DCBA
DCBA
有符号整数
uint32
4
小端
×
Double little-endian byte swap
float64GHEFCDAB
ABCDEFGH->HGFEDCBA->GHEFCDAB
GHEFCDAB
双精度浮点数
float64
8
小端
√
Double big-endian
float64ABCDEFGH
ABCDEFGH
ABCDEFGH
双精度浮点数
float64
8
大端
×
Double little-endian
float64HGFEDCBA
ABCDEFGH->HGFEDCBA
HGFEDCBA
双精度浮点数
float64
8
小端
×
Double big-endian byte swap
float64BADCFEHG
ABCDEFGH->BADCFEHG
BADCFEHG
双精度浮点数
float64
8
大端
√
64-bit Signed big-endian
int64ABCDEFGH
ABCDEFGH
ABCDEFGH
有符号整数
int64
8
大端
×
64-bit Signed little-endian byte swap
int64GHEFCDAB
ABCDEFGH->HGFEDCBA->GHEFCDAB
GHEFCDAB
有符号整数
int64
8
小端
√
64-bit Signed big-endian byte swap
int64BADCFEHG
ABCDEFGH->BADCFEHG
BADCFEHG
有符号整数
int64
8
大端
√
64-bit Signed little-endian
int64HGFEDCBA
ABCDEFGH->HGFEDCBA
HGFEDCBA
有符号整数
int64
8
小端
×
64-bit Unsigned big-endian
uint64ABCDEFGH
ABCDEFGH
ABCDEFGH
无符号整数
uint64
8
大端
×
64-bit Unsigned little-endian byte swap
uint64GHEFCDAB
ABCDEFGH->HGFEDCBA->GHEFCDAB
GHEFCDAB
无符号整数
uint64
8
小端
√
64-bit Unsigned big-endian byte swap
uint64BADCFEHG
ABCDEFGH->BADCFEHG
BADCFEHG
无符号整数
uint64
8
大端
√
64-bit Unsigned little-endian
uint64ABCDEFGH
ABCDEFGH
ABCDEFGH
无符号整数
uint64
8
小端
×
Hex
十六进制
Binary
bool
二进制
bool
1/8
大端(Big Endian)
在大端字节序中,多字节数据的最高有效字节(MSB)存储在最低的内存地址,其余字节按照重要性递减的顺序存储。这意味着数据的第一个字节是最重要的一个字节。
例如,16位整数
0x1234
在大端模式下的存储顺序是:
代码语言:javascript
复制
Memory Address -> | 12 | 34 |
其中,
12
是高位,存储在较低的地址。
小端(Little Endian)
在小端字节序中,多字节数据的最低有效字节(LSB)存储在最低的内存地址,其余字节按照重要性递增的顺序存储。这意味着数据的最后一个字节是最重要的一个字节。
例如,16位整数
0x1234
在小端模式下的存储顺序是:
代码语言:javascript
复制
Memory Address -> | 34 | 12 |
其中,
34
是低位,存储在较低的地址。
字节交换(Byte Swap)
字节交换是指在大端和小端之间转换数据时改变字节的顺序的过程。这通常在不同的计算系统之间传输数据时需要考虑,因为不同系统可能采用不同的字节序。字节交换确保数据在一个系统中被正确解释和使用。
例如,如果一个小端系统发送
0x1234
给一个大端系统,没有适当的字节交换,大端系统将会错误地解释这个数字为
0x3412
。为了防止这种情况,发送前需要将字节顺序从小端转换为大端,或者接收方需要在接收后进行转换。
按照字节来解析,最主要还是需要看转换过程,比如ABCD->DCBA->CDAB 相当于在程序中表达的ABCD字节,在进行modbus传输的时候需要将数据字节顺序转换成CDAB,以此类推。
5、01功能码解析
01功能码中的数据能够接受05功能码(单个线圈的控制)和15功能码(多个线圈的控制)的写入
(1)请求
事务标识符
协议标识符
长度字段
单元标识符
功能码
起始地址
数量
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
远程服务器地址,默认1
0x01
要读取的第一个线圈的地址
要读取的线圈数量
**事务标识符: **占用2字节,用来计数。例如客户端发送了0x00的事务标识,服务端接收到请求后也会带有0x00的事务标识进行返回,也就是说正常情况下单链路访问并发不能超过2字节(65535个)否则会导致接收到事务重复的回复数据。
长度字段: 这个字节之后剩余数据的长度
协议标识符: modbus 特有的协议标识,固定值
单元标识符: 服务器(Slave)的标记,一般一个网络中只有一个,所以默认为1,如果有多个就依次排序,不能重复。
功能码: 第一段中列出的功能码
起始地址: 在modbus中,每一个数据都有一个地址,在数据请求的时候,针对线圈(开关量)都是进行批量请求,所以在接收到服务端返回的数据的时候,需要用户自己来维护。我举一个例子:当你请求一个线圈(开关量)数据的时候,你应该设置其实地址为线圈实际地址,然后数量设置为1。但是在返回数据的时候是按照字节返回的,也就是说会直接返回8个开关量。这时候你只需要解析这个字节的第0位的数据状态就行,剩下的都是被服务端填充的。
数量: 要读取的线圈数量
(2)响应
事务标识符
协议标识符
长度字段
单元标识符
功能码
字节计数
状态
2字节
2字节
2字节
1字节
1字节
1字节
N字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
与请求包中的相同
0x01
表示后续线圈状态值的字节数
每个字节表示8个线圈的状态,1表示ON,0表示OFF
6、02功能码解析
02功能码只能读取数据,不能写入数据
(1)请求
事务标识符
协议标识符
长度字段
单元标识符
功能码
起始地址
数量
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
远程服务器地址,默认1
0x02
要读取的第一个线圈的地址
要读取的线圈数量
(2)响应
事务标识符
协议标识符
长度字段
单元标识符
功能码
字节计数
状态
2字节
2字节
2字节
1字节
1字节
1字节
N字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
与请求包中的相同
0x02
表示后续线圈状态值的字节数
每个字节表示8个线圈的状态,1表示ON,0表示OFF
7、03功能码
(1)请求
事务标识符
协议标识符
长度字段
单元标识符
功能码
起始地址
寄存器数量
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
远程服务器地址,默认1
0x03
表示请求的起始寄存器的地址
要读取的寄存器数量
(2)响应
事务标识符
协议标识符
长度字段
单元标识符
功能码
字节计数
数据
2字节
2字节
2字节
1字节
1字节
1字节
N字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
与请求包中的相同
0x03
表示接下来的数据字节的数量
实际的寄存器值,数量由字节计数确定
8、04功能码
(1)请求
事务标识符
协议标识符
长度字段
单元标识符
功能码
起始地址
寄存器数量
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
远程服务器地址,默认1
0x04
表示请求的起始寄存器的地址
要读取的寄存器数量
(2)响应
事务标识符
协议标识符
长度字段
单元标识符
功能码
字节计数
数据
2字节
2字节
2字节
1字节
1字节
1字节
N字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
与请求包中的相同
0x04
表示接下来的数据字节的数量
实际的寄存器值,数量由字节计数确定
9、05功能码
(1)请求
事务标识符
协议标识符
长度字段
单元标识符
功能码
输出地址
输出值
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
远程服务器地址,默认1
0x05
表示请求的起始寄存器的地址
将该线圈设置为ON或OFF。0x0000表示OFF,0xFF00表示ON
(2)响应
事务标识符
协议标识符
长度字段
单元标识符
功能码
输出地址
输出值
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
与请求包中的相同
0x05
表示接下来的数据字节的数量
实际的寄存器值,数量由字节计数确定
10、06功能码
(1)请求
事务标识符
协议标识符
长度字段
单元标识符
功能码
寄存器地址
寄存器值
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
远程服务器地址,默认1
0x06
寄存器的地址
寄存器的数据
(2)响应
事务标识符
协议标识符
长度字段
单元标识符
功能码
寄存器地址
寄存器值
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
与请求包中的相同
0x06
寄存器的地址
寄存器的数据
11、15功能码
(1)请求
事务标识符
协议标识符
长度字段
单元标识符
功能码
起始地址
输出数量
字节计数
数据
2字节
2字节
2字节
1字节
1字节
2字节
2字节
1字节
N字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
远程服务器地址,默认1
0x0F
寄存器的地址
指示要写入的线圈数量
随后的字节数量
线圈的值,每个线圈占1位,字节间从左到右填充,不足一个字节的部分填充至右侧。
(2)响应
事务标识符
协议标识符
长度字段
单元标识符
功能码
起始地址
输出数量
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
与请求包中的相同
0x0F
寄存器的地址
指示要写入的线圈数量
12、16功能码
(1)请求
事务标识符
协议标识符
长度字段
单元标识符
功能码
起始地址
寄存器数量
字节计数
寄存器值
2字节
2字节
2字节
1字节
1字节
2字节
2字节
1字节
N字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
远程服务器地址,默认1
0x10
寄存器的地址
寄存器的数据
随后的字节数(应等于寄存器数量乘以2,因为每个寄存器是2字节)
要写入的实际值,其中N是要写入的寄存器数量。
(2)响应
事务标识符
协议标识符
长度字段
单元标识符
功能码
起始地址
寄存器数量
2字节
2字节
2字节
1字节
1字节
2字节
2字节
标识Modbus事务
固定值0x0000
这个字节之后剩余数据的长度
与请求包中的相同
0x10
确认消息中涉及的第一个寄存器的地址。
确认消息中写入的寄存器数量。
版权归原作者 ljklxlj 所有, 如有侵权,请联系我们删除。