Modbus 协议

N_OSI模型&TCP&协议&封包

Modbus 是一种通信协议,用于在工业自动化领域中的设备之间进行数据交换。它是一种简单而广泛使用的串行通信协议,用于将控制设备(如传感器、执行器、PLC等)与监控设备(如计算机、远程终端等)连接起来。

Modbus RTU、ASCII、TCP 的区别

Modbus的协议版本 包括Modbus RTU、Modbus ASCII、Modbus TCP/IP、Modbus UDP/IP等

  • Modbus RTU与Modbus ASCII,都使用串口通讯协议,Modbus RTU使用二进制格式进行数据传输,通讯效率更高,Modbus ASCII使用ASCII码进行数据传输,可读性好,但通讯效率更低。
  • Modbus TCP/IP是基于以太网的一种通讯方式,它将Modbus协议封装在TCP/IP协议栈中,通过以太网传输数据。具有高速、稳定的特点。
  • Modbus UDP/IP是基于UDP/IP协议的一种通讯方式

Modbus RTU使用二进制编码进行通信,而Modbus ASCII则使用可打印的ASCII字符。Modbus RTU是更常用的版本,因为它在数据传输效率方面更高。

Modbus协议采用主从结构,其中一个设备充当主站(主机),负责发起通信请求和控制操作,而其他设备则充当从站(从机),接收主站的请求并提供数据。只能主站发起请求,从站不能,发起请求

Modbus 结构

1. 数据传输格式

协议类型数据编码帧结构示例
RTU二进制紧凑的二进制数据,直接传输十六进制字节(如 0x01)。[01][03][00][01][00][01][D5][CA]
ASCIIASCII字符数据转换为可读的ASCII字符(如 "0" → 0x30),每字节拆分为两个ASCII字符。:010300010001D5CA<CR><LF>
TCP二进制(基于TCP)​在TCP/IP协议栈上传输,添加MBAP头(Modbus Application Protocol header)。000100000006010300010001

2. 帧结构与分隔符

协议类型帧起始符帧结束符校验方式字节间隔要求
RTUCRC(2字节)严格时间间隔(3.5字符)
ASCII:(冒号)CR+LF(回车换行)LRC(纵向冗余校验)无严格间隔要求
TCPMBAP头通过TCP包长度标识无额外校验(依赖TCP/IP校验)无间隔要求

3. 传输效率

协议类型效率
RTU:二进制编码,数据紧凑,适合低速串行链路(如RS-485)。
ASCII:每个字节需转换为2个ASCII字符(如0xA1"A""1"),传输数据量翻倍。
TCP:基于TCP/IP,支持高速网络,但需额外添加MBAP头(7字节)。

4. 校验方式

协议类型校验机制校验范围
RTUCRC-16​(循环冗余校验)整个数据帧(地址+功能码+数据)
ASCIILRC​(纵向冗余校验,1字节)数据字段(不包含起始/结束符)
TCP依赖TCP/IP校验​(无额外Modbus层校验)TCP/IP协议栈自动校验
  • RTU / CRC-16-IBM CRC-16的算法有多种变种,Modbus使用的是CRC-16-IBM 以 0x01,0x03,0x00,0x00,0x00,0x08,0x44,0x0C的 0x3 请求为例 其中0x01,0x03,0x00,0x00,0x00,0x08 的CRC-16 (Modbus) 实际计算工具检验码是(0x440C按大端序输出​​:高字节 0x0C → 0x44
byte[] data = {0x01,0x03,0x00,0x00,0x00,0x08};

crc-calculation - https://www.lammertbies.nl/comm/info/crc-calculation


5. 物理接口

协议类型传输介质典型速率应用场景
RTURS-485/RS-2321.2kbps - 115.2kbps工业现场设备(PLC、传感器)
ASCIIRS-485/RS-232低于RTU(因效率低)调试场景(数据可读性强)
TCP以太网(TCP/IP)10Mbps - 1Gbps工厂局域网、SCADA系统远程通信

数据帧格式

无论哪一种Modbus协议版本的帧格式都是一样的

数据帧部分描述占用字节
设备地址(Slave ID)识别从站的唯一地址1字节
功能码(Function Code)主机对从机实现的操作,功能码1字节
数据区(Data Field)包含功能码所需的数据或返回的数据可变
错误校验(CRC)循环冗余校验,用于错误检测2字节

主站发出的功能码 01 ~ 06 的请求时, 数据一定的8个字节(数据区使用1个字节表示开始地址, 1个字节表示长度)

数据/地址类型

Modbus中定义的四种数据类型

  1. 离散输出(Discrete Outputs):
    • 这些寄存器也称为线圈(Coils),它们代表二进制输出(0 或 1),通常用于控制开关设备。
    • 地址范围通常是 0x00001 到 0xFFFFF(Modbus TCP)或 0x0000 到 0xFFFF(Modbus RTU/ASCII)。
    • 功能码 01(读取线圈状态)和 05(写入单个线圈)用于离散输出。
  2. 离散输入(Discrete Inputs):
    • 这些寄存器代表二进制输入状态,它们是只读的,通常用于表示传感器或开关的状态。
    • 地址范围通常是 0x10001 到 0x1FFFF(Modbus TCP)或 0x0001 到 0xFFFF(Modbus RTU/ASCII)。
    • 功能码 02(读取离散输入状态)用于离散输入。
  3. 保持寄存器(Holding Registers):
    • 这些寄存器用于存储可读写的数值数据,通常用于表示过程变量,如温度或压力。
    • 地址范围通常是 0x40001 到 0x4FFFF(Modbus TCP)或 0x0000 到 0xFFFF(Modbus RTU/ASCII)。
    • 功能码 03(读取保持寄存器)和 06(写入单个保持寄存器)用于保持寄存器。
  4. 输入寄存器(Input Registers):
    • 这些寄存器用于存储只读数值数据,通常用于表示模拟量输入,如电流或电压。
    • 地址范围通常是 0x30001 到 0x3FFFF(Modbus TCP)或 0x0000 到 0xFFFF(Modbus RTU/ASCII)。
    • 功能码 04(读取输入寄存器)用于输入寄存器。

功能码

​功能码(十六进制)​​名称​​操作类型​​访问权限​​PLC 地址范围​​数据类型​
​0x01​读取线圈状态(Read Coils)位操作00001-09999(0x地址)二进制位(ON/OFF)
​0x02​读取离散输入状态(Read Discrete Inputs)位操作10001-19999(1x地址)二进制位(ON/OFF)
​0x03​读取保持寄存器(Read Holding Registers)字操作40001-49999(4x地址)16位整数/浮点数
​0x04​读取输入寄存器(Read Input Registers)字操作30001-39999(3x地址)16位整数/浮点数
​0x05​写单个线圈(Write Single Coil)位操作00001-09999(0x地址)二进制位(ON/OFF)
​0x06​写单个保持寄存器(Write Single Register)字操作40001-49999(4x地址)16位整数/浮点数
​0x0F​写多个线圈(Write Multiple Coils)位操作00001-09999(0x地址)二进制位(ON/OFF)
​0x10​写多个保持寄存器(Write Multiple Registers)字操作40001-49999(4x地址)16位整数/浮点数
​0x07​读取异常状态(Read Exception Status)位操作由设备定义(内部线圈)二进制位(ON/OFF)
​0x08​回送诊断校验(Diagnostics)诊断操作读/写无特定地址诊断数据

Modbus功能码占用一个字节,取值范围是1127(即0x010x7F)。同时,使用功能码+0x80表示异常状态,即129~255代表异常码。 在Modbus标准协议中,一共规定了三类Modbus功能码。

  1. 公共功能码 。被明确定义的功能码; 。保证唯一性; 。由Modbus协会确认,并提供公开的文档: 。可进行一致性测试: 。包括协议定义的功能码和保留将来使用的功能码。

  2. 用户自定义功能码 。有两个用户自定义功能码区域,分别是6572和100110; 。用户自定义,不保证唯一性。

  3. 保留功能码 。保留功能码是因为历史遗留原因,某些公司的传统产品上现行使用的功能码不作为公共使用。

实际最常用的是公共功能码中的4个功能码:03/04/06/10

实例

主站发送

主站向从站发送的实际请求数据帧:03 04 00 08 00 01 B0 3B (假设从站地址为03) 其中: 03:为主站要访问的域名(即从站地址,范围0~247)。 04:表示功能码。 00 08:表示从从站寄存器08这个地址开始读取数据。 00 01:表示从站寄存器, 读取数据的长度。(这里即读取一个字节) b0 3b:两个字节的校验数据。(Modbus CRC)

从站响应

从站接收到主站的请求数据帧之后实际的响应数据帧为:03 04 02 00 0A 40 F7 其中: 03:为从站地址即域名(即从站地址,范围0~247)。(主站发送什么就响应什么) 04:表示功能码。(主站发送什么就响应什么) 02:被读取数据长度(所以最多 255 - 4 字节? 253字节) 00 0A:被读取的具体数据 40 F7:两个字节的校验数据

协议限制

  1. Modbus协议报文(两个帧的)间隔需要大于3.5个字符计算:

    1.1、有检验位 1个字符=1(起始位)+8(数据位)+1(奇偶校验位)+1(停竖位)=11位3.5个字符=3.511=38.5位 如果波特率=9600bps,则3.5个字符间隔时间为 38.5/9.6=4.0104167ms : 字节间间隔时间=1.5字符间隔时间 ≈2.6042ms 1.2 无校验位 1个字符=1(起始位)+8(数据位)+0(无校验位)+1(停止位)=10位 3.5个字符=3.5*10=35位

    如果波特率=9600bps,则3.5个字符间隔时间为35/9.6=3.6458毫秒

  2. 通常可以将传输 45位的时间四舍五入后做为报文时间间隔。 如果波特率=9600bps,则45位传输时间为45/9.6=4.6875≈5毫秒