当前位置: 首页 > news >正文

GKMLT通讯工具箱(WPF MVVM) - 02-Modbus RTU 与 TCP 报文格式、原理与CRC校验

目录

  1. 通讯方式对比
  2. Modbus协议概述
  3. Modbus RTU详解
  4. Modbus TCP详解
  5. RTU vs TCP对比
  6. CRC16校验原理
  7. 实战示例

串口通讯 vs 网口通讯

物理层对比

┌─────────────────────┐ ┌─────────────────────┐ │ 串口通讯 (RTU) │ │ 网口通讯 (TCP) │ ├─────────────────────┤ ├─────────────────────┤ │ • RS-232 / RS-485 │ │ • 以太网 / 光纤 │ │ • 点对点 / 总线型 │ │ • 交换机 / 路由器 │ │ • 传输距离: 短 │ │ • 传输距离: 长 │ │ • 速率: 低 │ │ • 速率: 高 │ │ • 抗干扰: 强 │ │ • 抗干扰: 需屏蔽 │ └─────────────────────┘ └─────────────────────┘

应用场景对比

  • 串口: 工业现场设备 → 短距离、实时控制
  • 网口: 远程监控 → 跨网络、数据采集

Modbus 协议基础

主从架构

Master (主站) Slave (从站) ↓ 发送请求 ↓ ↕ 返回响应 ┌─────────────┐ ┌─────────────┐ │ PLC/上位机 │────────→│ 传感器 │ │ │ │ 执行器 │ │ │←────────│ 变频器 │ └─────────────┘ └─────────────┘

核心特点

  • 单向通讯:只能由主站发起
  • 事务模型:一次一个事务
  • 地址空间:线圈、离散输入、寄存器

Modbus 功能码

8种标准功能码

功能码名称数据类型方向
0x01读取线圈Bool[]
0x02读取离散输入Bool[]
0x03读取保持寄存器Byte[]
0x04读取输入寄存器Byte[]
0x05写入单个线圈-
0x06写入单个寄存器-
0x0F写入多个线圈-
0x10写入多个寄存器-

Modbus RTU 报文结构

完整帧结构

┌─────────────────────────────────────────────────┐ │ Modbus RTU 数据帧 │ ├─────────────────────────────────────────────────┤ │ [从站地址][功能码][数据区][CRC16低][CRC16高] │ │ 1字节 1字节 N字节 1字节 1字节 │ └─────────────────────────────────────────────────┘

关键特性

  • ✅ 串行传输(RS-232/485)
  • ✅ 二进制编码
  • ✅ CRC16循环冗余校验
  • ✅ 紧凑的帧结构

Modbus RTU 读取报文示例

读取保持寄存器 (功能码 0x03)

请求报文 (读取10个寄存器)

HEX: 01 03 00 00 00 0A [CRC_L] [CRC_H] ┌─┬─┬────┬────┬───────┐ │ │ │ │ │ │ ↓ ↓ ↓ ↓ ↓ ↓ [01][03][00][00][00][0A][xx][xx] │ │ │ │ │ │ │ │ │ │ │ └─ CRC16校验 │ │ │ │ └──── 数量(10) │ │ └───┴─────── 起始地址(0) │ └─────── 功能码(读保持寄存器) └────────── 从站地址(1)

响应报文 (返回20字节数据)

HEX: 01 03 14 [20字节寄存器数据] [CRC_L] [CRC_H] ┌─┬─┬──┬───────────────────┬───────┐ │ │ │ │ │ │ ↓ ↓ ↓ ↓ ↓ ↓ [01][03][14][D0 D1 D2 D3 ... 0F][xx][xx] │ │ │ └── 实际数据 ──┘ │ │ │ └─── 字节数(20) │ │ └───── 功能码 │ └──────── 从站地址 └─ CRC16校验

Modbus TCP 报文结构

MBAP + Modbus PDU

┌────────────────────────────────────────────────────────────┐ │ Modbus TCP 数据帧 │ ├────────────────────────────────────────────────────────────┤ │ MBAP Header (7字节) │ Modbus PDU (N+1字节) │ ├──────────────┬───────────┼──────────────────────────────┤ │ 事务ID │ 协议ID │[单元ID][功能码][数据区] │ │ 2字节 │ 2字节 │ 1字节 1字节 N字节 │ ├──────────────┴───────────┴──────────────────────────────┤ │ Transaction │ Protocol │ Unit │Function│ Data │ │ ID │ ID │ ID │ Code │ │ └──────────────┴───────────┴────────┴────────┴──────────────┘

MBAP头结构

  • Transaction ID (2字节): 事务标识符,匹配请求/响应
  • Protocol ID (2字节): 协议标识符,Modbus TCP = 0x0000
  • Length (2字节): 后续字节数
  • Unit ID (1字节): 从站地址

Modbus TCP 读取报文示例

读取保持寄存器 (功能码 0x03)

请求报文

HEX: 00 01 00 00 00 06 01 03 00 00 00 0A ┌───┬───┬───────┬───┬───┬────┬───┬────┬────┬────┐ │ │ │ │ │ │ │ │ │ │ │ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ [00][01][00][00][00][06][01][03][00][00][00][0A] │ │ │ │ │ │ │ │ │ └── 数量(10) │ │ │ │ │ │ │ │ └─────── 起始地址(0) │ │ │ │ │ │ │ └────────── 功能码(0x03) │ │ │ │ │ │ └─────────────── 单元ID(从站1) │ │ │ │ │ └──────────────────── 长度(6字节) │ │ │ │ └────────────────────────── 协议ID(0) │ │ │ └─────────────────────────────── 事务ID(1) │ │ └──────────────────────────────────────────── 帧头(7字节) │ └────────────────────────────────────────────────── MBAP头 └───┴──────────────────────────────────────────────────── 完整TCP报文

响应报文

HEX: 00 01 00 00 00 15 01 03 14 [20字节寄存器数据] ┌───┬───┬───────┬───┬────┬───┬──┬──────────────┐ │ │ │ │ │ │ │ │ │ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ [00][01][00][00][00][15][01][03][14][D0 D1 ... 0F] │ │ │ │ │ │ │ └── 字节计数 │ │ │ │ │ │ │ │ └── 实际数据(20字节) │ │ │ │ │ │ │ └──────────────────── 功能码 │ │ │ │ │ └─────────────────────── 单元ID │ │ │ │ └────────────────────────────── 长度(21字节) │ │ │ └─────────────────────────────────── 协议ID │ │ └──────────────────────────────────────────── 事务ID │ └───────────────────────────────────────────────── MBAP头 └───┴────────────────────────────────────────────────── 完整报文

RTU vs TCP 核心区别

报文结构对比图

┌─────────────────────────────────────────────────────────────┐ │ Modbus RTU 报文结构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────┬────┬─────────────┬────────┐ │ │ │从站地址│功能│ 数据区 │CRC16 │ │ │ │ (1B) │码 │ (N Bytes) │(2B) │ │ │ └─────────┴────┴─────────────┴────────┘ │ │ 简单紧凑 │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ Modbus TCP 报文结构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────── MBAP Header ─────────────┬─────────┐ │ │ │TransID│ProtID│Length│UnitID│ 功能码│ 数据区 │ │ │ │ (2B) │(2B) │ (2B) │ (1B) │ (1B) │(N Bytes) │ │ │ ├───────┼──────┼──────┼──────┼──────┼──────────┤ │ │ │事务ID │ 协议 │ 长度 │ 单元 │ 功能 │ 数据 │ │ │ │ │ 标识 │ │ 标识 │ 码 │ │ │ │ └───────┴──────┴──────┴──────┴──────┴──────────┘ │ │ 复杂但标准化 │ └─────────────────────────────────────────────────────────────┘

RTU vs TCP 详细对比

特性Modbus RTUModbus TCP
传输层串口(RS-232/485)TCP/IP
最大长度256字节260字节
地址标识从站地址(1字节)单元标识符(1字节)
寻址范围1-2471-247
校验方式CRC16TCP校验和
帧头开销2字节(从站+功能)7字节(MBAP)
默认端口串口参数502
速度较慢较快
传输距离<1200米无限制(网络)

CRC16 校验原理 (1/4)

什么是CRC?

CRC (Cyclic Redundancy Check)- 循环冗余校验

定义: 根据数据块产生简短固定位数校验码的散列函数 主要用于检测或验证数据传输/存储后可能出现的错误 ┌─────────────────────────────────────────────────┐ │ 原始数据 │ │ ↓ │ │ 生成CRC校验码 │ │ ↓ │ │ 数据 + CRC ──→ 传输/存储 ──→ 接收端验证 │ └─────────────────────────────────────────────────┘

CRC16 特点

  • 校验码: 2字节 (16位)
  • 多项式: x¹⁶ + x¹⁵ + 1 (Modbus)
  • 初始值: 0xFFFF
  • 反转输入/输出: 是

CRC16 校验原理 (2/4)

计算流程图

┌─────────────────────────────────────────────────────┐ │ CRC16 计算流程 │ └─────────────────────────────────────────────────────┘ 初始化: CRC高字节 = 0xFF CRC低字节 = 0xFF 索引指针 = 0 ┌──────────────────────────────────────────┐ │ 开始处理每个字节 │ └──────────────────────────────────────────┘ ↓ ┌──────────────────────────────────────────┐ │ 取下一个字节 │ │ dataByte = buffer[index++] │ └──────────────────────────────────────────┘ ↓ ┌──────────────────────────────────────────┐ │ 计算索引 │ │ index = CRC_H ⊕ dataByte │ │ └── CRC_H = 高字节 │ └──────────────────────────────────────────┘ ↓ ┌──────────────────────────────────────────┐ │ 查表更新CRC │ │ CRC_H = CRC_L ⊕ TABLE[index] │ │ CRC_L = TABLE_H[index] │ └──────────────────────────────────────────� ↓ 还有数据? ──→ 否 ──→ 返回CRC ↓ 是

CRC16 校验原理 (3/4)

查表法计算

查表原理

预计算的查找表 (256字节) ┌─────────────────────────────────────────┐ │ 索引 0x00: CRC_H = 0x00, CRC_L = 0x00 │ │ 索引 0x01: CRC_H = 0xC1, CRC_L = 0xC0 │ │ 索引 0x02: CRC_H = 0x81, CRC_L = 0xC1 │ │ ... │ │ 索引 0xFF: CRC_H = 0x40, CRC_L = 0x81 │ └─────────────────────────────────────────┘ 计算步骤: 1. 取当前CRC高字节与数据字节异或 2. 异或结果作为索引 3. 从查找表取出新的CRC高低字节 4. 重复直到所有数据处理完

示例计算

数据: 0x01, 0x03, 0x00, 0x00, 0x0A 初始: CRC = 0xFFFF 第1字节(0x01): index = 0xFF ⊕ 0x01 = 0xFE CRC_H = 0x40 ⊕ aucCRCLo[0xFE] = ... CRC_L = aucCRCHi[0xFE] = ... ... (重复5次) 最终: CRC = [CRC_L] [CRC_H]

CRC16 校验原理 (4/4)

在Modbus RTU中的应用

报文验证流程

发送端: ┌──────────────┐ │ 数据 │ │ 01 03 00 00 │ │ 00 0A │ └──────┬───────┘ ↓ ┌──────────────┐ │ 计算CRC16 │ │ CRC = ... │ └──────┬───────┘ ↓ ┌──────────────┐ │ 附加CRC │ │ 01 03 00 00 │ │ 00 0A CRC_L │ │ CRC_H │ └──────────────┘ 接收端: ┌──────────────┐ │ 接收数据 │ │ 含CRC │ └──────┬───────┘ ↓ ┌──────────────┐ │ 计算CRC16 │ │ CRC_calc │ └──────┬───────┘ ↓ ┌──────────────┐ │ 比较CRC │ │ CRC_recv == │ │ CRC_calc ? │ └──────┬───────┘ ↓ ✓ 校验通过 ✗ 数据错误

Modbus RTU 写入报文

写入单个寄存器 (0x06)

请求报文

HEX: 01 06 00 00 00 01 [CRC_L] [CRC_H] ┌─┬─┬────┬────┬────┬──────┐ │ │ │ │ │ │ │ ↓ ↓ ↓ ↓ ↓ ↓ ↓ [01][06][00][00][00][01][xx][xx] │ │ │ │ │ └─ CRC16 │ │ │ │ └───── 写入值 (0x0001) │ │ │ └───────── 寄存器地址 (0) │ │ └───────────── 功能码 (写单个寄存器) │ └────────────────── 从站地址 (1)

响应报文 (Echo - 回显)

HEX: 01 06 00 00 00 01 [CRC_L] [CRC_H] └─────────────── 完全相同 ───────┘

特点: 响应报文与请求报文完全相同(回显机制)


Modbus TCP 写入报文

写入多个寄存器 (0x10)

请求报文

HEX: 00 05 00 00 00 0F 01 10 00 00 00 02 04 00 10 20 30 ┌───┬───┬───────┬───┬────┬───┬────┬────┬────┬────┬────┬──── │ │ │ │ │ │ │ │ │ │ │ │ │ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ [00][05][00][00][00][0F][01][10][00][00][00][02][04][00][10][20][30] │ │ │ │ │ │ │ │ │ │ │ │ └─ 数据 │ │ │ │ │ │ │ │ │ │ │ └───── 字节计数(4) │ │ │ │ │ │ │ │ │ │ └─────────── 数量(2) │ │ │ │ │ │ │ │ │ └─────────────── 起始地址(0) │ │ │ │ │ │ │ │ └────────────────────── 功能码(0x10) │ │ │ │ │ │ │ └───────────────────────────── 单元ID(1) │ │ │ │ │ │ └─────────────────────────────────── 长度(15) │ │ │ │ │ └──────────────────────────────────────── 协议ID(0) │ │ │ │ └───────────────────────────────────────────── 事务ID(5) │ │ │ └────────────────────────────────────────────────── MBAP头 │ │ └─────────────────────────────────────────────────────── 数据PDU │ └─────────────────────────────────────────────────────────────── Modbus TCP帧

Modbus TCP 响应报文

写入多个寄存器响应

响应报文

HEX: 00 05 00 00 00 06 01 10 00 00 00 02 ┌───┬───┬───────┬───┬────┬───┬────┬────┬────┐ │ │ │ │ │ │ │ │ │ │ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ [00][05][00][00][00][06][01][10][00][00][00][02] │ │ │ │ │ │ │ │ └───── 数量(2) │ │ │ │ │ │ │ └─────────── 起始地址(0) │ │ │ │ │ │ └─────────────── 功能码 │ │ │ │ │ └─────────────────────── 单元ID │ │ │ │ └────────────────────────────── 长度(6) │ │ │ └─────────────────────────────────── 协议ID │ │ └──────────────────────────────────────────── 事务ID │ └───────────────────────────────────────────────── MBAP头

注意: 响应只包含MBAP头 + 功能码 + 地址 + 数量,不包含写入的数据


Modbus 完整通讯流程

RTU 通讯流程

主站 (Master) 从站 (Slave) │ │ │ ①发送请求报文 │ ├─────────────────────→│ │ [Slave][FC][Data][CRC] │ │ │ │ ②接收响应报文 │ │←─────────────────────┤ │ [Slave][FC][Data][CRC] │ │ │ │ ③CRC验证 │ │ ✓ 通过 → 处理数据 │ │ ✗ 失败 → 重传/报错 │

TCP 通讯流程

客户端 (Client) 服务器 (Server) │ │ │ ①建立TCP连接 │ ├─────────────────────→│ │ Socket(Connect) │ │ │ │ ②发送Modbus请求 │ │ ├─────────────────────→│ │ [MBAP][PDU] │ │ │ │ ③接收Modbus响应 │ │ ←─────────────────────┤ │ [MBAP][PDU] │ │ │ │ ④TCP校验和 │ │ ✓ 通过 → 处理数据 │ │ ✗ 失败 → 重传/报错 │

实际应用场景对比

工业现场设备

┌─────────────────────────────────────────────────────────────┐ │ 工业自动化系统 │ └─────────────────────────────────────────────────────────────┘ ┌──────┐ RS-485总线 ┌──────┐ ┌──────┐ ┌──────┐ │ PLC │◄──────►│ 传感器│◄────►│ 执行器│◄──►│ HMI │ └──────┘ └──────┘ └──────┘ └──────┘ │ ▲ │ ▲ │ │ │ │ Modbus RTU Modbus RTU Modbus RTU Modbus RTU ┌──────┐ 以太网交换机 ┌──────┐ ┌──────────┐ │ 上位机│◄───────────►│ PLC │◄─►│ 远程I/O │ └──────┘ └──────┘ └──────────┘ │ ▲ ▲ │ Modbus TCP Modbus TCP 跨地域监控

性能与可靠性对比

传输性能

指标Modbus RTUModbus TCP
帧开销2字节7字节
吞吐量中等
延迟低(<10ms)中(10-50ms)
并发性单路多路

可靠性

特性Modbus RTUModbus TCP
纠错CRC16TCP校验和+重传
干扰抑制强(RS-485)中(需屏蔽)
距离限制<1200m无限制
故障隔离总线故障影响全部网络节点隔离

如何选择 Modbus RTU 或 TCP?

选择流程图

开始 │ ├─ 设备有串口? │ │ │ ├─ 是 ──→ 距离 < 100米? │ │ │ │ │ ├─ 是 ─→ ✅ Modbus RTU │ │ │ │ │ └─ 否 ─→ ❌ 考虑其他方案 │ │ │ └─ 否 ──→ 设备有网口? │ │ │ ├─ 是 ──→ ✅ Modbus TCP │ │ │ └─ 否 ─→ ❌ 需要转换器 │ └─ 环境要求高可靠性? │ ├─ 是 ──→ 有RS-485? ─→ ✅ Modbus RTU │ └─ 否 ──→ 需远程访问? ─→ ✅ Modbus TCP

常见问题与解决

Q1: CRC校验失败

问题: 返回报文错误

原因: • 波特率/数据位/校验位/停止位配置不匹配 • 从站地址错误 • 通讯线路干扰

解决:

1. 检查串口参数配置 2. 验证从站地址是否正确 3. 检查线路连接和屏蔽 4. 增加超时时间

Q2: TCP连接超时

问题: 无法连接到设备

原因: • IP地址或端口号错误 • 网络不通 • 防火墙阻止

解决:

1. ping设备IP地址 2. 检查端口号(默认502) 3. 关闭防火墙或添加白名单 4. 确认设备支持Modbus TCP

总结

核心要点回顾

Modbus RTU

  • ✅ 串口通讯,紧凑高效
  • ✅ CRC16校验,可靠性强
  • ✅ 适合工业现场短距离
  • ✅ RS-485总线支持多设备

Modbus TCP

  • ✅ 网络通讯,跨地域
  • ✅ MBAP头标准化
  • ✅ 支持并发通讯
  • ✅ 适合远程监控集成

CRC16校验

  • ✅ 16位校验码
  • ✅ 查表法快速计算
  • ✅ 检测数据完整性
  • ✅ 工业标准算法

END

http://www.jsqmd.com/news/722590/

相关文章:

  • 高并发场景下委托内存暴增?C# 13三大优化机制(静态委托缓存、目标弱引用、结构化闭包)全公开(仅限.NET 8.0+)
  • 大数据开发场景下,总结并翻译 Oracle 中常见的错误(补充其他错误码:适合初学者)
  • IG502边缘网关:空压机预测性维护的轻量化方案
  • 如何彻底解决电脑风扇噪音?Fan Control终极指南帮你实现静音与散热的完美平衡
  • 揭秘书匠策AI:论文降重与AIGC防御的“独门秘籍”
  • Figma设计自动化:用rules-figma实现设计规范检查与团队协作提效
  • 2026年正宗新会陈皮排行:3个合规品牌的硬参数对比 - 优质品牌商家
  • 视频数据集安全防护:基于聚类的智能防泄漏方案
  • ARMv9内存管理:PAR_EL1寄存器详解与应用
  • Go 语言从入门到进阶 | 第 22 章:日志与可观测性
  • 收藏必备!小白程序员轻松掌握RAG大模型,让你的AI秒懂公司文档!
  • 仅剩72小时!.NET 9正式版边缘部署黄金窗口期关闭前,必须完成的5项Runtime裁剪与符号剥离操作
  • Unity游戏实时翻译终极指南:XUnity.AutoTranslator深度技术解析
  • Python金融数据获取革命:efinance如何成为量化交易的最佳数据助手
  • 新联合众香港展会圆满落幕,AI融合硬件矩阵获全球瞩目
  • ARM MPAM内存带宽控制机制详解与配置实践
  • 服务器3个设置需配置好!王杨游戏蜘蛛养站系统seo站长要做的!
  • 天辛大师再谈人工智能时代,一人公司真的符合社会学演进规律吗
  • journalctl -xe -u k3s 命令详解
  • 为什么92%的PHP团队低估了PHP 8.9的类型校验强度?——基于Zend Engine v4.9.0源码级行为对比分析
  • TVA在新能源汽车制造与检测中的实践与创新(3)
  • ARM架构Hypervisor调试机制与安全隔离实践
  • .NET 9云原生迁移倒计时:仅剩120天——.NET 6 LTS终止支持前必须完成的5项容器化加固动作
  • 算法终极审判:软件测试从业者的专业视角
  • HiClaw 1.1.0:企业级 Agent 开发的基建升级
  • 2026年广州名贵补品回收门店排行及选购推荐 - 优质品牌商家
  • 前端性能优化:构建工具优化详解
  • 收藏!小白/程序员轻松入门大模型微调:从LoRA到视觉指令微调的进阶指南
  • latex表头左对齐,居中对齐
  • 环境一致性崩塌预警!Dev Containers 生产部署前必须验证的7项黄金检查项(含自动化校验脚本)