Modbus 设备配置
平台的 Modbus 连接器(服务名 modbus)作为 Modbus-RTU / Modbus-TCP 主站,与仪表、电源、采集模块、板卡等支持标准 Modbus 的从站设备通信。接入分两步:先在工位页面绑定设备(串口或 IP、从站地址、地址基准、字节序),再在仪器指令库按「数据区 + 地址 + 类型」写指令模板。
模板长这样,功能码由连接器自己推导,不用填:
HR:100;FLOAT:CDAB 读保持寄存器 100 起的 2 个,按字交换解析成浮点
HR:200=5 写 5 到保持寄存器 200
CO:0=1 线圈 0 置 ON记住三条判据就够了:
| 看到什么 | 结论 |
|---|---|
请求里有 = | 这是写(RW: 例外,带 = 但按读处理) |
开头是 HR / IR / CO / DI | 数据区,决定用哪个功能码(也可以直接写手册的 Modicon 编号,如 40101) |
| 分号后面的一段 | 解析段,决定读回来的字节怎么变成数字 |
本文以一台虚构的 DEMO_PM100 功率计(RS485,9600 8N1,从站地址 1)贯穿示例,写哪条指令直接对照第 11 节速查表复制即可。
相关页面:ATEBOX 485 连接说明、PMBus 设备配置、UDS 设备配置、PLC 设备配置、WAVESHARE 适配器配置。
1. 先备好点表这几项
从设备手册(或厂家给的点表)里抄下这几项,后面每一步都要用:
| 项目 | 说明 | 示例 |
|---|---|---|
| 传输方式 | 串口 RTU 还是以太网 TCP | RTU(RS485) |
| 从站地址 | 设备的 unit 号,1 ~ 247 | 1 |
| 数据区 | 线圈、离散输入、输入寄存器、保持寄存器 | 保持寄存器 HR |
| 地址 | 手册原样抄下来,写法见 1.2 | 40001 |
| 数据类型 | 16 位、32 位、浮点、BCD、字符串 | FLOAT,占 2 个寄存器 |
| 字节序 | 多字节数值的排列方式 | 字交换 CDAB |
1.1 四个数据区与功能码
| 数据区 | 前缀 | 手册地址段 | 读 | 写 | 单元 |
|---|---|---|---|---|---|
| 线圈(DO) | CO | 00001 ~ 09999 | FC1 | 单个 FC5、多个 FC15 | 1 位 |
| 离散输入(DI) | DI | 10001 ~ 19999 | FC2 | 不可写 | 1 位 |
| 输入寄存器(AI) | IR | 30001 ~ 39999 | FC4 | 不可写 | 16 位 |
| 保持寄存器(AO/通用) | HR | 40001 ~ 49999 | FC3 | 单个值 FC6、多值或 32 位以上 FC16 | 16 位 |
往离散输入、输入寄存器配写指令,模板在发送前就会被拒(提示「输入寄存器不可写」「离散输入不可写」),不用等设备回异常码。
1.2 地址怎么写
地址有三种写法,同一条模板里(请求和解析段)只能用同一种,不要混着来。
写法一:数据区:点号,如 HR:100、IR:16、CO:0、DI:3。
点号按工位绑定里的「地址基准」解释:
| 地址基准 | HR:100 的实际协议地址 | 什么时候选 |
|---|---|---|
0(缺省) | 100 | 手册给的已经是 0 起的协议地址 |
1 | 99 | 手册按 1 起编号(HR:1 指协议地址 0,HR:0 发送前报错) |
写法二:Modicon 编号,直接照抄手册的 40001、30010、00001:5 位或 6 位纯数字、首位是区号即可。这种写法不受地址基准影响:
| 首位 | 数据区 | 例子 | 协议地址 |
|---|---|---|---|
0 | 线圈 | 00001 | 0 |
1 | 离散输入 | 10001 | 0 |
3 | 输入寄存器 | 30010 | 9 |
4 | 保持寄存器 | 40101、400101 | 100 |
- 区号后面的点号从 1 起,所以
40101是第 101 个点,协议地址 100。 - 5 位编号最多到 9999 点;点数更大写 6 位(
400101),或改用HR:写法。 - 首位不是 0、1、3、4(如
22345)、点号为 0(如40000),发送前直接报错。
写法三:手册的 4x、0x 前缀必须去掉。 信捷等手册常写 4x41098、4x200、0x60,前缀只表示数据区,后面才是地址本体,请改成数据区写法:
| 手册写法 | 模板里写 | 不要写成 |
|---|---|---|
4x200(D200) | HR:200 | 40200(这是 Modicon,协议地址 199) |
4x41098(HD10) | HR:41098 | 41098(会被当成 5 位 Modicon,协议地址 1097) |
0x0、0x60(线圈) | CO:0、CO:0x60 | 00001(只表示线圈协议地址 0) |
元件号是八进制的(Y10、X17 这类只到 7),先自己换算成十进制线圈地址。M、D、HD、Y 这些元件名连接器不认,只认数据区加地址。
1.3 数字怎么写
地址、数量、写入值共用一套规则:
| 写法 | 含义 |
|---|---|
100、-5、1.5 | 十进制 |
0x6000、6000H | 十六进制,两种等价,不能同时写(0x6000H 报错) |
1A、FF、0b101 | 发送前报错。含 A ~ F 的会提示改成 0x1A 或 1AH,二进制不支持,请自行换算 |
字节串(FC: 的数据区、HEX 写入)另算一套:每个字节一律十六进制,空格、逗号分隔或整串连写都行(01 02、01,02、0102 等价),位数必须是偶数。
1.4 从站地址(unit)
| 取值 | 含义 |
|---|---|
1 ~ 247 | 正常单播,一问一答 |
0 | 广播:只发送、不等待响应,不能用于读,也不能用于按位写 |
248 ~ 255 | 保留,一般不用 |
同一条 RS485 总线可以挂多台设备,靠 unit 区分;绑成多个仪器就能分别读写。
2. 在工位绑定设备
在工位页面添加仪器,选 Modbus 连接器对应的型号,按传输方式填写。串口参数、从站地址、地址基准、字节序都属于设备级配置,只在这里填,不要写进指令模板。
2.1 RTU(串口 / RS485)
| 字段 | 必填 | 填写说明 |
|---|---|---|
| 协议 | 是 | 选 rtu(串口) |
| 资源 | 是 | 下拉选择本工位的串口,形如 modbus::serial:COM3(以工位列表实际显示为准);插好 USB-RS485、接好 485 端子后再开这个窗口 |
| 波特率 | 是 | 与设备一致,常见 9600、19200、38400、115200 |
| 数据位 | 是 | 常见 8(可选 5 ~ 8) |
| 校验 | 是 | N(无)/ E(偶)/ O(奇) |
| 停止位 | 是 | 1 或 2 |
| 从站地址 | 是 | 设备的 unit 号,默认 1 |
| 地址基准 | 建议核对 | 0(缺省,协议地址)/ 1(手册从 1 编号),见 1.2 |
| 字节序 | 建议核对 | ABCD(缺省)/CDAB/BADC/DCBA,见 2.3 |
| 超时时间 | 建议核对 | 毫秒,默认 1000;响应慢的设备加到 2000 ~ 3000 |
| 重试次数 | 可选 | 超时、CRC 错误时的额外重发次数,0 ~ 10,默认 0 |
2.2 TCP(以太网)
| 字段 | 必填 | 填写说明 |
|---|---|---|
| 协议 | 是 | 选 tcp |
| 主机 | 是 | 设备或串口服务器的 IP,如 192.168.0.10 |
| 端口 | 是 | 默认 502,串口服务器可能映射成 4001 等,按设备实际填 |
| 从站地址 | 是 | 串口服务器后面的从站号;直连网口的设备通常是 1 |
| 地址基准 / 字节序 / 超时 / 重试 | 建议核对 | 同上 |
2.3 字节序选哪个
以 32 位 0x12345678 为例,四种排列在线上发出的字节:
| 选项 | 线上字节 | 常见叫法 |
|---|---|---|
ABCD | 12 34 56 78 | 大端(缺省) |
CDAB | 56 78 12 34 | 字交换 |
BADC | 34 12 78 56 | 字节交换 |
DCBA | 78 56 34 12 | 小端 |
64 位同理:CDAB 是四个寄存器整体倒序,BADC 是每个寄存器内部两字节对调。16 位只看寄存器内部,BADC、DCBA 对调两个字节,ABCD、CDAB 没有区别。
读出来的浮点是离谱大数或 0,先换字节序,再怀疑地址。
2.4 总线是共享的,参数必须一致
- 同一条串口上绑定的所有仪器共享一根总线和一把锁,请求排队串行执行。同一串口的波特率、数据位、校验、停止位必须完全一致,否则保存时被拒,并提示已占用该串口的仪器序列号。
- 同一个
IP:端口上绑定的所有仪器共享一个连接,靠从站地址区分,请求同样串行。 - 连接器不在指令之间插延时,需要等待时用流程的等待节点控制。
2.5 在线状态怎么看
| 传输 | 在线判定 |
|---|---|
| TCP | 连接是否建立(每 15 秒检查一次,断线自动重连) |
| RTU | 绑定保存成功即显示在线 |
连接器不主动探测从站:指令超时、CRC 错误、设备返回异常码,都不会把仪器标成离线。所以「在线」只代表通路在,读数不对仍要按第 12 章查地址、数据区和参数。
3. 模板怎么构成
<请求>[;解析段][;解析段]...- 请求里有
=就是写,请求类型必须是2;RW:带=但仍按读处理。读的请求类型由平台下发(3),读指令必须配测试指标,否则报「读操作必须提供响应定义」。 - 关键字和类型名不区分大小写,前后空格忽略。
- 模板里的
{{参数编码}}先由测试参数替换,再解析。占位符名只认字母、数字、下划线(可以,NaN不认);缺参数时发送前失败,并列出全部缺失的名称。
七种骨架,覆盖所有场景:
| 目的 | 模板骨架 | 示例 |
|---|---|---|
| 读保持/输入寄存器 | HR:<地址>[:<数量>][;段...] | HR:100;FLOAT:CDAB |
| 读线圈/离散输入 | CO:<地址>[:<数量>][;段...] | CO:0:8;BIT;BIT |
| 写(单值/多值) | <数据区>:<地址>=<值>[,<值>...] | HR:200=5、HR:200=1,2,3 |
| 按位写 | HR:<地址>.<位>=<0|1> | HR:100.3=1 |
| 先写后读 | RW:<读地址>:<数量>:<写地址>[:<类型>]=<值>... | RW:3:6:14:UINT16=255,255,255;UINT16 |
| 读设备标识 | ID[:<读码>][;ID:<对象>]... | ID;ID:PRODUCT |
| 自定义功能码 | FC:<功能码>[:<字节串>][;段...] | FC:0x41:01 02;LEN:6;FLOAT |
旧版的
MB:FC…、READ:、WRITE:写法已全部废弃,现在填进去会直接报「旧语法」。老模板请按本文改写。
4. 读取指令
在仪器指令库中新增 「读取指令」,页面分基本信息、测试参数、测试指标三块,至少要有 1 条测试指标。
读的请求只有数据区、地址、数量三段,数量可以省略:
- 省略数量:读到解析段覆盖的最后一个地址为止(
HR:100;FLOAT自动读 2 个寄存器);没有解析段时读 1 个。 - 写了数量:必须盖住所有解析段,
HR:0:1;FLOAT会因为浮点要 2 个寄存器而失败。 - 上限:寄存器一次最多 125 个,线圈一次最多 2000 个。
HR:100;UINT16 读 1 个寄存器
HR:100:10;UINT16:102;BIT:105.3 读 100~109,取 102 的整数值、105 的第 3 位
CO:0:8;BIT;BIT 读 8 个线圈,取第 1、2 个
DI:0;BIT;BIT;BIT 读 3 个离散输入
40101;FLOAT 同一个点,按 Modicon 编号写4.1 解析段的地址是绝对地址
这一点和别的组态软件不同,别按「相对偏移」去想:
- 请求写
HR:100,段里就写102、0x66,按同一个地址基准解释。 - 请求用 Modicon 编号(
40101),段里也必须写 Modicon 编号(40103)。写成BIT:105.3会失败,并提示改成 Modicon 编号。 - 段地址必须落在本次读取范围内,且不能小于读起点。
- 省略段地址:紧接上一段往后排,第一段从读地址开始。连续点位就全都省掉地址。
- 点位不连续就显式写地址;它后面那些省略地址的段会跟着整体后移。
连续读时,段的长度决定它占几个寄存器:FLOAT 占 2 个,UINT16 占 1 个,DOUBLE 占 4 个。
4.2 配置示例:读电压
| 项目 | 填写 |
|---|---|
| 指令名称 | 读取电压 |
| 指令编码 | get_read_voltage |
| 指令模板 | HR:0;FLOAT:CDAB |
| 指令说明 | DEMO_PM100 电压,2 个寄存器,字交换浮点 |
测试指标(1 条):
| 指标名称 | 指标编码 | 指标类型 | 指标分类 | 指标单位 | 小数位 |
|---|---|---|---|---|---|
| 电压 | voltage | 数值 | 电压 | V | 2 |
读数值一定要写类型段(;FLOAT、;UINT16)。不写解析段时,指标拿到的是空格分隔的大写十六进制串(如 41 48 00 00),不是数字。
4.3 一次读多个量
分号分隔的每个占指标的段对应一条测试指标,顺序一一对应。TMO、LEN、FC16、FC22 这些选项不占指标。
示例——读电压、电流并算功率,共 3 条指标:
| 项目 | 填写 |
|---|---|
| 指令名称 | 读取电压电流及功率 |
| 指令编码 | get_read_vi_p |
| 指令模板 | HR:0;FLOAT:CDAB;FLOAT:CDAB;EXPR:voltage*current |
| 顺序 | 指标名称 | 指标编码 | 指标类型 | 单位 |
|---|---|---|---|---|
| 1 | 电压 | voltage | 数值 | V |
| 2 | 电流 | current | 数值 | A |
| 3 | 功率 | power | 数值 | W |
规则要点:
- 占指标的段数必须等于测试指标条数,否则发送前报「模板解析段数与 replys 数量不匹配」。
EXPR里的变量名优先取指标编码,其次指令原始键;变量必须是前面已经出现的指标。- 表达式支持
+ - * / % **、括号、一元负号,以及abs、round、min、max、sqrt。 - 指标的
scale和小数位只作用于十进制数值指标,字符串、十六进制显示不参与缩放。
5. 解析段详解
<类型>[:<地址>][:<字节序>]| 段 | 占用 | 说明 |
|---|---|---|
INT16 UINT16 BCD16 | 1 个寄存器 | BCD 任一半字节大于 9 则解码失败,报错带原始字节 |
INT32 UINT32 FLOAT BCD32 | 2 个寄存器 | |
INT64 UINT64 DOUBLE | 4 个寄存器 | |
STRING:<地址>:<字节数>[:BA] | 字节数 ÷ 2 向上取整 | ASCII,去掉尾部 00 和空格。地址必填;BA 先把每个寄存器内两字节对调,字节数必须是偶数 |
HEX[:<地址>[:<字节数>]] | 同上 | 空格分隔的大写十六进制。全省略时是整个数据区;只写地址时从该地址取到本次读取末尾 |
BIT:<地址>.<位> | 1 个寄存器,不推进顺延位置 | 位 0 是该寄存器最低位,结果为 0 或 1 |
BIT:<地址>.<高>-<低> | 同上 | 位域,高位必须大于等于低位,结果为整数 |
BIT[:<地址>] | 1 个线圈或离散输入 | 不写地址时从读起点向后顺延;线圈按字节打包,最低位是第一个线圈 |
EXPR:<表达式> | 不占位置 | 用前面的指标计算 |
5.1 位、位域、字符串、原始字节
| 需求 | 模板 | 指标类型 | 说明 |
|---|---|---|---|
| 读寄存器内第 5 位 | HR:0x100;BIT:0x100.5 | 数值 | 结果是 0 或 1 |
| 读状态字第 7 ~ 5 位 | HR:0x100;BIT:0x100.7-5 | 数值 | 位域,结果是整数 |
| 位域带文字含义 | HR:0x100;BIT:0x100.2-0:0=OFF,1=ON,2=ERR | 字符串 | 编码不在表里则该指标失败 |
| 读线圈第 0 个 | CO:0:8;BIT:0 | 数值 | 线圈用 BIT 不带点号 |
| 连续几个线圈 | CO:0:8;BIT;BIT | 数值 | 不写地址自动顺延 |
| 读 8 字节 ASCII | HR:0x10;STRING:0x10:8 | 字符串 | 地址必填 |
| 同上,寄存器内字节对调 | HR:0x10;STRING:0x10:8:BA | 字符串 | 字节数必须偶数 |
| 读原始字节 | HR:0:4;HEX:0:8 | 字符串 | 输出 41 4C 52 这种大写十六进制 |
BIT段占 1 个寄存器但不推进顺延位置,所以同一个寄存器要拆两个位域时,写两段、地址各写一遍即可。- 对照表写在位号后,给文字指标(类型选「字符串」)用;数值指标的对照值必须是数字。
STRING、HEX里的数字都是字节数,不是寄存器数。- 不写解析段时,整个数据区的十六进制串会填进每一个指标。
5.2 字节序写法
字节序写在类型后面,缺省取绑定里的设置(再缺省 ABCD):
FLOAT:CDAB 字节序 CDAB,地址从读起点开始
FLOAT:102 地址 102
FLOAT:102:CDAB 地址 102,字节序 CDABABCD、CDAB 这些是字母,不会被当成地址,所以 FLOAT:CDAB 不会被理解成「地址 0xCDAB」。
6. 设置指令
写操作在 「设置指令」 页面创建,= 一出现就是写,请求类型由平台置为 2;IR、DI 以及 Modicon 的 1 区、3 区不能写。
设置指令一般不加测试指标,把要写的值开放成测试参数(模板里写 {{value}},参数编码填 value)。
6.1 常用写法
| 模板 | 功能码 | 说明 |
|---|---|---|
HR:100=5 | FC6 | 缺省 16 位,范围 -32768 ~ 65535,负数取补码 |
HR:100=1,2,3 | FC16 | 连续写多个寄存器 |
HR:100:FLOAT:CDAB=3.3,4.4 | FC16 | 类型可写整数、BCD、FLOAT、DOUBLE |
HR:100=5;FC16 | FC16 | 设备不支持 FC6 时,单个 16 位值也走 FC16 |
HR:100:STRING:16=ABC | FC16 | 不足补 00,超长失败;BA 在补齐后对调字节 |
HR:100:HEX=01 02 03 04 | FC16 | 原始字节,必须是偶数个 |
CO:0=1 | FC5 | 1 发 FF00(ON),0 发 0000(OFF) |
CO:0=1,0,1 | FC15 | 多线圈,最低位是第一个线圈 |
HR:100.3=1 | FC3 + FC6 | 按位写,见 6.2 |
HR:100.3=1;FC22 | FC22 | 屏蔽写,从站一次完成 |
40101=5、40101.0=1 | FC6 / FC3+FC6 | 与 HR: 等价,区号决定数据区 |
写请求只要 PDU 不超过 253 字节就发送,不按标准里「一次最多写多少个」拒绝——例如线圈一次写 1976 个是允许的。
6.2 按位写:默认是读-改-写
HR:100.3=1 的实际动作是在同一把总线锁内:先 FC3 读 1 个寄存器 → 改第 3 位 → 再 FC6 写回。读失败就不写。位号范围 0 ~ 15。
中间那一刻的值可能被别的主站改掉,所以设备支持 FC22 时优先加 ;FC22,交给从站一次原子完成:
HR:100.0=1 读-改-写
HR:100.0=1;FC22 屏蔽写6.3 写入值换算(;EXPR:)
寄存器数值写可以在末尾加 ;EXPR:<表达式>,变量名固定为 value,每个写入值先换算再编码:
HR:10=12.5;EXPR:value*10 写入 125
HR:0:FLOAT=1.5;EXPR:value*10 写入 15.0整数类型(含缺省的 16 位和 BCD)结果必须是整数,出小数会报「整数类型的换算结果必须是整数」。HEX、字符串、线圈、按位写不能加 EXPR。
6.4 配置示例:设置输出电压
| 项目 | 填写 |
|---|---|
| 指令名称 | 设置输出电压 |
| 指令编码 | set_voltage |
| 指令模板 | HR:0x200:FLOAT:CDAB={{value}} |
| 指令说明 | 写 2 个寄存器,字交换浮点 |
测试参数:参数名称「输出电压」,参数编码 value,参数类型「数值」,参数形式「自定义」,范围 0 ~ 60,单位 V。
6.5 设置指令能带什么
只允许这些:TMO(覆盖本条超时);寄存器数值写另可带 EXPR、FC16;按位写另可带 FC22;FC: 另可带 LEN。带类型段、BIT 之类会在发送前报「写指令不支持解析段」——写操作的响应不解码。
7. 读写组合(先写后读)
RW:<读地址>:<读数量>:<写地址>[:<类型>][:<字节序>]=<值>[,<值>...][;解析段...]功能码 23,先写后读,按读指令处理:类型不能是 2,必须配测试指标。
- 三个地址写法与前面一致,都是寄存器;读数量 1 ~ 125。
- 解析段地址落在读区间内;不能写字符串。
RW:3:6:14:UINT16=255,255,255;UINT16 先往 14 写 3 个寄存器,再读 3 起的 6 个8. 设备标识
ID[:<读码>][;ID:<对象>]...走功能码 43(MEI 类型 14),按读指令处理。读码缺省 1,可取 1 ~ 4(1 基本、2 常规、3 扩展、4 单个对象);读码填 4 时只能有一个 ID: 段,连接器就用那个对象号发请求。
对象可以写名称或编号:
| 对象名称 | 编号 |
|---|---|
VENDOR | 0 |
PRODUCT | 1 |
VERSION | 2 |
URL | 3 |
NAME | 4 |
MODEL | 5 |
APP | 6 |
0x80 及以上的厂商自定义对象没有名称,直接写编号。
- 值是 ASCII,去掉尾部空白;响应里没有该对象,对应指标就失败。
- 响应提示还有后续对象时,连接器在同一条指令内接着读,最多 8 帧;超出则返回已读到的对象,并在日志里告警。
ID;ID:VENDOR;ID:PRODUCT
ID:4;ID:MODEL9. 自定义功能码
FC:<功能码>[:<字节串>][;段...]功能码沿用第 1.3 节的数字规则:FC:0x41 和 FC:41H 都是 65,而 FC:41 是十进制 41(0x29)。不在规范定义范围内、也不在保留区(65 ~ 72、100 ~ 110)的功能码照常发送,日志里会记一条警告。
- 数据区原样发送,每个字节十六进制、位数偶数。
- 响应取功能码之后的全部字节,段里的位置是字节偏移(从 0 起):
FLOAT;UINT16依次占 4 字节和 2 字节,等价于FLOAT:0;UINT16:4。 BIT:<偏移>.<位>在这一段里是从该偏移起的 2 个字节中取位。;LEN:<字节数>是响应数据区的字节数(不含功能码)。RTU 下读满即返回,不写就靠帧间静默判断结束;TCP 的长度由报文头决定,LEN只做发送前的范围检查。能确定长度时请写上。- 放在设置指令里(类型 2)不能带解析段,响应不解码,
LEN只用于 RTU 切帧。 FC:不核对功能码与指令类型是否匹配:FC:3:00 00 00 02在设置指令里也能发,但响应当原始字节,不会按保持寄存器解析。
FC:8:00 00 12 34
FC:0x41:01 02;LEN:6;FLOAT;UINT16
FC:0x41:01;LEN:2;TMO:100 设置指令里合法10. 选项段
不占指标,每种最多一段:
| 段 | 用于 | 说明 |
|---|---|---|
TMO:<毫秒> | 全部模板 | 覆盖这一条的响应超时,必须大于 0;按位写、设备标识的每一帧都用它 |
LEN:<字节数> | FC: | 响应数据区字节数,1 ~ 250 |
FC16 | 寄存器数值写 | 单个 16 位值也改用 FC16 |
FC22 | HR:<地址>.<位>= | 用屏蔽写代替读-改-写 |
11. 常用指令速查
同一点位既能读又能写时拆成两条,分别在「读取指令」「设置指令」里建。模板请原样复制,不要改写成指令编码。
11.1 常用读取
| 指令名称 | 指令编码 | 指令模板 | 测试指标(编码 / 名称 / 类型) |
|---|---|---|---|
| 读保持寄存器 | get_read_reg | HR:0;UINT16 | value / 读数 / 数值 |
| 读有符号寄存器 | get_read_reg_int | HR:0;INT16 | value / 读数 / 数值 |
| 读 32 位寄存器 | get_read_reg32 | HR:0;UINT32 | value / 读数 / 数值 |
| 读浮点 | get_read_float | HR:0;FLOAT | value / 读数 / 数值 |
| 读浮点(字交换) | get_read_float_cdab | HR:0;FLOAT:CDAB | value / 读数 / 数值 |
| 读 BCD 32 位 | get_read_bcd | HR:200;BCD32 | value / 读数 / 数值 |
| 读输入寄存器 | get_read_input | IR:0;UINT16 | value / 读数 / 数值 |
| 读线圈 | get_read_coil | CO:0;BIT | state / 线圈状态 / 数值 |
| 读离散输入 | get_read_di | DI:0;BIT | state / 输入状态 / 数值 |
| 读连续 4 个线圈 | get_read_coils4 | CO:0:4;BIT;BIT;BIT;BIT | 4 条:coil0 ~ coil3 |
| 读状态字拆位域 | get_read_status | HR:0x100;BIT:0x100.7-5;BIT:0x100.2-0:0=OFF,1=ON | 2 条:mode、fault |
| 读 ASCII 名称 | get_read_name | HR:0x10;STRING:0x10:8 | name / 名称 / 字符串 |
| 读原始字节 | get_read_raw | HR:0:4;HEX:0:8 | raw / 原始数据 / 字符串 |
| 读电压电流功率 | get_read_vi_p | HR:0;FLOAT:CDAB;FLOAT:CDAB;EXPR:voltage*current | 3 条:voltage、current、power |
| 先写后读 | get_read_after_write | RW:3:6:14:UINT16=255,255,255;UINT16 | value / 读数 / 数值 |
| 读厂商与型号 | get_read_id | ID;ID:VENDOR;ID:MODEL | 2 条:vendor、model(字符串) |
11.2 常用写入
| 指令名称 | 指令编码 | 指令模板 | 测试参数 |
|---|---|---|---|
| 写单个寄存器 | set_reg | HR:0={{value}} | value(数值) |
| 写固定十六进制值 | set_reg_hex | HR:0=0x1234 | 无(固定值) |
| 写多个寄存器 | set_regs | HR:0:UINT16={{v1}},{{v2}} | v1、v2(数值) |
| 写浮点(字交换) | set_float_cdab | HR:0:FLOAT:CDAB={{value}} | value(数值) |
| 写字符串 | set_string | HR:0x10:STRING:16={{text}} | text(字符串) |
| 写单个线圈 | set_coil | CO:0={{value}} | value(选项:0=断开,1=闭合) |
| 写多个线圈 | set_coils | CO:0={{b0}},{{b1}},{{b2}} | b0 ~ b2(0/1) |
| 只改一位 | set_bit | HR:100.3=1 | 无(固定值) |
| 只改一位(屏蔽写) | set_bit_mask | HR:100.3=1;FC22 | 无(固定值) |
| 写原始字节 | set_raw_bytes | HR:0:HEX=12 34 | 无(固定值) |
| 带缩放写入 | set_scaled | HR:0={{value}};EXPR:value*10 | value(填 25.5 实际写 255) |
| 动态地址写 | set_addr_value | HR:{{addr}}={{value}} | addr、value |
| 覆盖本条超时 | set_slow | HR:0x10={{value}};TMO:2500 | value(数值) |
模板里出现
{{xxx}},测试参数就必须有编码为xxx的参数,否则发送前报「参数列表中缺少模板中引用的参数」,并列出全部缺失的名称。
12. 填错了怎么查
| 现象 / 提示关键词 | 可能原因 | 处理建议 |
|---|---|---|
旧语法 | 模板里还是 MB:FC…、READ:、WRITE: | 按本文第 3 章改写 |
参数列表中缺少模板中引用的参数 | 占位符和测试参数编码对不上 | 补齐同名参数,编码区分大小写 |
含十六进制字符,请写 0x1A 或 1AH | 写成了 1A、FF 这种不带前缀的十六进制 | 加 0x 前缀或 H 后缀 |
应以 HR、IR、CO、DI… 开头 | 地址既不是数据区,也不是 5 位/6 位 Modicon 编号 | 补数据区前缀,或按 Modicon 写 |
段地址应写 Modicon 编号 | 请求用了 40101,解析段却写 105 | 段地址改成同区的 Modicon 编号 |
不在 … 内 / 需要寄存器 | 解析段超出读取数量(HR:0:1;FLOAT) | 数量盖住全部段,或让连接器自动推数量 |
读到的数和手册差 1、和 4x41098 对不上 | 把 4x 后面的地址当成了 5 位 Modicon 编号 | 4x41098 写 HR:41098,不要写 41098 |
请求 type 必须是 2 / type 不能是 2 | 写模板当成读、读模板当成写 | 有 = 的是写,RW/ID 按读处理 |
输入寄存器不可写 / 离散输入不可写 | 对 IR、DI 写值(含 Modicon 1 区、3 区) | 写操作用 CO 或 HR |
写指令不支持解析段 | 设置指令带了类型段、BIT | 只留 TMO,数值写可加 EXPR/FC16,按位写可加 FC22 |
模板解析段数与 replys 数量不匹配 | 占指标的段数与指标条数不同 | 一段一条指标,选项段不算 |
读操作必须提供响应定义 | 读指令没配测试指标 | 至少配 1 条指标 |
从站地址 0 是广播地址 | unit=0 用在了读或按位写上 | 广播只能写;读和按位写改成 1 ~ 247 |
整数类型的换算结果必须是整数 | EXPR 出小数,而类型不是 FLOAT/DOUBLE | 换成浮点类型,或调整表达式 |
异常码 0x02:非法数据地址 | 地址超设备映射,或往只读区写 | 核对点表;0x0A 是网关路径不可用,0x0B 是网关目标无响应 |
响应超时 | 设备无响应:接线、串口参数、从站号、IP/端口 | 先用最简单的单点读验证通路,或调大超时 |
| 日志提示「未在 Modbus 中定义」 | FC:41 是十进制 41,不是 0x41 | 手册的十六进制功能码写 FC:0x41 或 FC:41H |
自查顺序:
- 模板是不是按「数据区:地址」写的,有没有残留旧语法
- 地址有没有撞上 Modicon 编号(
41098vsHR:41098),地址基准选得对不对 - 读取指令:指标条数 = 占指标的段数
- 先用最简单的单点读(已知地址的
UINT16)验证通路,再上多段、位域、浮点 - 数值离谱:换字节序(
ABCD/CDAB/BADC/DCBA),再核对地址 - 仍失败看工位日志:请求发出去没有、设备回了什么异常码
13. 配置流程速览
抄点表:数据区(HR/IR/CO/DI)+ 地址 + 类型 + 字节序
↓
工位绑定:RTU(串口 + 波特率 + 校验 + 停止位)
或 TCP(IP + 端口)
统一填:从站地址、地址基准、字节序、超时
↓
确认地址:手册 40001 → 40101(Modicon)或 HR:0
手册 4x200 → HR:200(去掉 4x)
↓
读取指令:HR:<地址>;<类型>[:<字节序>](段数 = 指标条数)
或设置指令:HR:<地址>=<值> / HR:<地址>:FLOAT:CDAB=<值>
↓
一次读多个量 → 多个解析段 + EXPR(变量用前面的指标编码)
厂商私有功能码 → FC:0x41:…;LEN:<n>,能确定长度就写 LEN
↓
读不到或读不对 → 按第 12 章排查(模板 → 地址 → 段 → 字节序 → 通路)