08 · 内置协议怎么用

相关:第 05 章 点、通道、设备 · 第 07 章 驱动是怎么工作的

什么时候你会需要它

你要接一台 PLC 的时候。 这一章是操作手册:找到你的 PLC 型号 → 照抄连接参数 → 按格式写地址。

地址写错是采集失败的头号原因 —— 每个协议的地址写法完全不同,不能照抄别的协议。

协议速查表

ProtocolId(通道里填这个) 适用设备 传输 地址示例
ModbusTcp 几乎所有支持 Modbus 的设备 TCP + 串口 40001、100(无区码)
Modbus-Inovance 汇川 H1u / H2u / H3u / AM 系列 TCP + 串口 同 Modbus 四区
Modbus-Delta 台达 DVP / AS 系列 TCP + 串口 同 Modbus 四区
Modbus-Xinje 信捷 XC / XD / XL 系列 TCP + 串口 同 Modbus 四区
Modbus-Fatek 永宏 FBs / B1 系列 TCP + 串口 同 Modbus 四区
Modbus-Schneider 施耐德 M221 / M241 等 TCP + 串口 同 Modbus 四区
Modbus-Meter 电表 / 温控表 / 变频器等通用从站 TCP + 串口 同 Modbus 四区
S7-200SMART 西门子 S7-200 SMART TCP VW100、VB200
S7-300/400 西门子 S7-300 / S7-400 TCP DB1.DBW20、MW10
S7-1200/1500 西门子 S7-1200 / S7-1500 TCP DB1.DBD100
Mitsubishi-MC 三菱 Q / L / FX 系列 TCP D100、M20
Omron-FINS 欧姆龙 CJ / CS 系列 TCP D100、CIO100.05
Panasonic-Mewtocol 松下 FP 系列 TCP DT100、D100
Simulation 没有真机时调试用 — 任意

💡 不知道设备用哪个协议? 查设备手册的"通信"章节,或者问厂家。 最常见的是 Modbus(约八成国产仪表和变频器都支持)。

上面那 6 个 Modbus- 开头的品牌档,报文仍是标准 Modbus,只是把 ProtocolId、显示名和地址提示 换成了对应品牌 —— 选它不会改变通信行为,但建点时的地址向导和提示会贴该品牌的说法。 内置协议一共 14 个档(Modbus 7 + 西门子 3 + 三菱 / 欧姆龙 / 松下 / 模拟各 1),可插件继续扩展。


Modbus TCP / RTU

最常用,先看这个。

连接参数

参数 值
连接方式 Tcp 或 Serial
TCP 参数 host(设备 IP)、port(默认 502)
串口参数 com(COM3)、baud(9600)、parity、databits、stopbits
从站号 设备的 slave id,常见是 1

地址写法

用传统地址(4 位/5 位数字),首位是区码:

地址形式 区 读写
0xxxx 线圈 Coil 可读可写(布尔)
1xxxx 离散输入 DiscreteInput 只读(布尔)
3xxxx 输入寄存器 InputRegister 只读(16 位)
4xxxx 保持寄存器 HoldingRegister 可读可写(16 位)

注意是"传统 1 基地址":

40001  →  保持寄存器 offset 0(协议地址 0)
40002  →  保持寄存器 offset 1

也就是地址数字减 1 才是协议里的偏移。这是 Modbus 最容易踩的坑 —— 有些设备手册给的是协议地址(从 0 起), 有些给的是传统地址(从 1 起),对不上就会整体偏移一个寄存器。

取寄存器里的某一位

40012.3  →  保持寄存器 offset 11 的第 3 位

有些设备把 16 个开关状态打包在一个寄存器里,用这种写法取其中一位。

⚠ 地址只认十进制

解析器走的是 long.TryParse —— 写 0x10 会直接抛"地址无法解析"。只写十进制数字。

一个地址占几个寄存器

点类型决定宽度,地址写的是起始寄存器:

点类型 占几个寄存器
Bool / Int16 / UInt16 / Bcd16 1
Int32 / UInt32 / Float / Bcd32 2
Int64 / Double 4
点类型 = Float,地址 = 40001  →  实际读 40001 + 40002 两个寄存器
点类型 = Float,地址 = 40002  →  ⚠ 和上面重叠了!下一个点要从 40003 开始

⚠ 规划点表时要按宽度留空。一堆 Float 点连着排 40001, 40002, 40003… 会互相覆盖 —— 正确排法是 40001, 40003, 40005…(每个间隔 2)。

没有区码前缀怎么办

100  →  按整体数字当保持寄存器序号

⚠ 这种写法有歧义,建议永远带上区码前缀。

32 位值(浮点/双字)

Modbus 一个寄存器只有 16 位,32 位值要跨两个寄存器。这时字节序必须配对:

点类型 = Float,地址 = 40001  → 会读 40001 + 40002 两个寄存器

如果读出来的浮点数是乱码(比如 1.2e-38 这种离谱值),八成是 ByteOrder 不对,试试改成 CDAB 或 BADC。


西门子 S7

三个型号是三个不同的 ProtocolId,别选错。

ProtocolId 机架/槽位 说明
S7-200SMART rack 0 / slot 1 V 区映射到 DB1
S7-300/400 rack 0 / slot 2 槽位是 2,不是 1
S7-1200/1500 rack 0 / slot 1 PLC 侧必须开启 PUT/GET

⚠ 两个最常见的失败原因: 1. 300/400 的槽位写死 1 —— 必须填 2。 2. 1200/1500 没在 TIA Portal 里勾选"允许来自远方伙伴的 PUT/GET 通信访问", 并且要关闭数据块的"优化的块访问",否则地址对不上。

地址写法

S7 的偏移按字节算(不像 Modbus 按寄存器):

形式 含义
VB100 V 区,字节偏移 100,读 1 字节
VW100 V 区,字节偏移 100,读 1 个字(2 字节)
VD100 V 区,字节偏移 100,读 1 个双字(4 字节)
MW10 / MD10 M 区
I0.0 / Q0.0 输入/输出区
DB1.DBB0 DB1 里字节偏移 0
DB1.DBW20 DB1 里字偏移 20
DB1.DBD100 DB1 里双字偏移 100

前缀字母的含义:

  • V —— 变量存储区。在 S7-200 SMART 上,V 区会被映射到 DB1(这是最容易错的地方)
  • M —— 位存储区
  • I / Q —— 输入 / 输出
  • DB —— 数据块,写成 DB{块号}.DB{大小}{偏移}

位地址:写成 字节.位

V100.3      → V 区字节 100 的第 3 位
I0.0        → 输入区第 0 字节第 0 位
M10.2       → M 区第 10 字节第 2 位
DB1.DBX2.5  → DB1 里字节 2 的第 5 位

位号 0~7(S7 一字节 8 位)。内部换算成线性位号:字节 × 8 + 位。

⚠ 位地址目前是实验性开放 —— S7 的位是"读所在字节再取位",走的是 S7 自己的通路, 与其它协议按字节宽度拆包的通路不同。正式投产前建议先在现场验证。

💡 这条纪律值得学:不支持的功能明确报错,而不是悄悄返回一个错值。 现场排查"值不对"比"功能没有"痛苦十倍。


三菱 MC

连接参数

参数 值
连接方式 Tcp
端口 默认 6000
帧格式 Qna_3E / A_1E(驱动自动处理)

地址写法

软元件字母 + 序号:

类型 支持的软元件 序号进制 示例
字软元件 D(数据寄存器)、R(文件寄存器)、ZR 十进制 D100、R200
位软元件 M(内部继电器)、L、S、F 十进制 M20、L10
字软元件 W 16 进制 W1F = 第 31 字
位软元件 X / Y / B 16 进制 X1A = 第 26 点、Y10 = 第 16 点

X / Y / B / W 照 GX 里的写法直接填即可(序号按 16 进制解析,不用自己换算)。

⚠ 这四个区目前是实验性开放 —— 进制已对底层库逐字核实,但位响应打包与连续读仍需现场核验; 正式投产前建议先在现场小范围验证。

第一期不支持的

  • SB / SW —— 底层库没有对应分支,开了会读错位置,所以明确抛异常
  • 位取字(如 D10.3)—— 需要跨拆包改造,同样不支持

欧姆龙 FINS

连接参数

参数 值
连接方式 Tcp
端口 默认 9600

地址写法

字区(读写数据):

区 全名 别名(都能写)
D DM 数据区 DM
C CIO 区 CIO
W WR 工作区 WR
H HR 保持区 HR
A AR 辅助区 AR

例:D100 和 DM100 是同一个地址。

位区(读写单个开关):写成 字.位:

CIO100.05   → CIO 区第 100 字的第 5 位
W20.3       → W 区第 20 字的第 3 位
D10.2       → D 区第 10 字的第 2 位

内部会换算成线性位号:字 × 16 + 位。

EM 区(扩展数据存储器):E<bank>.<字>,bank 按 16 进制、字与位按 10 进制:

E0.100      → bank 0 的第 100 字
E1A.50      → bank 0x1A 的第 50 字
E0.100.5    → bank 0 第 100 字的第 5 位

⚠ 上表未列出的区一律未开放,填了会明确抛异常,不会静默误读。


松下 Mewtocol

连接参数

参数 值
连接方式 Tcp
端口 默认 9094

地址写法

字区:

DT100  或  D100     ← 两种写法都认,是同一个地址(可读可写)
WR10                ← R 继电器字(只读)
WX10                ← X I/O 字(只读)
WY10                ← Y I/O 字(只读)

⚠ 继电器 / IO 字区(WR / WX / WY)只读 —— 底层库没有公开的写接口。

第一期不支持的

  • 其他区(LD 链接寄存器、WL 等)
  • 位区(R 继电器、X / Y I/O 的位写法)
  • 位取字

同样是为了不静默读错。


模拟驱动:没有真机时用

ProtocolId = "Simulation"

不连任何真实设备,按地址生成假数据。用途:

  • 做界面的时候 —— 不用等设备到场
  • 调脚本逻辑 —— 不用真的接 PLC
  • 演示 / 培训

地址随便填,它不会真的去读。


采集不通?按这个顺序排查

1. 通道的 DriverName 选对了吗?(型号别选错,尤其 S7 三个型号)
        ↓
2. 设备的 Endpoint 和 Connection.Params 对得上吗?(host/port 两处都要填)
        ↓
3. 从这台电脑能 ping 通设备吗?端口通吗?(telnet ip port)
        ↓
4. 从站号 / 槽位对吗?(Modbus 从站号、S7-300/400 的 slot=2)
        ↓
5. 点的地址格式对吗?(照上面各协议的表核对)
        ↓
6. 质量戳是什么?(Bad/CommFailure = 没读上来;Good 但值不对 = 地址偏了)
        ↓
7. 值不对但质量是 Good → 九成是 ByteOrder 或 RawMin/RawMax 的问题

💡 第 6 步很关键:质量戳 Bad 说明通信根本没成,是配置问题; 质量戳 Good 但数值离谱,说明通信是通的,只是地址或解析参数不对。这两类问题的排查方向完全不同。

小结

  • 先认型号,再照表填参数和地址 —— 别跨协议照抄地址写法
  • Modbus 是传统 1 基地址,40001 = offset 0
  • S7 是字节偏移,三个型号的槽位不一样,1200/1500 要开 PUT/GET
  • 三菱只支持十进制软元件(D/R/ZR/M/L/S/F)
  • 欧姆龙字区有别名,位区写 字.位
  • 不支持的地址会明确报错,不会静默返回错值

下一步:第 09 章 写一个自己的协议插件 —— 内置协议不够用的时候。