目录通讯方式对比Modbus协议概述Modbus RTU详解Modbus TCP详解RTU vs TCP对比CRC16校验原理实战示例串口通讯 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 (N1字节) │ ├──────────────┬───────────┼──────────────────────────────┤ │ 事务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 0x0000Length (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)什么是CRCCRC (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