工业通讯协议(三)- Modbus

一. 概念

Modbus是一种应用层协议,主要用于工业环境中,允许不同设备之间的通信,例如传感器、控制器、仪表等。它是最早的现场总线之一,由Modicon公司(现为施耐德电气的一部分)在1979年为其可编程逻辑控制器(PLC)开发。

Modbus协议基于简单的请求/响应模型,并且可以运行在不同类型的物理层上,如RS-232、RS-485和TCP/IP网络。它是开放式的,无需支付版权费用,因而被广泛采用,成为工业通信领域的一个事实标准。

Modbus协议的主要特点包括:

  1. 简单性:Modbus协议结构简单,易于理解和实现,使其适用于各种设备和系统。

  2. 灵活性:它支持多种通信方式,包括串行通信(如Modbus RTU和Modbus ASCII)和以太网通信(如Modbus TCP/IP)。

  3. 可互操作性:由于是开放标准,许多设备制造商支持Modbus,使得不同厂家的设备可以通过Modbus进行互联。

  4. 主从结构:Modbus网络中包含一个或多个主设备(或称为客户端)和多个从设备(或称为服务器)。主设备发起请求,从设备回应这些请求。

  5. 功能码:Modbus定义了一系列功能码,用于指定要执行的操作,如读取和写入寄存器或线圈。

  6. 数据模型:Modbus定义了四种基本的数据模型 —— 线圈(用于表示离散输出)、离散输入、输入寄存器和保持寄存器。这些用于存储和传递信息。

Modbus的两种常见变体:

  1. Modbus RTU(Remote Terminal Unit):在串行通信中,数据使用二进制编码,适用于高速通信。

  2. Modbus ASCII:在串行通信中,数据使用ASCII字符表示,适用于调试和诊断,因为人们可以更容易阅读。

  3. Modbus TCP/IP:是Modbus在TCP/IP网络上的实现,它允许Modbus通信在以太网网络上进行。

如何工作:

  • 在串行版本(RTU或ASCII)中:数据通过串行线路传输,每个数据包包含设备地址、功能码、数据和校验和。

  • 在TCP/IP版本中:Modbus消息封装在TCP/IP包中,使其能够通过以太网传输。

Modbus中的专业名词

ADU Application Data Unit
IETF Internet Engineering Task Force
MAC Medium Access Control
MB MODBUS
MBAP MODBUS Application Protocol
PDU Protocol Data Unit
BSD Berkeley Software Distribution
MSL Maximum Segment Lifetime

由于其稳定性和简单性,Modbus在自动化和控制领域内仍然是一个重要且活跃的协议,尽管存在更现代和复杂的通信协议。

二. 通讯原理

Modbus的工作原理基于一种简单的主从通信模型,主要包括主设备(或客户端)和从设备(或服务器)。以下是Modbus的基本工作原理:

  1. 主从结构

    • 主设备(或客户端)负责发起通信请求。
    • 从设备(或服务器)响应主设备的请求。
  2. 通信方式

    • Modbus可以在串行通信和以太网通信两种环境下工作。
    • 在串行通信中,常见的有Modbus RTU和Modbus ASCII两种格式。
    • 在以太网通信中,使用Modbus TCP/IP协议。
  3. 请求/响应模式

    • 主设备向从设备发送请求,请求中包含要执行的操作和相关参数。
    • 从设备接收请求并执行相应的操作,然后将结果返回给主设备。
  4. 功能码

    • Modbus定义了一系列功能码,用于指定要执行的操作类型,如读取寄存器、写入寄存器等。
    • 功能码确定了请求和响应消息的类型和格式。
  5. 寄存器

    • Modbus通信涉及读取和写入数据到寄存器中。
    • 寄存器可以是线圈(用于表示离散输出)、离散输入、输入寄存器和保持寄存器。
  6. 地址

    • 每个从设备都有一个唯一的地址,用于识别和定位设备。
    • 主设备通过从设备的地址来确定发送请求的目标设备。
  7. 错误处理

    • Modbus协议中包含了错误检测和纠正机制,以确保通信的可靠性。
    • 如果发生通信错误,协议规定了一套错误码来指示错误类型。

image

在实际应用中,主设备可以是一个计算机、PLC(可编程逻辑控制器)、人机界面(HMI)等,而从设备可以是传感器、执行器、仪表等各种工业设备。通过Modbus协议,这些设备可以方便地进行数据交换和控制操作,实现自动化系统的集成和管理。

PDU和ADU

在Modbus通信中,PDU(Protocol Data Unit,协议数据单元)和ADU(Application Data Unit,应用数据单元)是两个重要的概念。

  1. PDU(Protocol Data Unit,协议数据单元)

    • PDU是Modbus协议中用于传输数据的基本单元。
    • 对于Modbus RTU和Modbus ASCII格式的串行通信,PDU包含了功能码、数据以及错误检验等信息。
    • 对于Modbus TCP/IP格式的以太网通信,PDU被封装在TCP/IP包中。

    image

  2. ADU(Application Data Unit,应用数据单元)

    • ADU是指在Modbus通信中,传输PDU的完整单元,即PDU加上地址和错误检验等附加信息的整个结构。
    • 对于串行通信,ADU由一组字节组成,包括起始符、地址、PDU、错误检验和结束符(如果是Modbus ASCII格式)。
    • 对于TCP/IP通信,ADU是TCP/IP包,其中包含Modbus PDU。

    image

ModbusRTU和ModbusTCP

ModbusRTU

Modbus RTU(Remote Terminal Unit)是Modbus协议的一种常用的串行通信格式。下面详细介绍Modbus RTU的格式:

1. 帧结构:

一个Modbus RTU帧由多个字节组成,通常包括以下部分:

  • 起始符(1 字节):

    • 一个连续的逻辑 0 信号,表示一个数据帧的开始。称为帧的起始标志。
  • 地址(1 字节):

    • 表示从设备的地址,范围为1到247。
    • 0 为广播地址,用于向所有从设备发送消息。
  • 功能码(1 字节):

    • 用于指定主设备发送的请求类型,如读取寄存器、写入寄存器等。
    • 功能码的范围是1到255,但并非所有功能码都被实现。
  • 数据(N 字节):

    • 包含主设备发送给从设备的数据,或者从设备发送给主设备的响应数据。
    • 数据的长度可以根据具体请求或响应的操作类型而变化。
  • CRC 校验(2 字节):

    • 循环冗余校验,用于检测数据传输过程中是否发生错误。
    • CRC 校验通常使用 CRC-16 标准算法计算得出。
  • 停止符(1 字节):

    • 一个逻辑 1 信号,表示一个数据帧的结束。称为帧的停止标志。
2. 数据长度:
  • 每个Modbus RTU帧的长度可以根据数据内容的不同而变化。
  • 在通常情况下,一个完整的Modbus RTU帧至少包含3.5个字节(起始符、地址、功能码、数据的一部分、CRC 校验的一部分)。
3. 数据传输:
  • Modbus RTU采用二进制形式传输数据。
  • 数据传输的速率(波特率)通常在 1200 到 115200 bps 之间,具体取决于通信设备的配置和需求。
4. 示例:

下面是一个简化的Modbus RTU请求帧的示例:

起始符   地址   功能码   数据   CRC 校验   停止符
0        1      3        0     XX XX     1

在此示例中:

  • 起始符为逻辑0信号。
  • 地址为从设备地址,此处为1。
  • 功能码为读取保持寄存器(Read Holding Registers),此处为3。
  • 数据字段包含请求的详细信息,此处为要读取的寄存器地址和数量。
  • CRC 校验字段包含计算得出的循环冗余校验值。
  • 停止符为逻辑1信号,表示帧的结束。

这样,Modbus RTU格式的数据帧就完成了一次请求。响应帧的结构与请求帧类似,但包含的数据会根据具体的响应内容而变化。

ModbusTCP

Modbus TCP是基于TCP/IP协议的Modbus变体,用于在以太网上进行通信。下面是Modbus TCP的详细格式:

1. 帧结构:

Modbus TCP帧由TCP/IP头部和Modbus PDU(Protocol Data Unit)组成,其中Modbus PDU包含了Modbus协议中定义的数据。以下是Modbus TCP帧的结构:

  • TCP/IP头部

    • 包含了源端口、目标端口等TCP/IP协议头部信息。
    • TCP端口号:Modbus TCP通信的默认端口号为502。
  • Modbus PDU

    • 包含Modbus应用数据单元(ADU)中的Modbus PDU部分。
    • Modbus PDU与Modbus RTU和Modbus ASCII格式中的PDU相似,包含了地址、功能码、数据等字段。
2. Modbus PDU结构:

Modbus PDU中的具体字段取决于Modbus请求或响应的类型(功能码)。以下是Modbus PDU的一般结构:

  • 功能码(1 字节):

    • 用于指定主设备发送的请求类型,如读取寄存器、写入寄存器等。
  • 数据(N 字节):

    • 包含主设备发送给从设备的数据,或者从设备发送给主设备的响应数据。
    • 数据的长度和内容取决于具体的请求或响应操作类型。
3. 示例:

下面是一个简化的Modbus TCP请求帧的示例:

TCP/IP头部   Modbus PDU
源端口、目标端口  功能码   数据
502           3       0     XX XX XX XX

在此示例中:

  • TCP/IP头部包含了源端口和目标端口等TCP/IP协议相关信息,其中源端口通常为客户端随机分配的端口号,目标端口为Modbus TCP的默认端口502。
  • Modbus PDU包含了Modbus请求的具体信息,其中包括了功能码和请求的数据内容。

这样,Modbus TCP格式的数据帧就完成了一次请求。响应帧的结构与请求帧类似,但包含的数据会根据具体的响应内容而变化。需要注意的是,Modbus TCP使用TCP连接进行通信,因此在TCP连接上建立和维护连接是必要的。

报文头MBAP

image
image

报文内容

modbus的操作对象有四种:线圈、离散输入、输入寄存器、保持寄存器。

Modbus报文中的操作对象和功能码用于指定要执行的操作类型和操作对象,以便正确地处理请求和响应。下面是Modbus报文中常用的操作对象和功能码:

操作对象:

  1. 线圈(Coil)

    • 用于表示离散输出。
    • 线圈是一个位(bit)。
    • 操作对象地址通常用于指定线圈的起始位置。
  2. 离散输入(Discrete Input)

    • 用于表示离散输入。
    • 离散输入也是一个位(bit)。
    • 操作对象地址通常用于指定离散输入的起始位置。
  3. 输入寄存器(Input Register)

    • 用于存储只读数据,如传感器数据。
    • 输入寄存器通常用于存储16位的数据。
    • 操作对象地址通常用于指定输入寄存器的起始位置。
  4. 保持寄存器(Holding Register)

    • 用于存储读写数据,如控制器设置值。
    • 保持寄存器通常用于存储16位的数据。
    • 操作对象地址通常用于指定保持寄存器的起始位置。

功能码:

  1. 读取线圈状态(Read Coils)

    • 功能码:1。
    • 用于从设备读取线圈(Coil)的状态。
  2. 读取离散输入状态(Read Discrete Inputs)

    • 功能码:2。
    • 用于从设备读取离散输入(Discrete Input)的状态。
  3. 读取保持寄存器(Read Holding Registers)

    • 功能码:3。
    • 用于从设备读取保持寄存器(Holding Register)的值。
  4. 读取输入寄存器(Read Input Registers)

    • 功能码:4。
    • 用于从设备读取输入寄存器(Input Register)的值。
  5. 写单个线圈(Write Single Coil)

    • 功能码:5。
    • 用于向设备写入单个线圈(Coil)的状态。
  6. 写单个保持寄存器(Write Single Register)

    • 功能码:6。
    • 用于向设备写入单个保持寄存器(Holding Register)的值。
  7. 写多个线圈(Write Multiple Coils)

    • 功能码:15。
    • 用于向设备写入多个线圈(Coil)的状态。
  8. 写多个保持寄存器(Write Multiple Registers)

    • 功能码:16。
    • 用于向设备写入多个保持寄存器(Holding Register)的值。

这些操作对象和功能码涵盖了Modbus通信中常见的操作类型,可以通过它们来实现对设备的读取和写入操作。

PDU详细结构

0x01:读线圈

在从站中读1~2000个连续线圈状态,ON=1,OFF=0

请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)()
响应:MBAP 功能码 数据长度 数据(一个地址的数据为1位)
如:在从站0x01中,读取开始地址为0x0002的线圈数据,读0x0008位
00 01 00 00 00 06 01 01 00 02 00 08
回:数据长度为0x01个字节,数据为0x01,第一个线圈为ON,其余为OFF
00 01 00 00 00 04 01 01 01 01

0x05:写单个线圈

将从站中的一个输出写成ON或OFF,0xFF00请求输出为ON,0x000请求输出为OFF

请求:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)
响应:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)
如:将地址为0x0003的线圈设为ON
00 01 00 00 00 06 01 05 00 03 FF 00
回:写入成功
00 01 00 00 00 06 01 05 00 03 FF 00

0x0F:写多个线圈

将一个从站中的一个线圈序列的每个线圈都强制为ON或OFF,数据域中置1的位请求相应输出位ON,置0的位请求响应输出为OFF

请求:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L 字节长度 输出值H 输出值L
响应:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L

0x02:读离散量输入

从一个从站中读1~2000个连续的离散量输入状态

请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)
响应:MBAP 功能码 数据长度 数据(长度:9+ceil(数量/8))
如:从地址0x0000开始读0x0012个离散量输入
00 01 00 00 00 06 01 02 00 00 00 12
回:数据长度为0x03个字节,数据为0x01 04 00,表示第一个离散量输入和第11个离散量输入为ON,其余为OFF
00 01 00 00 00 06 01 02 03 01 04 00

0x04:读输入寄存器

从一个远程设备中读1~2000个连续输入寄存器

请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)
如:读起始地址为0x0002,数量为0x0005的寄存器数据
00 01 00 00 00 06 01 04 00 02 00 05
回:数据长度为0x0A,第一个寄存器的数据为0x0c,其余为0x00
00 01 00 00 00 0D 01 04 0A 00 0C 00 00 00 00 00 00 00 00

0x03:读保持寄存器

从远程设备中读保持寄存器连续块的内容

请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)
如:起始地址是0x0000,寄存器数量是 0x0003
00 01 00 00 00 06 01 03 00 00 00 03
回:数据长度为0x06,第一个寄存器的数据为0x21,其余为0x00
00 01 00 00 00 09 01 03 06 00 21 00 00 00 00

0x06:写单个保持寄存器

在一个远程设备中写一个保持寄存器

请求:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
响应:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
如:向地址是0x0000的寄存器写入数据0x000A
00 01 00 00 00 06 01 06 00 00 00 0A
回:写入成功
00 01 00 00 00 06 01 06 00 00 00 0A

0x10:写多个保持寄存器

在一个远程设备中写连续寄存器块(1~123个寄存器)

请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L 字节长度 寄存器值(13+寄存器数量×2)
响应:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
如:向起始地址为0x0000,数量为0x0001的寄存器写入数据,数据长度为0x02,数据为0x000F
00 01 00 00 00 09 01 10 00 00 00 01 02 00 0F
回:写入成功
00 01 00 00 00 06 01 10 00 00 00 01

posted @ 2024-05-14 17:22  Asp1rant  阅读(16)  评论(0编辑  收藏  举报