Skip to content

9.6 多机通讯(PLC 之间直接交换数据) ​

多机通讯是 LPPLC 自带的一套 PLC 与 PLC 之间直接交换 D 区数据的功能,走 UDP,STM32 版和 ESP32 版都支持。

主要优点是被读写的一方无需任何配置:开机即应答,不用配主从、不用规划 Modbus 地址、不用写脚本。多台设备联动时,这是配置量最小的方式。

多机通讯:两台 LPPLC 直接交换 D 区数据

适用场景与不适用场景 ​

需求建议
同一车间 / 同一交换机下的几台 LPPLC 互传数据用多机通讯,配置更简单
只传少量 D 寄存器,几十毫秒一轮用多机通讯
要传 M / Y / T / C 等非 D 软元件用 MODBUS TCP(多机通讯只能传 D)
对方不是 LPPLC(第三方 PLC、仪表、变频器)用 MODBUS TCP 或 Lua 的 pipe
跨网段、跨厂区、走 4G / 公网用云服务数据交换,多机通讯穿不了 NAT
数据一个字节都不能丢、必须有回执用 MODBUS TCP(多机通讯是 UDP,无回执)

先确认您的平台 ​

看型号首位就行,两个平台发起数据交换的方式不一样:

  • STM32 版(LP2xxx,如 LP2927 / LP2300 / LP2323)→ 用梯形图指令 DFROM / DTO
  • ESP32 版(LP3xxx,如 LP3202 / LP3203 / LP3232)→ 用 Lua 的 plc.get / plc.put

被读写的那一方(数据源)两个平台都一样:开机常开,不需要任何设定,也不限制同时被几台读写。所以主机是 STM32、从机是 ESP32(或者反过来)也能互通。

ESP32 版:用 Lua 的 plc.get / plc.put ​

两个函数参数顺序完全一样,记住「先对方,后自己」:

lua
plc.get(对方IP, 对方D起始, 本机D起始, 点数)   -- 读:对方的 D → 本机的 D
plc.put(对方IP, 对方D起始, 本机D起始, 点数)   -- 写:本机的 D → 对方的 D

最小可用例子,直接贴进 main.lua 就能跑:

lua
timer.start(100, function()                -- 100ms 一轮
    plc.get("192.168.2.136", 1, 2, 2)      -- 读对方 D1-D2 → 本机 D2-D3
    plc.put("192.168.2.136", 3, 2, 1)      -- 本机 D2 → 对方 D3
    print("D2=", plc.d(2))
end)

不用选通道,不用在设备参数里开开关,网口 / WiFi 通了就能用。函数详细说明见 plc.get / plc.put。

STM32 版:用梯形图 DFROM / DTO ​

先用 D8126 选走哪个网络通道,再用 DFROM(读)/ DTO(写)。两条都是 32 位指令:

梯形图:与下方指令表同一段程序

梯形图:与下方指令表同一段程序

LD    M8000
MOV   K8888     D8126           ; 选择 com8 作为 UDP 通道

; 读 192.168.0.10 的 D100 到本机 D0,1 点
DFROM HC0A8000A K100 D0   K1

; 把本机 D100 写到 192.168.0.11 的 D200,1 点
DTO   HC0A8000B K200 D100 K1
  • D8126:8887 = com7,8888 = com8,8889 = com9
  • 操作数顺序:对方 IP、对方 D 地址、本机 D 地址、点数(最大 512 点)

IP 要写成打包后的 32 位值

DFROM / DTO 的第 1 个操作数不能用「192.168.0.10」这样的点分写法。固件是把这个操作数按 4 个字节逐字节解析成 IP 的,所以要传打包后的 32 位值,用十六进制写最直观:

  • 192.168.0.10 → HC0A8000A
  • 192.168.1.100 → HC0A80164

换算方法:每段各转成两位十六进制再拼起来。192=C0、168=A8、0=00、10=0A → HC0A8000A。

也不要写成 K192168000010 这种去掉点的十进制数,它超出 32 位有符号整数上限(2147483647),无法输入。

选型提醒:DFROM / DTO 在两个平台语义不同

在 ESP32 版上,DFROM / DTO 是扩展模块寄存器读写指令,第一个操作数是扩展模块单元号(0~7),不是 IP。把 IP 传进去会直接报参数错误(出错代码 6708)。ESP32 版请用上面的 plc.get / plc.put。

实用例程 ​

梯形图:与下方指令表同一段程序

LD M8000
MOV D8031 D0
MOV D8032 D2
END

把上面的地址、主题、引脚替换成你项目里的即可。

实战:一台主机轮询两台从机 ​

实战:一台主机轮询两台从机的数据

约定好地址分工,后面加机器就是复制粘贴:

  • 每台从机:D100 放状态字(给主机读),D200 放控制字(等主机写)
  • 主机:D10/D11 存两台从机的状态,D20/D21 放要下发的控制字

主机侧脚本(ESP32 版):

lua
local slaves = { "192.168.1.21", "192.168.1.22" }
local i = 0

-- 每 60ms 只轮询一台,天然错开,加机器不用改这段
timer.start(60, function()
    i = i % #slaves + 1
    local ip = slaves[i]
    plc.get(ip, 100, 10 + i - 1, 1)    -- 从机 D100 → 主机 D10 / D11
    plc.put(ip, 200, 20 + i - 1, 1)    -- 主机 D20 / D21 → 从机 D200
end)

两台从机各 120ms 刷新一次。要更快就把 60 改小,机器多了就适当加大 —— 一轮的总时间 = 定时器周期 × 台数。

两台从机无需任何配置:不用写脚本、不用改参数,开机即会应答。

怎么知道对方还活着

多机通讯没有在线状态位。常用做法:让从机在 D101 里放一个自增的心跳计数,主机把它一起读回来,发现值一直不变就判断掉线。

lua
-- 从机侧:心跳自增
timer.start(500, function()
    plc.d(101, (plc.d(101) + 1) % 30000)
end)

读不到数据?按这个顺序查 ​

读不到数据?按这个顺序查

用之前必须知道的限制 ​

限制说明
只能传 D 区范围 D0-D7999,超出范围读回 0,不报错
单次点数上限ESP32 版 255 点,STM32 版 512 点
超了会静默截断ESP32 版填 300 点,实际只传 44 点,固件不报错
异步、无回执两个函数发出去就返回,没有返回值、没有超时、没有错误码
写入无确认plc.put 对方不回执,要确认写进去了只能过一会 plc.get 读回来核对
只能同局域网UDP 单播穿不了 NAT,跨网段跨地区请用云服务
Linux / RDA8910 版该平台不支持 plc.get(收不回数据),只有 plc.put 可用

25388 端口没有身份认证

局域网内任何设备都能直接读写本机 D0-D7999,固件不校验身份。这是设计如此(为了零配置),但意味着:

  • 不要把 25388 端口映射 / 转发到公网
  • 生产网络和办公 / 访客网络要隔开
  • 需要跨地区交换数据请走云服务,云通道是带账号鉴权的

相关 ​

LPPLC 工业物联网云平台 · 软硬件与云平台全栈自研