首页/新闻资讯/正文详情

Modbus功能码与报文解析:PDU/ADU、异常响应与位字打包

发布时间:2026/11/4 17:54:13 来源:云帆数科 栏目:资讯中心
Modbus功能码与报文解析:PDU/ADU、异常响应与位字打包
简介《Modbus通讯功能码及实例.pdf》面向工业自动化、嵌入式开发、PLC编程及现场调试人员围绕Modbus通用工业通信协议整理常用功能码、报文结构与典型实例帮助读者理解主从设备之间线圈、输入状态、保持寄存器、输入寄存器的读写过程以及异常诊断思路。压缩包内仅含1个PDF文件大小约10KB内容篇幅精炼便于打印携带和随查随用文档以功能码01至06为主线同时覆盖15、16、17等批量操作与从机标识并配以设备地址、命令号、起始地址、寄存器数量、数据字节及CRC校验等字段说明还原请求帧与响应帧的组成。已有2332人学习适合作为协议速查手册、通信调试入门参考和报文分析辅助材料可帮助读者对照实例梳理读写流程、排查通信异常并加深对功能码用途的理解。1. 功能码不是命令表一条 8 字节报文如何决定工业现场的一次读写很多人第一次看 Modbus会把功能码当成一张命令表01 读线圈、03 读寄存器背下来就行。真正上现场会发现功能码只是 PDU 的第一个字节决定一次读写能否成立的还有地址基准、数量上限、字节计数和异常应答。Modbus 把“请求什么数据”和“数据怎么编进帧”分开定义串口 RTU 与以太网 TCP 只是外面的 ADU 不同里面的 PDU 语义一致。这份资料里列出的 01 到 06 六个高频码正好覆盖数字量与模拟量的读写把这六个码的请求和响应拆开就能理解功能码表背后的数据模型。先给结论读懂功能码不是背名称而是能根据请求数据域反推响应长度并根据异常码判断失败发生在哪一层。2. PDU 与 ADU功能码在报文里的位置为什么先定地址再定语义2.1 从串口帧到 PDU地址域、功能码域、数据域、CRC 的分层Modbus RTU 的一帧由三部分组成从站地址、PDU、CRC。PDU 又是“功能码 数据域”功能码占一个字节数据域长度由功能码和请求参数决定。从站地址放在 PDU 外面这不是随意排的一条 485 总线上可以挂多个设备主站必须先声明“我在跟谁说话”从站才会去解释后面的功能码。地址 0 是广播1 到 247 是从站地址248 到 255 保留。TCP 那边把地址和 CRC 换成了 MBAP 头PDU 原样保留所以功能码的语义跨传输层不变。资源里的例子[11][01][00][13][00][25][CRC低][CRC高]可以按字段拆开看0x11是 17 号从站0x01是读线圈0x0013是起始地址 190x0025是读 37 个开关量。这里有两个容易看漏的点起始地址在 PDU 里从 0 开始算不是从 1 开始多字节数值按高字节在前编码所以00 13拼出来是 19而不是 0x1300。CRC 两个字节则是低字节在前和前面数据域的高字节在前相反后面单独讲。字段长度资源例子含义从站地址1 字节0x1117 号从站功能码1 字节0x01读线圈状态起始地址2 字节0x00130-based 地址 19读取数量2 字节0x002537 个线圈CRC2 字节低字节在前从地址到数据域末字节设备响应[11][01][05][CD][6B][B2][0E][1B][CRC低][CRC高]里0x05是返回的字节个数后面 5 个字节是位图。37 个线圈需要 5 个字节因为 5×840 位最后 3 位没有实际意义按约定补 0。这个“字节个数”字段很关键RTU 没有总长度字段响应变长时主站要靠它知道后面该取多少字节。功能码 03 的响应也是同样思路只是字节个数等于寄存器数量乘 2。2.2 01/03 的请求与响应长度为什么能对上字节计数与寄存器数功能码 01 和 03 的请求都是定长 8 字节地址 1 字节、功能码 1 字节、起始地址 2 字节、数量 2 字节、CRC 2 字节。响应则变长靠第二个字节后面的“字节个数”把长度撑开。01 的字节个数是ceil(线圈数量 / 8)03 的字节个数是寄存器数量 × 2。主站解析时先读字节个数再按这个数取数据最后两个字节才是 CRC。这个设计让功能码本身不需要携带“响应有多长”长度信息被放进了数据域。用代码构造一个 03 请求能把地址和数量的编码看得很清楚import struct def build_read_holding(slave, start, qty): # 功能码 03起始地址和寄存器数量都按 16 位大端编码 pdu struct.pack(BHH, 0x03, start, qty) return pdu pdu build_read_holding(0x11, 0x006B, 0x0003) print(pdu.hex( )) # 03 00 6b 00 03BHH里的表示大端B是功能码两个H分别是起始地址和数量。slave没有进 PDU它要加在 PDU 前面CRC 也要在整帧拼好后追加。这个函数只负责 PDU方便在 TCP 和 RTU 两种 ADU 里复用。起始地址 0x006B 是 107数量 3对应资源里“从 107 号寄存器开始读 3 个模拟量”的例子。响应解析要先把异常响应拦下来def parse_read_holding_response(frame): slave, func, byte_count frame[0], frame[1], frame[2] if func 0x80: raise RuntimeError(f异常响应异常码0x{frame[2]:02X}) values [] for i in range(0, byte_count, 2): values.append(int.from_bytes(frame[3 i:5 i], big)) return slave, values frame bytes.fromhex(11 03 06 02 2B 00 00 00 64) print(parse_read_holding_response(frame)) # (17, [555, 0, 100])这段代码假设frame已经去掉了 CRC只保留地址、功能码、字节个数和数据。func 0x80用来判断最高位如果为 1说明从站返回的是异常响应此时frame[2]不是字节个数而是异常码。正常响应里byte_count6循环每次取两个字节按大端拼成 16 位整数得到 0x022B555、0x00000、0x0064100和资源例子一致。真实串口帧末尾还有两个 CRC 字节解析数据时不能把它们算进byte_count。2.3 异常响应功能码最高位置 1 之后错误码说明了什么异常响应的格式是[从站地址][功能码 | 0x80][异常码][CRC低][CRC高]。功能码最高位置 1表示“这个功能码的请求失败了”后面的异常码才说明原因。比如请求 03 读保持寄存器从站返回0x83主站就知道这是 03 的异常如果返回0x03那还是正常功能码不能混。功能码正常范围是 1 到 127异常标记用 0x80 不会和正常功能码冲突资源里把 128 到 255 保留给异常应答也是同一个空间划分思路。异常码含义常见触发场景0x01非法功能从站不支持该功能码0x02非法数据地址起始地址或寄存器范围越界0x03非法数据值数量超过上限、写线圈值不是 FF00/00000x04从站设备故障从站内部执行失败0x05确认从站已接受但需要长时间处理0x06从站设备忙从站正在执行长任务0x08存储奇偶校验错误从站存储校验失败0x0A网关路径不可用网关找不到目标设备0x0B网关目标设备无响应网关转发后目标从站未回异常码 02 和 03 最容易在联调时遇到。02 多半是地址基准错了比如手册写 40001报文里发了 0x000103 常见于数量超限比如 03 一次读 200 个寄存器超过 125 的上限。异常码 06 可以退避重试02 重试没有意义先把地址和数量改对。异常响应只有 5 个字节比正常响应短主站如果按正常响应的字节个数去等就会一直等到超时所以解析入口先看功能码最高位是比较稳妥的顺序。3. 位与字的分界01/02/05/15 为什么按位打包03/04/06/16 为什么按字拆高字节3.1 线圈与离散输入LSB 先行、末字节高位补零的打包规则功能码 01 读线圈、02 读离散输入数据域都是位图。一个字节装 8 个开关量字节的最低位对应该字节里地址最小的线圈也就是 LSB 先行。资源例子返回CD 6B B2 0E 1B第一个字节 0xCD 展开成二进制是1100 1101从低位往高位读bit01、bit10、bit21、bit31、bit40、bit50、bit61、bit71。对应起始地址 19 开始的 8 个线圈就是 19 号闭合、20 号断开、21 号闭合、22 号闭合、23 号断开、24 号断开、25 号闭合、26 号闭合。原文例子里说的 20 号到 27 号是 1-based 编号和 PDU 的 0-based 地址差 1。解析位图时不能按“高位先”去读否则开关顺序会整个反掉def unpack_bits(data, qty): bits [] for byte in data: for i in range(8): bits.append((byte i) 1) return bits[:qty] data bytes.fromhex(CD 6B B2 0E 1B) print(unpack_bits(data, 37)[:8]) # [1, 0, 1, 1, 0, 0, 1, 1]data是响应里的位图字节qty是请求里要读的线圈数量。每个字节从 bit0 到 bit7 依次追加最后按qty截断。37 个线圈会得到 40 位最后 3 位是补零的高位不能当成真实开关状态。02 的打包规则和 01 完全一样只是数据来源是只读的离散输入从站不会因为 02 改变输入状态。写多线圈 15 的请求数据也按同样规则打包所以 15 和 01 的位图可以共用一套打包函数本文还有配套的精品资源点击获取

相关推荐

使用CMake构建RTSP推流服务器的实践指南
使用CMake构建RTSP推流服务器的实践指南

1. 项目背景与核心价值 RTSP(Real Time Streaming Protocol)作为实时流媒体传输的行业标准协议,在视频监控、在线教育、视频会议等领域有着广泛应用。而CMake作为现代C/C项目的构建工具,能够有效管理跨平台编译的复杂性。将二者结… · 2026/11/4 17:54:13

Modbus功能码与RTU报文调试速查:01-06实例及避坑
Modbus功能码与RTU报文调试速查:01-06实例及避坑

简介:这是一份面向工业自动化初学者、电气工程师与嵌入式开发者的 Modbus 通讯入门资料,聚焦协议功能码含义与实际报文构造,帮助读者解决「看不懂功能码、不会拼报文、调试串口通讯无从下手」等问题,适合作为 RS-485 与以太网通讯… · 2026/11/4 17:54:13

数字病理与细胞图像分析技术解析与应用
数字病理与细胞图像分析技术解析与应用

1. 数字病理与细胞图像分析技术概述在医疗诊断和生命科学研究领域,数字病理和细胞图像分析正逐渐成为不可或缺的技术手段。这项技术通过将传统玻璃切片数字化,结合计算机视觉和机器学习算法,实现对病理图像和细胞形态的定量分析。我最初接触这… · 2026/11/4 17:54:13

Codex CLI增强框架superpowers:技能系统与持久记忆让AI编码助手更可靠
Codex CLI增强框架superpowers:技能系统与持久记忆让AI编码助手更可靠

开头先直接聊结论:如果你已经在用 Codex CLI,觉得它能干活但总是差口气,比如上下文记不住、复杂任务做到一半就跑偏、想让它按照团队规范写代码还得反复粘贴规则,那 superpowers 就是冲这个痛点去的。它不是一个新模型&#xff0c… · 2026/11/4 18:41:03

分布式系统时间同步技术:原理、实现与优化
分布式系统时间同步技术:原理、实现与优化

1. 时间同步技术概述在分布式系统和物联网设备开发中,时间同步是一个看似基础却至关重要的技术环节。作为一名长期从事嵌入式开发的工程师,我见过太多因为时间不同步导致的诡异问题:从简单的日志顺序错乱,到严重的分布式事务失败&… · 2026/11/4 18:41:03

CLI-Anything:把高频操作变成一行命令的效率工具
CLI-Anything:把高频操作变成一行命令的效率工具

1. 项目解读:CLI-Anything 到底在解决什么问题CLI-Anything 是我最近整理本地开发环境时沉淀出来的一个项目。名字没什么玄机,就是把那些分散在 GUI 工具、浏览器书签、终端历史记录里的高频操作,全部收编到命令行里,让任何重复性… · 2026/11/4 18:41:03

基于Dify构建自动化复盘工作流:从聊天记录到结构化报告
基于Dify构建自动化复盘工作流:从聊天记录到结构化报告

几个月前做内部工具选型时,我看到了一个叫 "hindsight" 的项目。第一眼以为是普通的复盘模板,把它和 Dify 放在一起跑了一遍之后,我才意识到它真正在做的事:把"事后聪明"这件每个人都会、但总是做不系统的事&… · 2026/11/4 18:41:03

PTA理论考C语言高频考点与易错点自检指南
PTA理论考C语言高频考点与易错点自检指南

简介:这份文档面向准备PTA平台C语言理论考试的学生与自学者,围绕判断题、选择题及参考答案进行整理,可用于考前自测、答案核对与薄弱知识点复盘。压缩包内仅含1个docx文件,大小约345KB,内容集中、查阅方便,… · 2026/11/4 18:41:03

城市交通仿真技术:原理、应用与AnyLogic实战
城市交通仿真技术:原理、应用与AnyLogic实战

1. 仿真技术在城市规划中的核心价值城市规划正面临前所未有的复杂性挑战。作为从业15年的城市仿真顾问,我亲历了从传统经验决策到数据驱动规划的转变过程。仿真技术之所以能成为现代城市规划的"数字沙盘",关键在于它解决了三大痛点&#xff1a… · 2026/11/4 18:40:03

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

AI辅助技术栈评估:提升研发决策效率60%
AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17

从生成Token到直接决策:Jev如何重塑AI Agent工程实践
从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17

32G统一内存跑大模型:内存账、TPS实测与端云分流
32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码