Modbus 寄存器地址:40001 怎样对应协议偏移 0
手册写着 40010,起始地址为什么要填 9?对照完整 Modbus 请求,弄清寄存器编号、协议偏移、FC03 和十六进制地址。
Modbus 寄存器地址:40001 怎样对应协议偏移 0
手册写着 40010,软件的起始地址却要填 9,差别在于两边用的不是同一种编号。如果手册把第一个保持寄存器编号为 40001,而软件要求输入协议偏移,那么 40010 就该填十进制 9。ModbusKit 的 RTU 请求生成器使用的就是协议偏移。
有些软件也接受 40010 这样的参考编号,并替你完成换算。所以,遇到“地址”一栏,不能只凭字段名称判断该填哪个数。
手册里的 40010 是哪一种地址
Modbus 请求中的 PDU 地址从零开始。手册如何给寄存器编号,以及这些地址对应设备里的什么数据,则需要看厂商的定义。应用协议规范第 4.4 节说明了这层映射关系。
在保持寄存器从 40001 开始编号的手册中:
40001 - 40001 = 0 -> HEX 0000
40010 - 40001 = 9 -> HEX 0009
Modbus Organization 的入门说明使用了这种参考编号:开头的 4 表示保持寄存器区域,不会作为前缀放进请求的起始地址字节里。
但并非所有手册都写 40010。同一个位置也可能标成零基偏移 9、十六进制偏移 0009,或从一开始数的寄存器序号 10。先找表头里的进制、起始编号说明,拿不准时再对照手册给出的完整请求。已经是零基偏移的 9 不需要再减一;“所有地址都减一”会把原本正确的位置改错。
如果手册使用 400001 一类六位参考编号,也不要直接套用上面的五位公式。寄存器地址换算可以分别选择五位参考地址、六位参考地址和请求偏移。按手册选择数据区及格式后再换算;输入请求偏移时也支持 0x 开头的 HEX。
从 40010 生成一条读取请求
假设手册采用上面的 40001 编号方式,设备地址是 1,要从 40010 开始读两个保持寄存器。在 RTU 请求生成器中选择 DEC,设备地址填 1,功能码选 FC03,起始地址填 9,数量填 2,得到:
01 03 00 09 00 02 14 09
地址字段是 00 09,后面的 00 02 表示读两个寄存器。末尾 14 09 是按传输顺序排列的 CRC,其数值为 0914。可以把完整报文放进报文解析器,对照这些字段。
这里容易混淆的是功能码:参考编号前面的 4 不代表 FC04。保持寄存器用 FC03 读取,输入寄存器用 FC04 读取,两者是不同的数据区,定义见应用协议规范第 6.3、6.4 节。设备可能在两个区域的相同偏移处放置不同数据,也可能只支持其中一种读取功能。
如果手册要求读取输入寄存器,且给出的协议偏移同样是 9,对应请求是:
01 04 00 09 00 02 A1 C9
功能码变了,CRC 也随之改变。不过,即使 CRC 正确,也可能读错数据区或偏移。CRC 校验指南介绍了校验码能检查什么。
填入 10,读到的却是偏移 16
输入框的进制同样会改变地址含义。9 在 DEC 和 HEX 下恰好相同,换成 10 就不同了:
| 目标偏移 | 选择 DEC 时输入 | 选择 HEX 时输入 |
|---|---|---|
| 九 | 9 | 0009 |
| 十 | 10 | 000A |
| 十六 | 16 | 0010 |
在 HEX 模式下输入 10,请求里的地址字节就是 00 10,也就是十进制偏移 16。设备未必会报错:这个位置若存在,也会返回数据,甚至看起来像一个合理的测量值。检查生成报文中的地址字节,比单看输入框里的数字更可靠。
地址对了,才轮到 FLOAT32 的字序
假设 40010 开始存放的是一个 FLOAT32。每个寄存器只有 16 位,所以要连续读取两个寄存器,才能拿到一个完整的 32 位值。上面请求中的数量 2,读取的是一个浮点数所占的两个字。
以高字在前的排列为例,数据字节 3F 80 00 00 表示 FLOAT32 数值 1。下面是一条教学用的完整响应:
01 03 04 3F 80 00 00 F7 CF
其中 04 是数据字节数,接下来的四个字节才是浮点数内容。解析完整响应后,可以用 FLOAT32 转换示例查看这四个字节的结果。
这条响应本身没有起始偏移。FC03 的正常响应不会把请求中的 00 09 再发回来,因此要保留对应请求,才能确认读的是哪个位置。
如果数值不对,先回头看请求是否从正确位置读齐了两个寄存器,再检查手册规定的字序。读错了一对寄存器,交换它们的顺序也补不回缺失的数据。地址和数量确认后,可以继续用浮点数与字节序指南核对排列方式。