简介:面向西门子 PLC 工程师与技术维护人员,这份资料针对两台 PLC 分属不同网段时如何借助路由器建立通信展开,完整梳理了从 IP 规划、路由配置到开放式用户通信指令调用的操作流程。压缩包内为 1 个 docx 文档,大小约 1.89MB,将方法、步骤、指令参数与注意事项集中整理,便于按文档逐项落地实施。目前已有 167 人学习下载。文档以 S7-1512SP-1 PN 与 S7-1214C 为例,介绍了设置子网网关、PLC 地址及路由器地址的具体方法,并给出 TSEND_C 与 TRCV_C 的组态要点,包括未指定通信伙伴、使用程序块连接、主动/被动连接端口配置等。同时特别提醒跨网段通信仅适用于开放式用户通信,不适用于 PN IO,若要实现跨网段 PN 通信需增加硬件。对于需要解决跨网段数据交换问题的读者,是一份简洁实用的参考。
1. 西门子PLC跨网段通信:先解决“下一跳”再谈协议
两台西门子PLC,一台在192.168.1.0/24,另一台挂在10.10.0.0/24,用交换机直连,PING不通,博途里也连不上远端站。大多数现场人员第一反应是通信块没写对,反复调整PUT/GET和连接号,问题却始终在IP层:跨网段数据包必须交给路由器,路由表里没有路径,S7协议封装得再标准也过不去。本文围绕西门子PLC通过路由方式实现跨网段通信的全过程,从IP地址、子网掩码、默认网关这些基础配置讲起,再到路由器静态路由、博途S7连接组态和故障抓包,覆盖S7-1200、S7-1500以及存量S7-300/400设备。适合现场做PLC集成、上位机联调和网络改造的工程师参考,让“跨网段通信”不再靠试。
2. 跨网段通信的前提:IP地址、子网掩码与网关
2.1 先搞清为什么“同网段”和“跨网段”走的路不一样
IP通信的第一步是判断目标在不在本地网络。PLC的以太网协议栈拿到目标IP后,会用自己的子网掩码和本地IP做“与”运算,得到本网段地址;再对目标IP做同样的运算,结果相同就发ARP广播,结果不同就把数据包交给默认网关。这个判断发生在TCP/IP层,与PLC品牌无关。所以西门子PLC跨网段通信,首先要保证CPU能正确判断“目标不在本网段”。
现场最常见的做法是PLC地址设在192.168.0.10,触摸屏在192.168.0.11,工程师站也在同一个网段,这种情况下不配网关也能通信。一旦把上位机或者远程IO网段改到10.10.0.0,操作侧不在同一广播域,PLC如果没配网关,它会把发往远端网段的包当成不可达目标直接丢弃。更隐蔽的情况是网关填错:比如PLC的IP是192.168.1.5,路由器接口在192.168.1.1,结果把网关填成了10.10.0.1。PLC在本地广播域里ARP不到10.10.0.1的MAC地址,自然不会把包发出去。因此第一步不是写程序,而是检查CPU接口的“路由器地址”是不是与PLC同网段的真实上一跳。
2.2 博途里给S7-1200/1500设置IP与默认网关
在TIA Portal中,选中CPU的设备视图,在下方的“PROFINET接口”属性中展开“以太网地址”,能看到IP地址、子网掩码和路由器地址三个字段。这里的“路由器地址”就是默认网关。很多项目只填IP和掩码,网关留空,同网段没有问题,跨网段就出状况。设置步骤如下:
- 选中CPU的PROFINET接口;
- 勾选“在项目中设置IP地址”,填入本机PLC的IP和掩码;
- “路由器地址”填与PLC在同一网段的路由器接口IP,例如PLC是192.168.1.5,网关填192.168.1.1;
- 编译下载后,在“在线与诊断”中查看接口状态,确认地址生效。
提示:S7-1200和多数S7-1500 CPU只支持一个默认网关。如果同一个PLC需要访问两个不同网段,不要试图给PLC配置第二个网关,而应该在外部路由器上做静态路由或策略路由。另外,跨网段使用PUT/GET时,两端CPU还要在“属性→防护与安全→连接机制”中勾选“允许来自远程对象的PUT/GET通信访问”,否则路由通了也连不上。
2.3 S7-200 SMART与S7-300/400网关设置的差异
不同PLC系列的网关配置入口差别很大。S7-200 SMART在“系统块→以太网端口”里修改IP、掩码和网关;S7-300/400的PN接口或CP卡在“硬件组态”里双击接口模块找到IP和路由器。用CP343-1或CP443-1时,网关配置在CP卡的属性页里,不在CPU属性里。下表是现场最常用的对应关系:
| PLC系列 | 配置入口 | 网关字段 | 跨网段常用做法 |
|---|---|---|---|
| S7-200 SMART | 系统块→以太网端口 | 网关 | 作为客户端时指向路由器同侧接口 |
| S7-1200 | TIA设备视图→PROFINET接口 | 路由器地址 | 外部路由器或三层交换机做路由 |
| S7-1500 | TIA设备视图→PROFINET接口 | 路由器地址 | 外部路由器或三层交换机做路由 |
| S7-300+CP343-1 | HW Config→CP属性 | Router | 外部路由器为主,CP路由表少用 |
| S7-400+CP443-1 | HW Config→CP属性 | Router | 外部路由器为主,跨网段需路由资源 |
S7-300/400修改CP属性后,整个机架组态会被重新生成,下载时有时要求停机,修改前务必先备份硬件组态。S7-200 SMART则简单很多,改完重启CPU即可。无论哪种型号,网关地址都必须指向与自身同网段的路由器接口,不能指向远端PLC,这是跨网段通信里最容易踩的坑之一。
3. 用路由器把两个网段接起来:拓扑、接口与静态路由
3.1 最小拓扑:一台路由器,两个接口,两张路由表
给一个最常见的现场拓扑:路由器或三层交换机作为核心节点,左侧接口连接192.168.1.0/24,右侧接口连接10.10.0.0/24;左侧接S7-1500(192.168.1.10)和工程师站(192.168.1.100),右侧接S7-200 SMART(10.10.0.20)和触摸屏。两侧PLC的默认网关分别是192.168.1.1和10.10.0.1,也就是路由器各自的接口地址。
路由器会把自己直连的两个网段放进路由表,但跨网段真正的关键是“回程路径”。两侧PLC通过默认网关把包发出去,如果路由器不知道目的网段怎么回,就会丢弃。以左侧PLC发起到右侧PLC的通信为例:左侧把包交给192.168.1.1,路由器查路由表发现10.10.0.0/24是自己的直连网段,于是从右侧接口转发给右侧PLC。右侧PLC回包时,把包交给自己的网关10.10.0.1,路由器查表发现192.168.1.0/24也是直连网段,再转发回来。直连网段之间基本不需要手工静态路由,但一旦引入第三个网段,静态路由就少了不了。
3.2 在路由器上配置接口与静态路由:以Linux工控机为例
现场没有工业路由器时,常见做法是用一台双网卡Linux主机当路由器验证配置。假设eth0接左侧网段,eth1接右侧网段,命令如下:
# 配置eth0接口IP,对应192.168.1.0/24侧 ip addr add 192.168.1.1/24 dev eth0 # 配置eth1接口IP,对应10.10.0.0/24侧 ip addr add 10.10.0.1/24 dev eth1 # 打开IP转发开关,否则Linux不转发跨网段数据包 echo 1 > /proc/sys/net/ipv4/ip_forward # 查看直连路由是否已经自动生成 ip route show第一条和第二条命令分别给两个接口配上IP和掩码,系统会自动生成两条直连路由。第三条命令是Linux转发数据包的总开关,执行后内核才允许把目的地址不是本机的IP包转发出去。最后的ip route show应能看到192.168.1.0/24 dev eth0和10.10.0.0/24 dev eth1两条路由;如果只看到一条,说明有一个接口没有正常UP。
如果远端不是直连网段,而是在另一台路由器后面,就要加静态路由:
# 增加一条到172.16.0.0/24网段的静态路由,下一跳是另一台路由器的接口192.168.1.254 ip route add 172.16.0.0/24 via 192.168.1.254这里的via表示下一跳地址,必须和本路由器直连可达。很多配置失败是因为下一跳填了非直连地址,路由器查不到ARP条目,包只能一直挂在黑洞里。跨网段排错时,务必两端都测:从左侧PC ping右侧PLC,再从右侧设备 ping左侧PC,两边都通才算路由闭环。
3.3 工业路由器/三层交换机的配置差异
西门子SCALANCE X系列中带路由功能的型号,配置思路和Linux一样,只是入口从命令行变成了Web。我一般会先给设备配好管理IP,然后在“Layer 3”或“Routing”菜单里添加静态路由,填目标网络、掩码、下一跳。比Linux多一个关键开关:有些工业设备默认关闭三层路由模式,必须先开启,否则路由表写了也不生效。
三层交换机则常用VLAN接口作为网关。以下是一个常见配置片段:
# 创建VLAN10并配置接口IP,用于左侧网段 interface vlan 10 ip address 192.168.1.1 255.255.255.0 no shutdown # 创建VLAN20并配置接口IP,用于右侧网段 interface vlan 20 ip address 10.10.0.1 255.255.255.0 no shutdown # 开启三层交换机的IP路由转发 ip routinginterface vlan是三层接口,ip routing与Linux的ip_forward作用一样。需要注意物理端口要划分到对应VLAN,否则PLC和上位机还是在默认VLAN1里,路由配置得再正确也接不到正确网段。三种平台配置对比如下:
| 平台 | 直连网段路由 | 非直连网段路由 | 关键开关 |
|---|---|---|---|
| Linux主机 | 自动生成 | ip route add | ip_forward |
| SCALANCE X | 自动生成 | Web静态路由表 | 三层路由模式 |
| 三层交换机 | VLAN接口自动生成 | ip route或静态路由表 | ip routing |
4. PLC程序里的跨网段通信实现:PUT/GET连接参数与调用示例
4.1 为什么跨网段首选PUT/GET
西门子PLC之间跨网段通信,常见方案有PUT/GET、开放式以太网TCP、ISO-on-TCP等。PUT/GET由S7协议封装,通信双方不需要自己处理socket、握手和报文拆分,直接调用系统功能块SFB15/SFB14即可。跨网段场景下,IP层的路径由路由器和默认网关负责,PLC只需要配置正确的连接ID和伙伴IP。先别急着写通信块,先确认两端CPU都勾选了“允许来自远程对象的PUT/GET通信访问”,否则连接建立了,数据读写也会被拒绝。
4.2 在博途里组态S7连接并指定远端IP
在TIA Portal项目树的“网络视图”里把两个PLC拖到同一张图上,右键选择本地PLC,新建S7连接。伙伴选择“未知”,在连接属性里填写远端PLC的真实IP。跨网段的关键就在这里:伙伴IP填远端PLC的实际地址,例如10.10.0.20,而不是路由器地址。本地连接属性会自动分配一个“本地ID”,后续调用PUT/GET时要保持一致,我一般习惯把ID记成十六进制,比如1对应16#0001。
可复现的组态步骤:
- 网络视图中在本地PLC连接表新建S7连接;
- 伙伴选择“未知”,地址填远端PLC的IP;
- 连接方式选“S7 connection”,记录本地ID;
- 在两端CPU的“连接机制”中勾选允许PUT/GET访问;
- 编译下载后,先在两个CPU之间测试连接诊断。
连接建立后,跨网段路径上只要PING通,S7连接通常没问题。连接失败时先查路由器回程,不要反复改连接参数。
4.3 调用PUT功能块的STL示例与参数表
下面是一个典型示例:S7-1200作为客户端,把本地DB20的100字节写到远端PLC的DB10。使用STL调用SFB15“PUT”:
CALL "PUT", "PUT_DB" REQ := #sendTrigger // 上升沿触发发送 ID := 1 // TIA连接组态里的本地ID ADDR_1 := P#DB10.DBX0.0 BYTE 100 // 远端PLC的DB10起始100字节 SD_1 := P#DB20.DBX0.0 BYTE 100 // 本地DB20起始100字节 DONE := #done // 发送成功标志 ERROR := #error // 错误标志 STATUS := #status // 错误码"PUT_DB"是SFB15的背景数据块,在TIA中调用时自动生成。REQ需要边沿触发,不要在OB1里每个周期都给TRUE,否则会产生大量通信任务。ID必须和连接组态的本地ID一致,不一致时STATUS字会提示连接号错误。P#DB10.DBX0.0 BYTE 100是Any指针,要注意显式写“BYTE 100”,如果只写地址不写长度,访问位和字节的长度处理不同,容易报参数错误。
GET调用格式与PUT类似,只是数据方向相反:
CALL "GET", "GET_DB" REQ := #readTrigger ID := 1 ADDR_1 := P#DB10.DBX0.0 BYTE 100 // 远端PLC的DB10起始100字节 RD_1 := P#DB20.DBX0.0 BYTE 100 // 本地DB20起始100字节,存放读回内容 DONE := #done ERROR := #error STATUS := #statusGET读远端数据到本地,ADDR_1指向远端地址,RD_1指向本地接收区,方向千万别搞反。通信过程中,新增通信任务前先判断DONE和ERROR,上一次请求没有结束时,不要给REQ新的上升沿,这是S7通信任务并发冲突的常见原因。
4.4 PUT/GET跨网段通信的带宽与资源建议
PUT/GET的数据量受CPU通信资源限制,S7-1200能同时维持的连接数和每个任务的字节数都比S7-1500低一些,具体上限以CPU技术手册为准。跨网段时,建议加一个发送定时器,例如每100ms触发一次,不要把通信周期压到几毫秒。跨网段链路上往往还有工业路由器、光电转换器,短报文过多会让设备负载升高。另一个建议是把通信数据集中放在一个DB里,使用相同长度的数据块,减少ADDR_1参数里的Any指针修改频率,方便后续维护。
5. 故障诊断:从PING到Wireshark抓包,排掉常见的路由坑
5.1 分三层验证跨网段通透性
跨网段通信出问题,先别怀疑PLC程序。我一般的验证顺序是:先用工程师站PING路由器两个接口,再PING远端PLC。假设本机IP是192.168.1.100,本侧网关192.168.1.1,远端网关10.10.0.1,远端PLC是10.10.0.20:
ping 192.168.1.1 ping 10.10.0.1 ping 10.10.0.20第一个PING不通,检查本机到网关的物理链路;第二个不通,说明路由器到右侧网段的接口或链路有问题;第三个不通,再看路由器静态路由和远端PLC的网关配置。三个都通,再检查博途连接和PUT/GET访问开关。这组命令能快速把故障范围从“整个跨网段通信”缩小到某一层,减少盲目重配参数的时间。
5.2 在路由器上检查转发状态
以Linux路由器为例,跨网段PING不通时,在路由器上执行:
# 查看当前路由表,确认两个网段都在 ip route show # 查看ARP表,确认是否解析到两侧PLC的MAC地址 arp -n # 确认IP转发是否已经开启,1表示开启 cat /proc/sys/net/ipv4/ip_forwardip route show应能看到至少两条直连路由;如果只有一条,接口IP没配成功。arp -n能看到路由器每个接口解析到的MAC;如果站点PING不通,对应ARP条目不会出现,说明设备之间链路层没有建立。ip_forward输出必须是1,如果重启后变回0,要把配置写进/etc/sysctl.conf。
5.3 抓包确认数据包是否到达远端接口
路由表和ARP都正常,但S7连接还是建立不了,就需要抓包。在路由器远端接口上监听TCP 102端口:
# 在eth1上监听所有访问S7协议端口102的TCP流量 tcpdump -i eth1 tcp port 102 -n此时在本地PLC侧触发一次PUT/GET,观察eth1上是否有TCP SYN包到达。没有SYN,说明包在去程丢了,问题在本侧网段到路由器的路径;有SYN但没有SYN-ACK,说明远端PLC收到了连接请求但没回包,重点检查远端PLC是否勾选允许PUT/GET、远端PLC的默认网关是否正确。用Wireshark在工程师站抓包也可以,过滤器写tcp.port == 102,关注三次握手是否完整。跨网段S7通信中,只出现SYN没有SYN-ACK,绝大多数是回程路由缺失或远端PLC保护机制拦截。
5.4 三个常见误配置对照
| 现象 | 为什么 | 怎么修正 |
|---|---|---|
| PING不通跨网段PLC,但PING通本侧网关 | 路由器缺远端网段回程路由 | 在路由器上加静态路由,下一跳指向对应接口 |
| PING通PLC,但博途连不上 | 未允许PUT/GET访问 | 在两端PLC属性中勾选允许PUT/GET |
| 通信时通时断,重启后恢复 | 默认网关冲突或路由表环路 | 检查是否有其他设备宣告相同网段,使用静态ARP固定PLC地址 |
6. 进阶:用静态路由冗余和心跳探测让跨网段通信更稳
6.1 给跨网段加一条备用路径
单台路由器是跨网段通信的单点,现场常见做法是用两台路由器把两个网段连起来,一台做为主路径,一台作为备用路径。Linux下可以通过metric参数配置两条到同一目标网段的静态路由:
# 主链路:下一跳为192.168.1.2,优先级高 ip route add 10.10.0.0/24 via 192.168.1.2 metric 10 # 备用链路:下一跳为192.168.1.3,优先级低 ip route add 10.10.0.0/24 via 192.168.1.3 metric 20metric越小优先级越高,主链路不可达时,Linux会尝试使用metric更大的备用路由。不过Linux静态路由不会自动探测下一跳的存活状态,实际项目中我建议用三层交换机的VRRP或工业路由器的冗余协议,切换速度比纯静态路由更快。配置完成后的验证方式是:持续PING远端PLC,拔掉主链路网线,观察丢包数量和通信恢复时间,恢复时间太长就需要检查PLC侧连接是否允许断开重连。
6.2 用心跳计数监控跨网段通信质量
跨网段通信往往不止用一次,平时看似正常,半夜偶发一次超时就被忽略。一个具体做法是:在远端PLC里放一个心跳字,本地PLC周期通过GET读取该值,连续读取失败超过N次就置位报警位。以下逻辑片段用SCL实现:
// 每500ms触发一次GET读取远端心跳字 IF #hbDone THEN #failCount := 0; // 读取成功,清空失败计数 ELSIF #hbErr THEN #failCount := #failCount + 1; // 读取失败,累加 IF #failCount >= 5 THEN #commAlarm := TRUE; // 连续5次失败,确认通信中断 END_IF; ELSE #failCount := #failCount + 1; IF #failCount >= 5 THEN #commAlarm := TRUE; END_IF; END_IF;这段逻辑的关键是“连续失败计数”而不是单次失败,因为跨网段偶尔丢一两个包是正常的,连续5次基本能确认链路中断。#commAlarm置位后可以送到HMI报警区,也可以通过MODBUS TCP或SNMP转发给上级系统。最后要说的是,跨网段通信排错一定要画一张“去程/回程”路径图,标出每个节点的IP、网关和路由下一跳,大多数疑难问题都出在回程路由不对称上,画图比猜更有效。
本文还有配套的精品资源,点击获取