构建Modbus TCP写多个寄存器指令详解
构建Modbus TCP写多个寄存器指令详解
在Modbus TCP通信中,构建正确的指令对于实现设备间的数据交换至关重要。本文将详细解释如何构建一个Modbus TCP指令,用于向设备地址为1的从站,从地址200(0xC8)开始,连续写入8个寄存器,其中前4个寄存器写入值1,后4个寄存器写入值2。
一、Modbus TCP帧结构
Modbus TCP帧由两部分组成:
- MBAP头(Modbus Application Protocol Header):7个字节
- PDU(Protocol Data Unit):功能码及其相关数据
1.1 MBAP头结构
字节序号 | 字段名称 | 长度 | 描述 |
---|---|---|---|
0-1 | 事务标识符 | 2 | 匹配请求与响应的唯一标识符 |
2-3 | 协议标识符 | 2 | 固定为0x0000,表示使用Modbus协议 |
4-5 | 长度字段 | 2 | 后续PDU部分的字节数,包括单元标识符 |
6 | 单元标识符 | 1 | 从设备的地址(这里为1) |
1.2 PDU结构
字节序号 | 字段名称 | 长度 | 描述 |
---|---|---|---|
0 | 功能码 | 1 | 指示操作类型(写多个寄存器为0x10) |
1-2 | 起始地址 | 2 | 要写入的第一个寄存器地址(0x00C8) |
3-4 | 寄存器数量 | 2 | 要写入的寄存器数量(8个) |
5 | 字节计数 | 1 | 后续数据部分的字节数(8个寄存器 × 2 = 16) |
6-21 | 寄存器值 | 16 | 要写入的寄存器值,每个寄存器2字节 |
二、构建指令步骤
2.1 确定各字段值
- 事务标识符(Transaction Identifier):任意选择一个唯一值,例如0x0001
- 协议标识符(Protocol Identifier):固定为0x0000
- 长度字段(Length Field):
- PDU部分包括:单元标识符(1) + 功能码(1) + 起始地址(2) + 寄存器数量(2) + 字节计数(1) + 寄存器值(16) = 23字节
- 因此,长度字段为0x0017(23)
- 单元标识符(Unit Identifier):1(目标从设备地址)
- 功能码(Function Code):0x10(写多个寄存器)
- 起始地址(Starting Address):0x00C8(200)
- 寄存器数量(Quantity of Registers):0x0008(8)
- 字节计数(Byte Count):0x10(16)
- 寄存器值(Register Values):
- 前4个寄存器值:0x0001, 0x0001, 0x0001, 0x0001
- 后4个寄存器值:0x0002, 0x0002, 0x0002, 0x0002
2.2 构建完整指令
将上述字段按顺序排列,得到完整的Modbus TCP指令:
[0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x01,
0x10, 0x00, 0xC8, 0x00, 0x08, 0x10,
0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02]
2.3 字节分解
字节序号 | 字节值 | 描述 |
---|---|---|
0-1 | 0x00 0x01 | 事务标识符(1) |
2-3 | 0x00 0x00 | 协议标识符(0) |
4-5 | 0x00 0x17 | 长度字段(23) |
6 | 0x01 | 单元标识符(从设备地址1) |
7 | 0x10 | 功能码(写多个寄存器) |
8-9 | 0x00 0xC8 | 起始地址(200) |
10-11 | 0x00 0x08 | 寄存器数量(8) |
12 | 0x10 | 字节计数(16) |
13-28 | 0x00 0x01, 0x00 0x01, 0x00 0x01, 0x00 0x01, 0x00 0x02, 0x00 0x02, 0x00 0x02, 0x00 0x02 | 寄存器值(前4个为1,后4个为2) |
三、示例代码实现
以下是使用Python和pymodbus
库构建并发送上述Modbus TCP指令的示例代码:
3.1 安装pymodbus
库
首先,确保已安装pymodbus
库:
pip install pymodbus
3.2 实现Modbus TCP客户端
from pymodbus.client.sync import ModbusTcpClient
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.constants import Endian
# 创建Modbus TCP客户端并连接到服务器
client = ModbusTcpClient('192.168.1.100', port=502) # 替换为实际服务器IP和端口
connection = client.connect()
if connection:
print("连接成功")
# 构建寄存器值:前4个寄存器为1,后4个寄存器为2
builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big)
for _ in range(4):
builder.add_16bit_uint(1)
for _ in range(4):
builder.add_16bit_uint(2)
payload = builder.to_registers()
# 执行写多个寄存器操作
starting_address = 200 # 起始地址
register_values = payload # 寄存器值列表
result = client.write_registers(address=starting_address, values=register_values, unit=1)
if not result.isError():
print("写入成功")
else:
print("写入失败:", result)
# 关闭连接
client.close()
else:
print("连接失败")
代码解析:
- 连接服务器:使用
ModbusTcpClient
连接到目标Modbus TCP服务器。 - 构建寄存器值:使用
BinaryPayloadBuilder
按照大端字节序(Endian.Big)依次添加寄存器值。 - 写入寄存器:调用
write_registers
方法,指定起始地址、寄存器值列表和从设备地址(1)。 - 处理响应:检查写入操作是否成功。
- 关闭连接。
3.3 构建手动指令
如果需要手动构建上述Modbus TCP指令,可以参考以下Python代码:
def build_modbus_tcp_write_multiple_registers(transaction_id, unit_id, start_address, register_values):
protocol_id = 0x0000
function_code = 0x10
quantity = len(register_values)
byte_count = quantity * 2
# MBAP头
mbap = [
(transaction_id >> 8) & 0xFF,
transaction_id & 0xFF,
(protocol_id >> 8) & 0xFF,
protocol_id & 0xFF,
((6 + byte_count) >> 8) & 0xFF, # Length high byte
(6 + byte_count) & 0xFF, # Length low byte
unit_id
]
# PDU
pdu = [
function_code,
(start_address >> 8) & 0xFF,
start_address & 0xFF,
(quantity >> 8) & 0xFF,
quantity & 0xFF,
byte_count
]
# 寄存器值
for value in register_values:
pdu.append((value >> 8) & 0xFF)
pdu.append(value & 0xFF)
# 合并MBAP头和PDU
message = mbap + pdu
return message
# 示例参数
transaction_id = 1
unit_id = 1
start_address = 200
register_values = [1, 1, 1, 1, 2, 2, 2, 2]
# 构建指令
instruction = build_modbus_tcp_write_multiple_registers(transaction_id, unit_id, start_address, register_values)
print("Modbus TCP指令:", [hex(byte) for byte in instruction])
输出结果:
Modbus TCP指令: ['0x0', '0x1', '0x0', '0x0', '0x0', '0x17', '0x1', '0x10', '0xc8', '0x0', '0x8', '0x10', '0x0', '0x1', '0x0', '0x1', '0x0', '0x1', '0x0', '0x1', '0x0', '0x2', '0x0', '0x2', '0x0', '0x2', '0x0', '0x2']
这与前述手动构建的指令一致。
四、总结
通过上述步骤,我们成功构建了一个Modbus TCP指令,用于向从设备地址为1的从站,从地址200开始,连续写入8个寄存器,其中前4个寄存器写入值1,后4个寄存器写入值2。确保每个字段的正确性,特别是MBAP头中的长度字段,是实现成功通信的关键。
在实际应用中,推荐使用现有的Modbus库(如pymodbus
)来简化指令的构建和发送过程,减少手动错误。同时,使用网络抓包工具(如Wireshark)可以帮助调试和验证Modbus TCP通信的正确性。
原文地址:https://blog.csdn.net/weixin_37647148/article/details/144402777
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!