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 掐死
相关推荐
滕州市燕猫虎计算机科技工作室个体工商户1 小时前
《Rust程序设计》学习笔记八:结构体
笔记·学习·rust·rust程序设计
志尊宝2 小时前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览
前端·javascript·vue.js·笔记·#javascript·#vue.js
后季暖3 小时前
电商问数笔记(2)
笔记
xier_ran4 小时前
【infra之路】AI 编译器学习笔记(二):重拾 C++——移动语义与 LLVM 风格的类型转换
人工智能·笔记·学习
星恒随风6 小时前
Linux库的底层原理:ELF文件格式、静态链接、程序加载、虚拟地址空间与GOT/PLT详解
linux·运维·笔记·学习·状态模式
罗西的思考6 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 — (7)— 混合机制
笔记·学习
ClinicTech7 小时前
婴儿培养箱技术笔记:温控、报警与数据记录的三层架构
笔记
xiaominngtongxue7 小时前
从一次接触网实训课看中职实训教学的组织逻辑
笔记
xier_ran8 小时前
【infra之路】AI 编译器学习笔记(四):PatternRewriter 与贪心 driver
人工智能·笔记·学习
ACP广源盛139246256738 小时前
硬件选型笔记|国产 PCIe4.0 交换芯片 IX8012@ACP,边缘 AI 设备 IO 扩展方案探讨
人工智能·笔记·硬件架构·pcie·国产芯片