自学内容网 自学内容网

构建Modbus TCP写多个寄存器指令详解

构建Modbus TCP写多个寄存器指令详解

在Modbus TCP通信中,构建正确的指令对于实现设备间的数据交换至关重要。本文将详细解释如何构建一个Modbus TCP指令,用于向设备地址为1的从站,从地址200(0xC8)开始,连续写入8个寄存器,其中前4个寄存器写入值1,后4个寄存器写入值2。

一、Modbus TCP帧结构

Modbus TCP帧由两部分组成:

  1. MBAP头(Modbus Application Protocol Header):7个字节
  2. 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 确定各字段值

  1. 事务标识符(Transaction Identifier):任意选择一个唯一值,例如0x0001
  2. 协议标识符(Protocol Identifier):固定为0x0000
  3. 长度字段(Length Field)
    • PDU部分包括:单元标识符(1) + 功能码(1) + 起始地址(2) + 寄存器数量(2) + 字节计数(1) + 寄存器值(16) = 23字节
    • 因此,长度字段为0x0017(23)
  4. 单元标识符(Unit Identifier):1(目标从设备地址)
  5. 功能码(Function Code):0x10(写多个寄存器)
  6. 起始地址(Starting Address):0x00C8(200)
  7. 寄存器数量(Quantity of Registers):0x0008(8)
  8. 字节计数(Byte Count):0x10(16)
  9. 寄存器值(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-10x00 0x01事务标识符(1)
2-30x00 0x00协议标识符(0)
4-50x00 0x17长度字段(23)
60x01单元标识符(从设备地址1)
70x10功能码(写多个寄存器)
8-90x00 0xC8起始地址(200)
10-110x00 0x08寄存器数量(8)
120x10字节计数(16)
13-280x00 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("连接失败")

代码解析:

  1. 连接服务器:使用ModbusTcpClient连接到目标Modbus TCP服务器。
  2. 构建寄存器值:使用BinaryPayloadBuilder按照大端字节序(Endian.Big)依次添加寄存器值。
  3. 写入寄存器:调用write_registers方法,指定起始地址、寄存器值列表和从设备地址(1)。
  4. 处理响应:检查写入操作是否成功。
  5. 关闭连接

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)!