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/YI/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 章 写一个自己的协议插件 —— 内置协议不够用的时候。