Modbus RTU/TCP 协议详解与Spring Boot集成指南

目录

Modbus协议基础概念

什么是Modbus

主要变种

基本数据模型

Modbus RTU详解

协议特点与原理

基本特性

物理层特性

数据传输格式

帧结构详解

完整帧格式

字段详细分析

CRC计算详解

功能码详细解析

基本读操作功能码

基本写操作功能码

批量操作功能码

异常响应机制

异常码定义

异常响应格式

通信时序与状态机

主站状态机

从站状态机

时序要求详解

实际通信示例分析

读保持寄存器完整流程

写多个寄存器示例

数据类型与编码

数据类型映射

字节序处理

线圈数据编码

性能特点与优化

传输效率分析

通信优化策略

错误处理与诊断

常见错误类型

诊断方法

高级特性

多主站支持

扩展功能码

广播操作

Modbus TCP详解

协议特点

帧结构

与RTU的区别

Spring Boot集成Modbus RTU

依赖配置

配置类

服务类实现

控制器示例

Spring Boot集成Modbus TCP

依赖配置

配置类

连接池管理

服务类实现

控制器示例

实际应用案例

数据采集服务

配置文件示例

最佳实践与注意事项

性能优化

错误处理

安全考虑

通用注意事项

调试技巧


Modbus协议基础概念

什么是Modbus

Modbus是一种串行通信协议,由Modicon公司(现为施耐德电气)于1979年发布。它是工业自动化领域中最常用的通信协议之一,具有以下特点:

  • 开放性:免费使用,无需许可证
  • 简单性:易于实现和维护
  • 可靠性:具有错误检测机制
  • 广泛支持:几乎所有PLC和工业设备都支持

主要变种

  • Modbus RTU:基于RS232/RS485串行通信
  • Modbus TCP:基于以太网TCP/IP通信
  • Modbus ASCII:基于ASCII编码的串行通信

基本数据模型

Modbus定义了四种基本数据类型:

数据类型 地址范围 访问权限 说明
线圈 (Coils) 00001-09999 读/写 单比特,输出类型
离散输入 (Discrete Inputs) 10001-19999 只读 单比特,输入类型
输入寄存器 (Input Registers) 30001-39999 只读 16位,输入类型
保持寄存器 (Holding Registers) 40001-49999 读/写 16位,输出类型

Modbus RTU详解

协议特点与原理

基本特性
  • 传输方式:串行通信(RS232/RS485/RS422)
  • 数据格式:二进制(紧凑高效)
  • 主从架构:一个主站(Master),多个从站(Slave)
  • 半双工通信:同一时刻只能单向传输
  • 错误检测:CRC16校验,可靠性高
  • 传输效率:相对ASCII格式效率更高
  • 实时性:适合实时控制应用
物理层特性

RS232特性:

  • 点对点通信,最大距离15米
  • 电压范围:±3V到±25V
  • 传输速率:通常9600-115200 bps
  • 适用于短距离设备连接

RS485特性:

  • 多点通信,支持32个节点
  • 最大距离1200米(低速率)
  • 差分信号传输,抗干扰能力强
  • 电压范围:±1.5V到±6V
  • 适用于工业环境长距离通信
数据传输格式

字符帧格式:

起始位 | 数据位  | 奇偶校验位 | 停止位
  1    | 8 bits |    1     |  1-2

时序要求:

  • 静默间隔:帧间必须有至少3.5个字符时间的静默
  • 字符间隔:同一帧内字符间隔不能超过1.5个字符时间
  • 响应时间:从站收到请求后的响应时间窗口

帧结构详解

完整帧格式
+----------+----------+----------+----------+----------+
| 静默间隔 | 设备地址 | 功能码   | 数据域   | CRC校验  | 静默间隔 |
| >=3.5字符| 1 byte   | 1 byte   | N bytes  | 2 bytes  | >=3.5字符|
+----------+----------+----------+----------+----------+----------+
字段详细分析

1. 设备地址(Device Address)

  • 长度:1字节(8位)
  • 范围:0-255
  • 含义
    • 0:广播地址,所有从站接收但不响应
    • 1-247:有效从站地址
    • 248-255:保留地址
  • 示例
    地址1: 0x01地址16: 0x10广播: 0x00
    

2. 功能码(Function Code)

  • 长度:1字节
  • 分类
    • 01-64:公共功能码
    • 65-72:用户自定义功能码
    • 128+:异常响应(最高位置1)

3. 数据域(Data Field)

  • 长度:0-252字节
  • 内容:根据功能码不同而变化
  • 结构:地址+数量/值

4. CRC校验(Error Check)

  • 算法:CRC-16-ANSI
  • 多项式:0xA001
  • 长度:2字节
  • 字节序:低字节在前,高字节在后
CRC计算详解

CRC-16计算算法:

初始值: 0xFFFF
多项式: 0xA001

步骤:
1. 将CRC寄存器初始化为0xFFFF
2. 对消息中每个字节:
   a. 将字节与CRC寄存器低8位异或
   b. 右移CRC寄存器8次,每次:
      - 如果移出位为1,CRC寄存器与0xA001异或
      - 如果移出位为0,继续移位
3. 最终CRC值:低字节在前,高字节在后

Java实现示例:

public static int calculateCRC16(byte[] data) {
    int crc = 0xFFFF;
    for (byte b : data) {
        crc ^= (b & 0xFF);
        for (int i = 0; i < 8; i++) {
            if ((crc & 0x0001) == 1) {
                crc = (crc >> 1) ^ 0xA001;
            } else {
                crc = crc >> 1;
            }
        }
    }
    return crc;
}

功能码详细解析

基本读操作功能码

功能码01:读线圈状态

  • 请求格式
    [地址][01][起始地址2字节][线圈数量2字节][CRC2字节]
    
  • 响应格式
    [地址][01][字节数1字节][线圈状态N字节][CRC2字节]
    
  • 示例:读取地址1设备的线圈0-15
    请求: 01 01 00 00 00 10 3D CC响应: 01 01 02 CD 6B B2 0E
    

功能码03:读保持寄存器

  • 请求格式
    [地址][03][起始地址2字节][寄存器数量2字节][CRC2字节]
    
  • 响应格式
    [地址][03][字节数1字节][寄存器值N*2字节][CRC2字节]
    
  • 示例:读取地址1设备的寄存器40001-40003
    请求: 01 03 00 00 00 03 05 CB响应: 01 03 06 00 0A 00 0B 00 0C 7F 3F
    
基本写操作功能码

功能码05:写单个线圈

  • 请求格式
    [地址][05][线圈地址2字节][线圈值2字节][CRC2字节]
    
  • 线圈值:0xFF00(ON)或0x0000(OFF)
  • 响应:回显请求帧

功能码06:写单个寄存器

  • 请求格式
    [地址][06][寄存器地址2字节][寄存器值2字节][CRC2字节]
    
  • 响应:回显请求帧
批量操作功能码

功能码15(0x0F):写多个线圈

  • 请求格式
    [地址][0F][起始地址2字节][线圈数量2字节][字节数1字节][线圈值N字节][CRC2字节]
    
  • 线圈值编码:8个线圈打包到1个字节,LSB在前

功能码16(0x10):写多个寄存器

  • 请求格式
    [地址][10][起始地址2字节][寄存器数量2字节][字节数1字节][寄存器值N*2字节][CRC2字节]
    

异常响应机制

异常码定义
异常码 名称 说明
01 ILLEGAL_FUNCTION 不支持的功能码
02 ILLEGAL_DATA_ADDRESS 无效的数据地址
03 ILLEGAL_DATA_VALUE 无效的数据值
04 SLAVE_DEVICE_FAILURE 从站设备故障
05 ACKNOWLEDGE 确认(需要长时间处理)
06 SLAVE_DEVICE_BUSY 从站设备忙
08 MEMORY_PARITY_ERROR 内存奇偶校验错误
10 GATEWAY_PATH_UNAVAILABLE 网关路径不可用
11 GATEWAY_TARGET_DEVICE_FAILED 网关目标设备无响应
异常响应格式
[地址][功能码+0x80][异常码1字节][CRC2字节]

通信时序与状态机

主站状态机
空闲 → 发送请求 → 等待响应 → 接收响应 → 处理响应 → 空闲
     ↓                ↓
   错误处理 ← ← ← ← ← 超时/异常
从站状态机
监听 → 接收完整帧 → 地址匹配 → CRC校验 → 处理请求 → 发送响应 → 监听
     ↓           ↓         ↓       ↓
   忽略 ← ← ← ← 不匹配/错误 ← ← ← ← ← ← ← ← ← ← ← ← ←
时序要求详解

字符间超时(Inter-character Timeout):

  • 定义:同一帧内连续字符间的最大间隔
  • 时间:1.5个字符时间
  • 计算:T1.5 = 1.5 × 11 / 波特率(秒)
  • 示例:9600bps时,T1.5 = 1.708ms

帧间间隔(Inter-frame Interval):

  • 定义:不同帧之间的最小静默时间
  • 时间:3.5个字符时间
  • 计算:T3.5 = 3.5 × 11 / 波特率(秒)
  • 示例:9600bps时,T3.5 = 3.986ms

实际通信示例分析

读保持寄存器完整流程

场景:读取从站地址1的保持寄存器40001-40002(地址0-1)

1. 主站发送请求:

原始数据: 01 03 00 00 00 02
CRC计算: C4 0B
完整帧: 01 03 00 00 00 02 C4 0B

字节分析:
01     - 从站地址1
03     - 功能码:读保持寄存器
00 00  - 起始地址:0(对应40001)
00 02  - 寄存器数量:2个
C4 0B  - CRC校验值

2. 从站响应:

假设寄存器值:40001=0x1234, 40002=0x5678
响应数据: 01 03 04 12 34 56 78
CRC计算: [计算得出]
完整帧: 01 03 04 12 34 56 78 [CRC]

字节分析:
01     - 从站地址1
0

你可能感兴趣的:(Modbus,网络)