> 技术文档 > Modbus TCP报文协议(ModbusTCP)(单元标识符、分站id、单元id、unitId、从站id)

Modbus TCP报文协议(ModbusTCP)(单元标识符、分站id、单元id、unitId、从站id)


Modbus TCP报文协议详解

概述

Modbus TCP是一种基于TCP/IP协议的工业通信协议,广泛应用于PLC、DCS和SCADA系统中。它继承了Modbus协议简单、可靠的特点,同时利用了以太网的高速和灵活性。

Modbus TCP报文结构

MBAP报头

Modbus TCP报文由MBAP(Modbus Application Protocol)报头和PDU(Protocol Data Unit,协议数据单元)组成。MBAP报头长度为7个字节,包含以下字段:

- 事务标识符(Transaction Identifier,2字节):用于请求和响应的配对。
- 协议标识符(Protocol Identifier,2字节):固定为0,表示Modbus协议。
- 长度(Length,2字节):后续数据的长度,包括单元标识符和PDU。
- 单元标识符(Unit Identifier,1字节):用于多从站的标识,在TCP/IP中通常为0。(注意,如果有多个从站,这个值必须为各个从站指定的地址)

协议数据单元(PDU)

PDU由功能码和数据字段组成:

- 功能码(Function Code,1字节):指定要执行的操作,例如读写寄存器。
- 数据字段(Data,N字节):包含与功能码相关的参数或数据。

常用功能码

- 0x01:读线圈状态

- 0x02:读离散输入状态

- 0x03:读保持寄存器

- 0x04:读输入寄存器

- 0x05:写单个线圈

- 0x06:写单个保持寄存器

- 0x0F:写多个线圈

- 0x10:写多个保持寄存器

报文示例

读保持寄存器请求报文

假设需要从地址为0x0000的寄存器开始读取10个保持寄存器,构建的请求报文如下:

  • MBAP报头

    • 事务标识符:0x0001
    • 协议标识符:0x0000
    • 长度:0x0006(后续6个字节)
    • 单元标识符:0x01
  • PDU

    • 功能码:0x03
    • 起始地址:0x0000
    • 数量:0x000A

完整报文(16进制表示):

00 01 00 00 00 06 01 03 00 00 00 0A
00 0100 0000 06010300 0000 0A事务标识符协议标识符长度单元标识符功能码起始地址寄存器数量

响应报文

假设从站返回的数据为20个字节,对应10个保持寄存器的值:

  • MBAP报头

    • 事务标识符:0x0001
    • 协议标识符:0x0000
    • 长度:0x0015(后续21个字节)
    • 单元标识符:0x01
  • PDU

    • 功能码:0x03
    • 字节数:0x14(20个字节)
    • 数据:20个字节的寄存器值

完整报文(16进制表示):

00 01 00 00 00 15 01 03 14 [20字节数据]
00 0100 0000 15010314[20字节数据]事务标识符协议标识符长度单元标识符功能码字节计数数据

Python示例代码

使用pymodbus库实现Modbus TCP通信的示例代码:

from pymodbus.client.sync import ModbusTcpClient# 创建Modbus TCP客户端client = ModbusTcpClient(\'192.168.1.100\', port=502)# 连接到服务器client.connect()# 读取保持寄存器,地址从0开始,读取10个寄存器result = client.read_holding_registers(address=0, count=10, unit=1)# 检查是否成功读取if not result.isError(): # 输出读取的寄存器值 print(result.registers)else: print(\"读取失败\")# 写单个保持寄存器,地址为0,值为123client.write_register(address=0, value=123, unit=1)# 关闭连接client.close()

注意事项

  • 端口号:Modbus TCP默认使用502端口,需要确保防火墙或路由器未阻挡此端口。
  • 单元标识符:在TCP/IP网络中,单元标识符通常设置为0或1,但在一些网关或路由器中可能有特殊含义。
  • 异常码处理:从站可能返回异常码,需要在程序中进行处理,确保通信的可靠性。
  • 线程安全:在多线程环境中使用Modbus客户端时,需要注意线程安全,可能需要加锁或使用线程安全的客户端实例。

应用场景

  • 工业自动化:用于PLC和上位机之间的数据交换。
  • 能源管理:在电力、石油等行业,实现对设备的远程监控和控制。
  • 楼宇自动化:对暖通空调、照明等系统进行集中控制。

结论

深入理解Modbus TCP报文协议,有助于在工业应用中实现高效可靠的通信。通过掌握报文结构、功能码和异常处理,可以开发出稳定的通信程序,满足各种工业现场的需求。

关于从站单元标识符(unitId)

Modbus TCP协议中的“单元标识符”(Unit Identifier,1字节)允许在一个IP地址下配置多个从站设备,但这并不是Modbus TCP的常规用法,而是协议设计中保留的一个特性。以下是详细解释:


1. 单元标识符的作用

- 协议设计背景

Modbus TCP最初是为以太网通信设计的,继承了Modbus RTU/ASCII的主从架构。在串行通信(如RS485)中,每个从站通过唯一的从站地址(0-255)被标识。而在以太网中,设备通过IP地址唯一标识,因此理论上不需要额外的地址字段。
但为了兼容性和灵活性,Modbus TCP保留了“单元标识符”(即从站地址的替代),作为MBAP报文头的一部分(见知识库[2]、[7]、[12])。

- 实际用途
  • 虚拟从站:如果多个从站逻辑上共享一个IP地址(例如通过网关或虚拟化设备),可以通过不同的单元标识符区分它们。
  • 多协议支持:某些设备可能同时支持Modbus TCP和其他协议(如Profinet),单元标识符可用于路由到不同的协议处理模块。
  • 历史兼容:在混合网络(如以太网+串口桥接)中,单元标识符可能对应串口从站地址。

2. 为什么“一个IP下多个从站”不常见?

尽管协议支持,但实际应用中很少使用单元标识符来区分同一IP下的多个从站,原因如下:

1. IP地址的唯一性

在以太网中,每个设备通常分配一个唯一的IP地址,这已经足够标识通信目标。使用单元标识符会增加复杂性,且容易引发配置错误(例如主站发送的单元标识符与从站配置不匹配)。

2. 设备实现限制

大多数Modbus TCP从站设备(如PLC、传感器)仅支持通过IP地址进行通信,不支持通过单元标识符区分多个从站。因此,即使协议允许,硬件或软件可能不支持该功能。

3. 网络管理复杂性

在大型工业网络中,为每个从站分配独立IP地址更易于管理和故障排查。而通过单元标识符管理同一IP下的多个从站,会增加网络配置和调试的难度。


3. 实际场景中的替代方案

如果需要实现“一个IP下多个从站”的功能,通常采用以下方法:

1. 网关/桥接设备

使用支持Modbus TCP的网关(如知识库[5]、[8]提到的网关设备),将多个从站(如Modbus RTU设备)连接到同一个IP地址下,并通过网关的配置分配不同的单元标识符。

  • 例如:网关作为Modbus TCP从站(IP地址为192.168.1.100),内部连接两个Modbus RTU设备,分别配置单元标识符为1和2。主站通过访问192.168.1.100:502,并指定单元标识符1或2来区分设备。
2. 虚拟化技术

在软件层面(如虚拟机或容器)中运行多个Modbus TCP从站服务,共享同一个IP地址,但通过不同的端口或单元标识符隔离逻辑从站。

3. 分布式控制系统

如知识库[6]所述,通过多路复用技术(如贝加莱控制器)在同一个以太网接口上同时与多个从站通信,但每个从站仍需独立的IP地址或通过其他机制区分。


4. 如何验证是否支持“单元标识符”功能?

- 检查设备文档

确认从站设备是否支持通过单元标识符区分多个逻辑从站。例如,某些网关或工业计算机可能提供此功能。

- 抓包分析

使用Wireshark等工具捕获Modbus TCP通信数据包,观察MBAP报文头中的“单元标识符”字段是否被设置为非零值(通常默认为0)。

- 配置测试

如果设备支持该功能,尝试在主站请求中修改单元标识符(例如从0改为1),观察从站是否响应。


总结

- 理论可行性:Modbus TCP协议允许通过“单元标识符”在一个IP地址下区分多个从站。
- 实际限制:大多数设备不支持此功能,且实际网络中更倾向于为每个从站分配独立IP地址。
- 推荐方案:如需多从站共享IP,建议使用网关或虚拟化设备,并确保所有通信方(主站和从站)都支持单元标识符的配置。