Modbus 速查与实战笔记(功能码、帧结构、坑点)

文章目录

  • [Modbus 速查与实战笔记(功能码、帧结构、坑点与最佳实践)](#Modbus 速查与实战笔记(功能码、帧结构、坑点与最佳实践))
    • [1. Modbus 是啥(一句话版)](#1. Modbus 是啥(一句话版))
    • [2. 数据模型:四类"地址空间"](#2. 数据模型:四类“地址空间”)
    • [3. 传输形态与帧结构](#3. 传输形态与帧结构)
      • [3.1 Modbus RTU(串口)](#3.1 Modbus RTU(串口))
      • [3.2 Modbus TCP(以太网)](#3.2 Modbus TCP(以太网))
    • [4. 必背功能码(现场 90% 用这些)](#4. 必背功能码(现场 90% 用这些))
    • [5. 地址与数据编码的坑](#5. 地址与数据编码的坑)
    • [6. 最小闭环:如何"正确把数读出来"](#6. 最小闭环:如何“正确把数读出来”)
      • [6.1 串口(RTU)最小步骤](#6.1 串口(RTU)最小步骤)
      • [6.2 以太网(TCP)最小步骤](#6.2 以太网(TCP)最小步骤)
    • [7. 异常响应(错误码)速记](#7. 异常响应(错误码)速记)
    • [8. 小示例(思路级伪代码)](#8. 小示例(思路级伪代码))
      • [8.1 读保持寄存器(TCP)](#8.1 读保持寄存器(TCP))
      • [8.2 写单个寄存器(RTU)](#8.2 写单个寄存器(RTU))
    • [9. 现场调试清单(拎着就走)](#9. 现场调试清单(拎着就走))
    • [10. 常见 FAQ](#10. 常见 FAQ)
    • [11. 你可能用得上的补充知识点](#11. 你可能用得上的补充知识点)
    • [12. 一页速查卡(Cheat Sheet)](#12. 一页速查卡(Cheat Sheet))

Modbus 速查与实战笔记(功能码、帧结构、坑点与最佳实践)

这篇当做一份能落地的备忘录:概念够用、步骤清晰、功能码一页记住,顺手补上常见坑和调试要点。少花时间踩雷,多花时间把数读对。


1. Modbus 是啥(一句话版)

工业现场最常见的主从式(Client/Server)通信协议之一。串口时代用 RTU/ASCII (走 RS-485/RS-232),以太网时代用 Modbus TCP(端口 502)。简单、稳定、跨厂商通用,但无认证、无遮挡------生产网请收口隔离。


2. 数据模型:四类"地址空间"

设备内部数据被抽象成 4 类寄存器/位,读写行为受功能码约束:

  • Coils(线圈):开关量输出,布尔,可读写
  • Discrete Inputs(离散输入):开关量输入,布尔,只读
  • Holding Registers(保持寄存器):16 位寄存器,可读写(常用来存参数/输出)
  • Input Registers(输入寄存器):16 位寄存器,只读(常用来读测量值)

传统文档里会看到 0xxxx/1xxxx/3xxxx/4xxxx 的"人类友好地址",协议帧里没有这些前缀 ,只有零基地址 。是否偏移 +1 ,各家实现不一------最容易踩坑,下文有对策。


3. 传输形态与帧结构

3.1 Modbus RTU(串口)

  • 物理层:常见 RS-485 半双工,多点总线

  • 帧格式(请求示例,读保持寄存器 0x03)

    复制代码
    [SlaveID][Func][StartAddrHi][StartAddrLo][QtyHi][QtyLo][CRCLo][CRCHi]

    响应:

    复制代码
    [SlaveID][Func][ByteCount][Data(2*N bytes)][CRCLo][CRCHi]
  • CRC16:初值 0xFFFF,多项式 0xA001(低字节在前)

  • 定时 :帧间至少 3.5 字符时间 静默;字符间不应超过 1.5 字符时间,否则被视为断帧

3.2 Modbus TCP(以太网)

  • 端口 502,不带 CRC,在 TCP 里靠 MBAP 头

  • MBAP Header

    复制代码
    [TransactionID(2)][ProtocolID=0(2)][Length(2)][UnitID(1)]

    随后是 PDU[Func][Data...]

  • UnitID:穿透网关时用来指明下游 RTU 的从站地址;直连纯 TCP 设备时通常固定为设备定义的值(常见 1)

术语对齐:
PDU (Protocol Data Unit)= 功能码 + 数据;
ADU(Application Data Unit)= 传输介质相关的完整帧(RTU=地址+PDU+CRC,TCP=MBAP+PDU)。


4. 必背功能码(现场 90% 用这些)

功能码 名称 读写 典型用途
01 (0x01) Read Coils 开关量输出状态
02 (0x02) Read Discrete Inputs 开关量输入状态
03 (0x03) Read Holding Registers 读参数、模拟量、运算结果
04 (0x04) Read Input Registers 读传感器测量值
05 (0x05) Write Single Coil 置位/复位一个线圈
06 (0x06) Write Single Register 写入一个保持寄存器
0F (0x0F) Write Multiple Coils 批量写线圈
10 (0x10) Write Multiple Registers 批量写保持寄存器
17 (0x17) Read/Write Multiple Registers 读写 一次性读写寄存器(少见但高效)

其他常见但非必背:
08 诊断、11 报告设备 ID、14/15 文件记录、16 掩码写寄存器、18 读 FIFO、2B/0E (设备识别,Modbus TCP 常见)。
广播地址 0(仅 RTU/ASCII):无响应,只能用于部分写操作。


5. 地址与数据编码的坑

  1. 偏移问题(0/1 基)

    • 设备手册写"40001"的点,协议里通常发 0x0000
    • 有的厂商把"寄存器号 40001"直接当 1 用。
    • 对策:先读一个已知值的寄存器,连着试 addr 和 addr-1,一眼就能确认。
  2. 字节序 & 字序

    • 单个寄存器 16 位:**大端字节序(高字节在前)**是 Modbus 约定。
    • 32 位/64 位:跨两个/多个寄存器时,不同厂商可能字序交换(word swap),甚至"字节+字都交换"。
    • 对策:拿一个易识别常量(如 1.0f、1000 或时间戳)对照,快速判别组合方式。
  3. 布尔打包

    • 01/02 返回的位是从 LSB 开始依序装在字节里;第 0 位对应请求的起始地址。

6. 最小闭环:如何"正确把数读出来"

6.1 串口(RTU)最小步骤

  1. 物理层:两线 RS-485,末端 120Ω 终端电阻 ,总线两端加,偏置电阻/Fail-safe建议到位。
  2. 接口参数:波特率/数据位/校验/停止位要与设备一致(常见 9600/19200,8E1 或 8N1)
  3. 从站地址:1--247,确定唯一
  4. 先用 功能码 03 读一个已知寄存器,确认地址偏移与字节/字序
  5. 写操作先在仿真/非产线环境验证,避免误动作

6.2 以太网(TCP)最小步骤

  1. 设备 IP、端口 502 可达;生产网请VLAN/ACL隔离
  2. 若通过网关转 RTU,UnitID 必须为下游 RTU 的从站地址
  3. 仍旧用 03 做握手验证,再扩展到批量读写

7. 异常响应(错误码)速记

当设备返回的功能码最高位被置 1(如请求 0x03,响应 0x83),随后的一个字节是异常码:

  • 01:非法功能(该设备不支持这个功能码)
  • 02:非法数据地址(寄存器不存在/不可达)
  • 03:非法数据值(长度、范围不合法)
  • 04:从站设备故障(内部错误)
  • 05:已接收请求,处理需时间(少见)
  • 06:从站忙
  • 08:存储奇偶错误
  • 0A/0B:网关路径不可达 / 目标设备无响应(TCP-RTU 网关场景)

读到这些,先检查功能码是否对、地址是否对、长度是否越界、权限是否允许


8. 小示例(思路级伪代码)

8.1 读保持寄存器(TCP)

text 复制代码
目标:读设备 10.0.0.5 上保持寄存器起始 0(40001)起的 2 个寄存器,UnitID=1

请求PDU: [0x03][0x00 0x00][0x00 0x02]
MBAP: TxID任意; ProtID=0; Length = PDU长度 + UnitID(1)
完整: MBAP + [UnitID=0x01] + PDU
响应: [0x03][0x04][Data0Hi Data0Lo Data1Hi Data1Lo]
把两个寄存器按设备手册组合成 32 位(注意字序)

8.2 写单个寄存器(RTU)

复制代码
[SlaveID][0x06][AddrHi][AddrLo][DataHi][DataLo][CRCLo][CRCHi]
响应会回显同样内容,CRC 校验一致

9. 现场调试清单(拎着就走)

  • 物理层:A/B 极性 各家标法不一(有厂商 A=--,B=+),不通就对调 再测;总线只在两端加终端电阻
  • 串口参数:波特率/校验必须匹配;RTU 帧间隔别被驱动层无意拉大
  • 地址:先 03 读一个已知值 ;不通就试addr 与 addr-1
  • 数据:确认字节序+字序;浮点/整型转换别混
  • 网关:TCP 的 UnitID 与下游从站地址一致
  • 安全:端口 502 不外曝;分区分域,必要时加网关白名单/隧道
  • 抓包:以太网可用抓包器看 MBAP/PDU;串口用 USB-485 + 串口监视工具

10. 常见 FAQ

  • 能广播写吗? RTU/ASCII 可用从站地址 0 做无应答写(仅部分写类功能支持),TCP 没有广播。
  • 一次最多读多少? 标准上寄存器读常见上限 125(字),线圈 2000(位);很多设备更保守。
  • 为什么读 32 位总是错位? 你和设备对"高字在前/低字在前"的理解不一致。先读一组已知值或文档示例校对字序。
  • 能否混合长短帧? RTU 要求一个帧内连续发送,字符间隔不要超过 1.5 字符时间。

11. 你可能用得上的补充知识点

  • ASCII 模式 :以 : 开头、结尾 \r\n、校验 LRC,人眼可读但效率低,现代现场罕用
  • 文件记录/设备识别:0x14/0x15/0x2B-0x0E 能读设备序列号、版本等,做资产盘点挺香
  • 时间同步:无内建时钟同步,通常通过写寄存器实现(厂商自定义)
  • 冗余:协议本身不管冗余,靠上层逻辑或网络结构实现

12. 一页速查卡(Cheat Sheet)

  • 必用功能码:01/02/03/04/05/06/0F/10(+ 17 进阶)
  • 地址 :文档 40001 ⇄ 帧里 0x0000(小心 +1 偏移
  • 字节序 :寄存器大端;跨寄存器字序不定,实测为准
  • RTU 定时:帧间 ≥ 3.5 char;CRC16 初值 0xFFFF,多项式 0xA001
  • TCP :端口 502;MBAP 有 TransactionID/Length/UnitID;无 CRC
  • 异常码:01/02/03/04 最常见
  • 安全不暴露公网,网关/ACL 掐死
相关推荐
easy20203 小时前
从机器学习的角度实现 excel 中趋势线:揭秘梯度下降过程
笔记·机器学习·线性回归
Hóng xīng qiáo4 小时前
swVBA自学笔记014、Lisp适合对SolidWorks进行二次开发吗 ?
开发语言·笔记·lisp
Magnetic_h4 小时前
【iOS】block复习
笔记·macos·ios·objective-c·cocoa
带娃的IT创业者5 小时前
《AI大模型应知应会100篇》第68篇:移动应用中的大模型功能开发 —— 用 React Native 打造你的语音笔记摘要 App
人工智能·笔记·react native
wan5555cn12 小时前
多张图片生成视频模型技术深度解析
人工智能·笔记·深度学习·算法·音视频
雁于飞13 小时前
vscode中使用git、githup的基操
笔记·git·vscode·学习·elasticsearch·gitee·github
rannn_11114 小时前
【Javaweb学习|实训总结|Week1】html基础,CSS(选择器、常用样式、盒子模型、弹性盒布局、CSS定位、动画),js(基本类型、运算符典例)
css·笔记·学习·html
Ro Jace14 小时前
心灵笔记:第一性原理学习与实践
笔记
aramae15 小时前
C++ -- 模板
开发语言·c++·笔记·其他