
很多刚接触 Modbus 的朋友,第一次看到设备日志里的报文时都会有点懵:
01 03 00 00 00 02 C4 0B
01 03 04 00 E6 01 2C 1B 89
这些数字看起来像一串密码,但它们不是随机内容。Modbus RTU 报文通常由 从机地址、功能码、数据区、CRC 校验 组成。只要先看清这几个部分,再结合设备手册中的寄存器表,就能判断一条报文在问什么、设备又回复了什么。
03 和 04 是设备采集中最常见的两个读取功能码。本文会先拆解 03 / 04 的查询请求和回复报文,再介绍 ThingsCloud 的 属性智能转换:它可以根据设备类型中的 Modbus 寄存器配置,把设备回复的 Modbus 报文自动转换成设备属性值;对于读写类寄存器或 IO,也可以把属性下发转换成对应的 Modbus 写入报文。
一、先记住一条规则:主站问,从站答
Modbus RTU 是典型的主站 / 从站通信。主站负责发起请求,从站收到请求后再回复。接入 ThingsCloud 时,可以先按下面这层关系理解:
- ThingsCloud 任务生成并下发 Modbus 查询报文,DTU / 网关负责把报文透传到 RS485 总线。
- RS485 总线上的传感器、仪表、PLC、温控器等设备作为从站回复数据。
- 设备回复后,DTU / 网关把 Modbus RTU 报文透传回云端,ThingsCloud 再根据配置解析成属性。

所以,当你在日志里看到两行报文时,通常可以先判断:
主站请求:01 03 00 00 00 02 C4 0B
从站回复:01 03 04 00 E6 01 2C 1B 89
第一行是在问:“地址为 01 的设备,请用 03 功能码,从地址 0000 开始,读取 2 个寄存器。”
第二行是在答:“地址为 01 的设备回复了 4 个字节的数据,分别是 00 E6 和 01 2C。”
二、03 和 04 到底有什么区别?
03 和 04 都是“读取寄存器”,它们的请求报文结构几乎一样,区别在于读取的寄存器类型不同。
| 功能码 | 名称 | 常见用途 | 寄存器特性 |
|---|---|---|---|
03 | 读取保持寄存器 | 读取或写入配置值、参数值,也常被一些厂家用于读取传感器数值 | 通常可读可写 |
04 | 读取输入寄存器 | 读取温度、湿度、压力、流量、电压等采集值 | 通常只读 |
在 ThingsCloud 的 Modbus 配置中,这个差异对应到数据寄存器的读写类型:
- 只读 / 输入寄存器:读取功能码是
04,用于采集传感器数值。 - 读写 / 保持寄存器:读取功能码是
03,写入单个保持寄存器时通常使用06,常用于读取或修改配置数值。
但现场设备不一定完全按教科书来。有些厂家的温湿度传感器也用 03 功能码读取采集值。因此,最终以设备厂家提供的 Modbus 寄存器手册为准,不要只凭“传感器就一定用 04”来判断。
三、03 功能码请求报文怎么拆?
先看一条完整的 03 请求报文:
01 03 00 00 00 02 C4 0B

把它拆开:
| 字节 | 含义 | 解释 |
|---|---|---|
01 | 从机地址 | 要访问地址为 1 的设备 |
03 | 功能码 | 读取保持寄存器 |
00 00 | 起始寄存器地址 | 从 0x0000 开始读取 |
00 02 | 寄存器数量 | 读取 2 个寄存器 |
C4 0B | CRC 校验 | 用于校验报文是否传输错误 |
这条请求用一句话翻译就是:
主站请求地址为
01的从站,从保持寄存器地址0x0000开始,读取2个寄存器。
这里有 3 个细节很容易出错。
第一,报文中的起始地址是 16 位地址字段,这里用十六进制展示。设备手册里可能写 0000H、0x0000、40001、寄存器地址 0 等不同形式。尤其要注意,40001 常是保持寄存器的参考编号,不一定等于报文里直接填写的地址值。
第二,读取数量是“寄存器数量”,不是字节数量。1 个 Modbus 寄存器是 2 个字节,所以读取 2 个寄存器,回复数据区里会有 4 个数据字节。
第三,CRC 在 Modbus RTU 报文里通常低字节在前。上面这条请求的 CRC 是 0x0BC4,报文里写成 C4 0B。
四、03 功能码回复报文怎么拆?
对应的回复报文:
01 03 04 00 E6 01 2C 1B 89
拆开来看:
| 字节 | 含义 | 解释 |
|---|---|---|
01 | 从机地址 | 地址为 1 的设备在回复 |
03 | 功能码 | 回复的是 03 读取保持寄存器 |
04 | 字节数 | 后面有 4 个数据字节 |
00 E6 | 第 1 个寄存器值 | 十六进制 0x00E6,十进制是 230 |
01 2C | 第 2 个寄存器值 | 十六进制 0x012C,十进制是 300 |
1B 89 | CRC 校验 | 校验回复报文 |
如果这两个寄存器分别代表温度和湿度,并且设备手册说明需要除以 10,那么:
00 E6=230,实际温度是23.0℃。01 2C=300,实际湿度是30.0%RH。
也就是说,Modbus 报文本身只告诉你“寄存器里的原始值”。这个值代表温度、湿度还是电压,是否要除以 10 或 100,需要看设备手册和平台配置。
五、04 功能码请求报文怎么拆?
04 请求报文和 03 几乎一样,只是功能码变成了 04。
01 04 00 00 00 02 71 CB
拆开:
| 字节 | 含义 | 解释 |
|---|---|---|
01 | 从机地址 | 要访问地址为 1 的设备 |
04 | 功能码 | 读取输入寄存器 |
00 00 | 起始寄存器地址 | 从 0x0000 开始读取 |
00 02 | 寄存器数量 | 读取 2 个寄存器 |
71 CB | CRC 校验 | 用于校验报文是否传输错误 |
翻译成自然语言:
主站请求地址为
01的从站,从输入寄存器地址0x0000开始,读取2个寄存器。
六、04 功能码回复报文怎么拆?
对应的 04 回复报文:
01 04 04 09 C4 13 88 B4 B3
拆开:
| 字节 | 含义 | 解释 |
|---|---|---|
01 | 从机地址 | 地址为 1 的设备在回复 |
04 | 功能码 | 回复的是 04 读取输入寄存器 |
04 | 字节数 | 后面有 4 个数据字节 |
09 C4 | 第 1 个寄存器值 | 十六进制 0x09C4,十进制是 2500 |
13 88 | 第 2 个寄存器值 | 十六进制 0x1388,十进制是 5000 |
B4 B3 | CRC 校验 | 校验回复报文 |
如果设备手册说明第 1 个寄存器是温度,单位需要除以 100;第 2 个寄存器是湿度,单位需要除以 100,那么:
09 C4=2500,实际温度是25.00℃。13 88=5000,实际湿度是50.00%RH。
同样的回复结构,在不同设备上可能代表不同物理含义。读报文不能脱离寄存器手册。
七、为什么回复里有“字节数”,请求里没有?
03 / 04 的请求里已经写明了要读取多少个寄存器,所以请求不需要再写“字节数”。例如 00 02 表示读取 2 个寄存器。
回复里则需要告诉主站“我后面带了多少字节的数据”。因为 1 个寄存器是 2 个字节,所以:
| 读取寄存器数量 | 回复字节数 |
|---|---|
1 个寄存器 | 02 |
2 个寄存器 | 04 |
3 个寄存器 | 06 |
10 个寄存器 | 14,也就是十进制 20 |
所以看到回复报文中的第三个字节,不要把它当成寄存器值。它只是后面数据区的长度。
八、如何从数据字节变成设备属性值?
读懂 03 / 04 报文后,还差最后一步:把寄存器原始值变成有业务意义的属性。
以这条 04 回复为例:
01 04 04 09 C4 13 88 B4 B3
数据区是:
09 C4 13 88
如果按照 2 个 16 位无符号整数解析,就是:
| 寄存器 | 原始值 | 十进制 | 业务属性 | 换算后 |
|---|---|---|---|---|
| 第 1 个寄存器 | 09 C4 | 2500 | 温度 | 25.00℃ |
| 第 2 个寄存器 | 13 88 | 5000 | 湿度 | 50.00%RH |
但有些设备会用 32 位浮点数表示一个值。例如电表的电压可能占用 2 个寄存器,也就是 4 个字节。此时就不能按两个 16 位整数拆,而要按 32 位浮点数解析,还要关注字节序,例如 ABCD、BADC、CDAB、DCBA。
这也是很多新手遇到“读到了数据,但数值不对”的原因:报文能通,不代表数据类型、寄存器长度和字节序一定配对正确。
九、ThingsCloud 如何把 Modbus 报文变成属性?
如果完全手写解析逻辑,你需要自己处理从机地址、功能码、起始地址、寄存器数量、数据类型、字节序、倍率换算和 CRC。对单个设备还可以接受,一旦项目里有多种型号、多条总线或多个项目,就很容易出错。
ThingsCloud 的 属性智能转换 正是为这个场景设计的。它的核心思路是:先在设备类型中定义属性,再在 Modbus 配置中把属性和寄存器地址绑定。
典型配置链路是:
- 在设备类型中创建属性,例如
temperature、humidity、voltage。 - 在 Modbus 配置中,为这些属性填写寄存器地址、读写类型、数据类型和字节序;普通透传场景还要确认从机地址,云网关子设备场景通常使用子设备地址。
- 开启 属性智能转换,并设置正确的自定义数据流。
- 通过任务下发 03 / 04 查询指令。
- 设备回复 Modbus 报文后,ThingsCloud 自动解析并更新属性当前值。

例如,你已经把温度属性绑定到输入寄存器 0x0000,数据类型配置为 16 位无符号整数,并按设备手册设置倍率。当设备回复:
01 04 04 09 C4 13 88 B4 B3
ThingsCloud 就可以根据寄存器表,把 09 C4 解析为温度属性,把 13 88 解析为湿度属性。随后这些属性可以用于设备详情、历史数据、可视化看板、ThingsX App、告警策略和自动化逻辑。
十、属性智能转换解决了哪些问题?
对新手来说,属性智能转换最大的价值不是“少写代码”,而是把 Modbus 的底层复杂度收敛到一张寄存器配置表里。
它主要解决 4 类问题:
| 问题 | 传统做法 | ThingsCloud 做法 |
|---|---|---|
| 报文看不懂 | 自己写解析脚本或用调试工具反复试 | 按寄存器表配置,平台自动解析 |
| 数据类型容易错 | 手动判断 16 位、32 位、浮点数和字节序 | 在 Modbus 配置中选择数据类型和字节序 |
| 上层应用难复用 | 每个应用都要理解寄存器 | 看板、App、告警统一使用属性 |
| 下发控制复杂 | 手写 Modbus 写寄存器报文 | 读写属性下发可自动转换为对应 Modbus 报文 |
在 ThingsCloud 中,数据寄存器可以绑定到 Number 属性。平台支持常见的 16 位整数、16 位无符号整数、32 位整数、32 位无符号整数和 32 位浮点数,并支持常见字节序配置。对于 IO 寄存器,则可以绑定 Boolean 属性。
十一、调试时按这 5 步排查
如果你正在现场调试 03 / 04 功能码,建议按下面顺序排查。
- 先看从机地址
请求里的第 1 个字节必须和设备实际地址一致。同一条 RS485 总线上不能有两个设备使用同一个从机地址。 - 再看功能码
设备手册写 03 就用 03,写 04 就用 04。不要只按经验猜。 - 核对起始寄存器地址
特别注意0x0000、0001H、40001这些写法之间的差异。不同手册和工具对地址起点的表达可能不同。 - 核对读取数量
读取数量是寄存器数量。读 2 个寄存器,回复数据区应该是 4 个字节。 - 最后看数据类型和字节序
如果日志有回复,但数值明显不对,优先检查 16 / 32 位类型、是否有倍率、字节序是否匹配。
如果使用 ThingsCloud,可以在设备调试日志中观察请求和回复,再结合 Modbus 配置表确认属性是否被正确更新。
总结
03 和 04 功能码并不复杂。请求报文的核心是“问哪台设备、用什么功能码、从哪个地址开始、读几个寄存器”;回复报文的核心是“哪台设备在答、答的是哪个功能码、后面有多少字节数据、每个寄存器的值是多少”。
真正容易出错的,是从报文到业务属性的最后一段:数据类型、字节序、倍率、寄存器地址和属性之间的关系。ThingsCloud 的属性智能转换把这段关系配置化,让设备回复的 Modbus 报文能够自动变成温度、湿度、电压、电流等设备属性,也让上层看板、App、告警和自动化不必直接面对底层报文。
对初学者来说,先学会拆 03 / 04 报文,再用 ThingsCloud 的 Modbus 配置把寄存器映射成属性,是理解 Modbus 设备接入最稳的一条路径。
相关文档可参考:
关于 ThingsCloud
ThingsCloud 是新一代物联网设备统一接入平台,帮助企业在极短的时间内搭建个性化的物联网平台和应用,并适应不断变化的发展需求。目前广泛应用于制造、电力、能源、环境、农业、楼宇、家居、教育、交通、物流、自动化等领域。
ThingsCloud 可接入各类网关,传感器、执行器、控制器、通信模组、智能硬件等,实现数据采集、远程控制,数据分析、告警通知、智能联动。还可以零代码生成项目应用 SaaS 和用户应用 App,并开放 API 和实时消息,便于业务系统集成和扩展开发。
通过使用 ThingsCloud,企业可以大大缩短搭建物联网系统的时间,节省软件开发费用,降低定制开发的风险,快速落地数字化和智能化项目。我们的客户遍布各行业,包括中国石化、中国铁塔、中国燃气、吉林大学、北控水务、ACE、中国民航大学、西安交通大学、精量电子、大秦铁路、宁波水利局等。




















