主题
MODBUS 串口通讯例程
用梯形图把本机的 RS-485 串口配成 MODBUS 从站(让其他设备读取本机),或者配成主站去读别的设备。 先给 9 段串口例程,再附 2 段带网口的 STM32 版机型用网口跑 MODBUS TCP 的例程。 下面所有模式值都按本机实际能跑通的写法给出;如果您手上还留着更早版本的纸质手册, 其中串口 3 的两处模式值(印的是
K2007/K2008)是串口 2 的值,照本页写即可。
返回 例程总览。
动手前先记住三件事
MOV一条 + 通讯指令一条,成对出现。 EXTR / DEXTR / ADPRW 自己不带功能编号,做什么由D8126决定。 设备支持的每一个模式值、以及它在哪款机型上有,全列在 6.3 D8126 模式表。 您这台机型没有的那一档执行会报 6599 —— 最容易碰到的是K7004~K9004网口套接字那一组,它只有带网口的 STM32 版机型有。D8126是全局的一个寄存器。 程序里所有这几条指令共用它 —— 一个扫描周期里要让同一条指令做两件事, 就得错开执行,不能各设各的值同时跑。- 先设定、再通讯。 串口自己的波特率/校验/协议要用「设定模式」(
K1004/K2004/K3004…)先配好, 这个设定会存进设备,掉电不丢;之后换成读写模式才通得起。
设定模式那条指令的四个操作数
MOV K1004 D8126(串口 1)之后执行 DEXTR,四个操作数的含义是:
| 位置 | 填什么 | 可填的值 | 填错报 |
|---|---|---|---|
| 1 | 波特率 | K300 K600 K1200 K2400 K4800 K9600 K19200 K38400 K57600 K76800 K115200 | 6581 |
| 2 | 校验 | K0 无校验 / K1 奇校验 / K2 偶校验 | 6582 |
| 3 | 数据位 + 停止位 | 十位是数据位(K7/K8),个位是停止位(K1/K2)→ K71 K72 K81 K82 | 6583 |
| 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)。 - 个位(尾号)看是哪条指令,同尾号在不同指令下不是同一件事:
| 指令 | 用到的尾号 |
|---|---|
| EXTR | 4 设定通道 · 7 连续读写 · 8 脉冲读写 · 9 自由口 · 19 AT;另有 9996 读写实时时钟、9997 停止运行、9998 清除程序、9999 程序加密、30000~30003 OneNET 手动上送 |
| DEXTR | 4 设定串口 · 27 电表(DL/T645)连续 · 28 电表脉冲 —— DEXTR 不做 MODBUS 主站读写 |
| ADPRW | 4 设定通道 · 6 脉冲 · 7 连续(和 EXTR 的尾号含义不同,也没有 ASCII 版);另有 9999/10000/10001/18888/30011 |
| RS | 0 收发自由口数据;31000~31002 做 16 位 / 32 位 / 浮点数数据变换 |
…7/…8的协议跟着通道走:串口上是 MODBUS RTU,网口套接字上是 MODBUS TCP; 十位为1的 ASCII 版只有串口用得上。网口套接字那一档再多出…00结尾的 MQTT(K7100/K8100/K9100)。
规律只能帮您认,不能帮您猜 —— 哪个通道真的存在这些模式、您这个机型有没有, 一律以 6.3 D8126 模式表 为准:表里查不到这个值, 或者查到了但「哪些机型有」那一栏没列您的机型,执行就是报 6599。