Skip to content

MODBUS 串口通讯例程 ​

用梯形图把本机的 RS-485 串口配成 MODBUS 从站(让其他设备读取本机),或者配成主站去读别的设备。 先给 9 段串口例程,再附 2 段带网口的 STM32 版机型用网口跑 MODBUS TCP 的例程。 下面所有模式值都按本机实际能跑通的写法给出;如果您手上还留着更早版本的纸质手册, 其中串口 3 的两处模式值(印的是 K2007 / K2008)是串口 2 的值,照本页写即可。

返回 例程总览。


动手前先记住三件事 ​

  1. MOV 一条 + 通讯指令一条,成对出现。 EXTR / DEXTR / ADPRW 自己不带功能编号,做什么由 D8126 决定。 设备支持的每一个模式值、以及它在哪款机型上有,全列在 6.3 D8126 模式表。 您这台机型没有的那一档执行会报 6599 —— 最容易碰到的是 K7004~K9004 网口套接字那一组,它只有带网口的 STM32 版机型有。
  2. D8126 是全局的一个寄存器。 程序里所有这几条指令共用它 —— 一个扫描周期里要让同一条指令做两件事, 就得错开执行,不能各设各的值同时跑。
  3. 先设定、再通讯。 串口自己的波特率/校验/协议要用「设定模式」(K1004/K2004/K3004…)先配好, 这个设定会存进设备,掉电不丢;之后换成读写模式才通得起。

设定模式那条指令的四个操作数 ​

MOV K1004 D8126(串口 1)之后执行 DEXTR,四个操作数的含义是:

位置填什么可填的值填错报
1波特率K300 K600 K1200 K2400 K4800 K9600 K19200 K38400 K57600 K76800 K1152006581
2校验K0 无校验 / K1 奇校验 / K2 偶校验6582
3数据位 + 停止位十位是数据位(K7/K8),个位是停止位(K1/K2)→ K71 K72 K81 K826583
4协议 + 从站地址低字节 = 协议号,高字节 = 从站地址。例:K1 = RTU 从机站号 1、H501 = RTU 从机站号 5、H2 = RTU 主机—
  • 协议号那一列的完整对照(还有 DLT645 电表、自由口、AT、MC、N:N、信号板、BACnet MS/TP)见 串口工作模式对照表。
  • 做从机时站号填 0,设备自动按 1 处理。
  • 做 RTU 时第三操作数的数据位不作数:RTU 一律按 8 位数据位收发,所以 RTU 写 K81/K82 就行; K71/K72(7 位)只在做 ASCII 时才有意义。

主站读写那条指令的四个操作数 ​

MOV K2017 D8126(串口 2 · ASCII · 连续)之后执行 EXTR,四个操作数是另一套含义:

位置填什么
1合并字:高字节 = 对面设备的站号,低字节 = MODBUS 功能码。H0103 就是「站号 1、功能码 03」
2对面设备的寄存器地址,报文里的 0 基地址(想读 40001 就填 H0)
3读/写的点数
4本机软元件首址:读回来的写到这里,要写出去的从这里取

常用功能码:H01 读线圈、H02 读离散输入、H03 读保持寄存器、H04 读输入寄存器、 H05 写单个线圈、H06 写单个寄存器、H0F 写多个线圈、H10 写多个寄存器。


一、把串口配成 MODBUS 从站(例程 1~5) ​

场景:对端是触摸屏、仪表、或者另一台 PLC 的主站口,要主动来读/写本机的软元件。 这五条例程结构完全一样,只是串口号、站号、协议不同 —— 挑一条对上您的接线用即可。

例程 1:串口 1 做 RTU 从机,站号 1 ​

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

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

LD    M8002                ; 只在第一个扫描周期执行一次
MOV   K1004 D8126          ; 选「设定串口 1 的工作参数」
DEXTR K9600 K0 K81 K1      ; 9600 · 无校验 · 8N1 · RTU 从机 · 站号 1
  • 要点:M8002 换成 M8000 效果相同(这条指令只在通电的上升沿设定一次),用 M8002 是为了让人一眼看出它只跑一次。
  • 验证方法:拿 USB-485 加 MODBUS 调试工具,或以另一台主站,按 9600/N/8/1、站号 1 发功能码 03, 能读回本机 D 区的值即通。对端地址和本机软元件的对应关系见 Modbus 地址映射。
  • 注意事项:485 总线两端要接 A/B 一致、要有终端电阻;站号冲突时两台从机同时应答,表现为数据时有时无。

例程 2:串口 1 做 RTU 从站,站号 5 ​

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

LD    M8002
MOV   K1004 D8126
DEXTR K9600 K0 K81 H501    ; 高字节 05 = 站号 5,低字节 01 = RTU 从机
  • 要点:站号写在高字节,所以是 H501 而不是 K501。同一根总线上多台 LPPLC 靠这个字节区分。
  • 验证方法:主站分别以站号 1、站号 5 轮询,两台都只在自己的那一次应答。

例程 3:串口 2 做 RTU 从站,站号 2 ​

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

LD    M8002
MOV   K2004 D8126          ; 串口 2 的设定模式是 K2004(把 1004 的千位换成串口号)
DEXTR K9600 K0 K81 H201
  • 注意事项:不是每台机器都有串口 2。只有带对应硬件串口(以及扩展串口板)的机型才认这些值。

例程 4:串口 3 做 ASCII 从站,站号 2 ​

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

LD    M8002
MOV   K3004 D8126
DEXTR K9600 K0 K72 H203    ; 9600 · 无校验 · 7 位数据 2 位停止 · 低字节 03 = ASCII 从机 · 站号 2
  • 要点:ASCII 格式按标准用 7 位数据位,所以这一条填 K72;换 RTU 那套 8 位写法对端会校验错。
  • 注意事项:RTU 和 ASCII 对端必须一致,两者报文完全不同,波特率相同也不通。

例程 5:串口 2 做 RTU 主站 ​

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

LD    M8002
MOV   K2004 D8126
DEXTR K9600 K0 K81 H2      ; 低字节 02 = RTU 主机;主机不用填自己的站号
  • 要点:这一步只是把串口变成「会发主站报文」的状态,真正读什么还要配合下面的连续/脉冲例程。
  • 验证方法:串口接一台已知 good 的从站(仪表或另一台 PLC),跑例程 6 能读到值即为既配好又通。

二、本机做主站,连续刷新(例程 6~7) ​

场景:数据要一直保持最新(比如本机做网关把一台仪表的温度常年在 D 区里刷新)。 「连续」= 指令通电期间一轮一轮地发,不用您给触发信号。

例程 6:串口 2 · ASCII · 连续读站号 1 的保持寄存器 ​

MOV   K2004 D8126          ; 先按例程 5 的路子把串口 2 配成 ASCII 主机
DEXTR K9600 K0 K72 H4      ; 9600 · 无校验 · 7 位数据 2 位停止 · ASCII 主机
MOV   K2017 D8126          ; 改成「串口 2 · MODBUS ASCII · 连续读写」
LD    M8000                ; 运行期间一直刷
EXTR  H0103 H0 K1 D10      ; 读站号 1、功能码 03、从站 0 号寄存器 1 点 → 存进 D10
  • 要点:H0103 是高字节站号 + 低字节功能码;H0 是对面设备的地址(0 基,对应 40001)。
  • 验证方法:改对面设备 40001 的值,看本机 D10 是否跟着变。
  • 注意事项(重要):连续模式要执行的指令条数是在第一个扫描周期统计的。 设备在 RUN 状态时往程序里增删这类指令,统计就和新程序对不上,表现为有的指令永远不发。 改完程序请停止再运行(或重启设备),不要在线追加。

例程 7:串口 3 · RTU · 连续把 D0 写到站号 2 ​

MOV   K3004 D8126          ; 设定串口 3
DEXTR K9600 K0 K81 K2      ; 9600 · 无校验 · 8N1 · RTU 主机
MOV   K3007 D8126          ; 改成「串口 3 · MODBUS RTU · 连续读写」
LD    M8000
EXTR  H0206 K1 K1 D0       ; 站号 2、功能码 06(写单个寄存器)、对面 1 号寄存器、1 点、数据取 D0
  • 要点:功能码 06 只写一个点,所以第三操作数写 K1;本机一侧改 D0 的值,写出去的内容跟着变。
  • 验证方法:改本机 D0,看对面设备 1 号寄存器(40002)是否同步。
  • 注意事项:写类功能码在对面的从站上要有写权限;有些仪表明面上地址对得上但寄存器只读,会回非法数据地址。

三、本机做主站,按节拍触发(例程 8~9) ​

场景:不必每个周期都刷,几秒读一次就够(省总线带宽、也免得对端仪表被问得太频繁)。 「脉冲」= 给一次能流就发一条报文,发完等下一次触发。

例程 8:串口 2 · ASCII · 每秒读一次 ​

MOV   K2018 D8126          ; 「串口 2 · MODBUS ASCII · 脉冲读写」
LD    M8013                ; 1 秒时钟脉冲
EXTR  H0103 H0 K1 D10      ; 同上:读站号 1 的 0 号寄存器 → D10
  • 要点:把例程 6 的 K2017 换成 K2018、M8000 换成 M8013 就是脉冲版;要更慢就用 M8013 驱动计数器或定时器的常开触点。
  • 验证方法:D10 只在秒脉冲的时刻刷新;总线上的报文间隔约 1 秒。
  • 注意事项:触发时如果上一条报文还没发完,这一条会被跳过。波特率低、点数多时更容易出现,把节拍放慢即可。

例程 9:串口 3 · RTU · 每秒把 D0 写过去 ​

MOV   K3008 D8126          ; 「串口 3 · MODBUS RTU · 脉冲读写」
LD    M8013
EXTR  H0206 K1 K1 D0
  • 要点:ASCII 和 RTU 的差别只在模式值的十位(…17/…18 是 ASCII,…07/…08 是 RTU), 串口号和连续/脉冲的差别在千位和个位。
  • 验证方法:见例程 7。

附:带网口的 STM32 版机型用网口跑 MODBUS(例程 10~11) ​

K1004~K5004 管的是串口,K7004~K9004 管的是网口套接字 7 / 8 / 9 —— 这一组只有带网口的 STM32 版机型(LP2252 / LP2250 / LP2229 / LP2222)有实现,其余机型执行会报 6599, 逐格对照见 6.3 D8126 模式表 的「哪些机型有」一栏。

指令还是那两条,只是设定模式下的四个操作数换成另一套含义 —— 不再是波特率,而是「配成什么协议、连到谁」:

位置填什么做服务器时
1工作模式:K0 UDP · K1000 TCP 服务器 · K1002 MODBUS TCP 服务器 · K2000 TCP 客户端 · K2002 MODBUS TCP 客户端 · K2004 HTTP 客户端 · K2005 MQTT生效
2本机端口生效
3对方 IP 的存放起始地址,连读四个字各放一段(D0=192、D1=168、D2=0、D3=200)不作数
4对方端口不作数

第 3 操作数指不到连续四个字时同样报 6583。这条设定会存进设备、掉电不丢,但要求能流一直保持接通, 所以和串口那几条一样挂在 M8000 下。

例程 10:网口 7 做 MODBUS TCP 从站,监听 502 端口 ​

← 进入「设定网口套接字 7」
LD    M8000
MOV   K7004     D8126

← MODBUS TCP 服务器,本机端口 502(后两个操作数这时不作数)
LD    M8000
EXTR  K1002     K502     D0     D4
  • 验证方法:触摸屏或组态软件按 MODBUS TCP 连这台设备的 IP、端口 502, 软元件地址照 1.8 Modbus 地址映射 填。

例程 11:网口 7 做 MODBUS TCP 主站,连 192.168.0.200 的 502 端口 ​

← ① 先把对方的地址备好
LD    M8000
MOV   K192      D0
MOV   K168      D1
MOV   K0        D2
MOV   K200      D3
MOV   K502      D4           ← 对方端口

← ② 把这个套接字配成 MODBUS TCP 客户端,本机端口用 5000
LD    M8000
MOV   K7004     D8126
LD    M8000
EXTR  K2002     K5000    D0     D4

← ③ 换成主站读写模式,之后每周期连续读对方 10 个保持寄存器到本机 D100
LD    M8000
MOV   K7007     D8126
LD    M8000
EXTR  H0103     H0       K10    D100
  • 第 ③ 步的四个操作数含义和串口主站完全一样(见前面「主站读写那条指令的四个操作数」那张表); 换的只是模式值的千位:7 = 套接字 7,8 / 9 类推。
  • 站号照旧填在合并字的高字节(H0103 = 站号 1 · 功能码 03),TCP 帧里它就是单元标识。
  • 要按节拍读写而不是每周期刷,就用脉冲版 K7008,和串口的 K1008 一个道理。
  • 验证方法:先用对方设备的 502 端口确认能建立 TCP 连接,再看本机 D100 是否跟着对方的寄存器变。

模式值怎么读 ​

模式值的排布是有规律的,看懂了不用查表也知道个大概:

  • 千位 = 通道号:1~5 是串口,6 是 CAN 口,7~9 是网口套接字(只有带网口的 STM32 版机型有), 所以 K3018 一定是串口 3 的事。
  • 十位 = 1 表示 ASCII(只有 EXTR 的 MODBUS 读写模式用这一位;0 是 RTU)。
  • 个位(尾号)看是哪条指令,同尾号在不同指令下不是同一件事:
指令用到的尾号
EXTR4 设定通道 · 7 连续读写 · 8 脉冲读写 · 9 自由口 · 19 AT;另有 9996 读写实时时钟、9997 停止运行、9998 清除程序、9999 程序加密、30000~30003 OneNET 手动上送
DEXTR4 设定串口 · 27 电表(DL/T645)连续 · 28 电表脉冲 —— DEXTR 不做 MODBUS 主站读写
ADPRW4 设定通道 · 6 脉冲 · 7 连续(和 EXTR 的尾号含义不同,也没有 ASCII 版);另有 9999/10000/10001/18888/30011
RS0 收发自由口数据;31000~31002 做 16 位 / 32 位 / 浮点数数据变换
  • …7 / …8 的协议跟着通道走:串口上是 MODBUS RTU,网口套接字上是 MODBUS TCP; 十位为 1 的 ASCII 版只有串口用得上。网口套接字那一档再多出 …00 结尾的 MQTT(K7100/K8100/K9100)。

规律只能帮您认,不能帮您猜 —— 哪个通道真的存在这些模式、您这个机型有没有, 一律以 6.3 D8126 模式表 为准:表里查不到这个值, 或者查到了但「哪些机型有」那一栏没列您的机型,执行就是报 6599。


相关文档 ​

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