西门子PLC TCP通讯测试与故障排查实战指南 写这个系列的时候我就说过搞西门子PLC的TCP通讯最磨人的不是写指令而是看起来啥都配好了却死活ping不通、连不上、数据出不来的时候根本不知道问题到底出在哪一层。前面两篇分别讲了TCP通讯的基础原理和不同项目下的组态思路这篇就专门把“TCP测试”这件事掰开揉碎说清楚从最底层的物理链路排查到指令级的联调验证再到各种奇奇怪怪的报错怎么定位整个流程走一遍。这篇适合正在做S7-1200/1500之间或PLC与上位机TCP通讯、卡在联调阶段的人也适合刚入门想搞懂“通讯到底通没通”的新手。1. 不同项目下TCP通讯的整体思路与准备工作1.1 为什么是“不同项目下”以及连接模式的选型先解释一下标题里“不同项目下”这五个字很多人看到这个表述会懵。常规做法是两台PLC在同一个TIA项目里做硬件组态组态一个S7连接或者TCP连接然后调用通讯指令这种情况其实不需要你手动去管连接参数组态工具已经帮你规划好了。但实际工程里更常见的是两台S7-1200/1500分别属于不同的电柜、不同的分包商各用各的TIA项目根本没有办法统一组态。这时候就要靠TSEND_C和TRCV_C这类指令自带的连接参数来工作双方约定好IP、端口和连接ID各写各的程序只要网络能通数据就能传。这种模式下最关键的是确定谁主动建立连接。TCP通讯本质上是客户端/服务器模型主动发起连接的一方叫Active被动等待的一方叫Passive。在指令参数里对应的是ActiveEstablishment这个选项主动端选Active被动端选Passive。这里建议把能确定IP的一端设为主动端比如PLC主动去连上位机软件因为上位机软件作为服务器监听端口更容易实现两台PLC之间通讯则建议把上电较早、程序逻辑更简单的一端作为主动端主动端会不断尝试建立连接直到成功为止被动端只需要让TRCV_C一直处于使能状态就行。1.2 测试前的硬件与软件准备工作我见过太多人一上来就写程序连CPU型号和固件版本都不确认结果指令都调不出来。做TCP通讯测试前先把下面这几样东西准备好两台S7-1200或S7-1500 CPU不同系列混搭也没问题比如1200和1500之间通讯完全可以固件版本建议V4.0以上越新越好老固件在TCP指令上的功能差异比较大一台普通交换机完全不需要管理型交换机TCP通讯走的是标准以太网傻瓜交换机足够至少一台电脑装好TIA Portal版本建议V15.1以上同时装好对应的仿真软件如果你要用PLCSIM做纯软件测试的话TCP调试助手工控圈最常用的是NetAssist和SocketTool二选一就行网线若干最好带水晶头屏蔽线虽然TCP对网线要求不高但现场环境干扰大的时候劣质网线的丢包问题会把你折磨到怀疑人生另外特别提醒一句如果要测试的程序还没下载到真实PLC里想用PLCSIM先模拟跑一下TCP通讯要注意PLCSIM对TCP的支持是有限制的。PLCSIM V15以上版本支持S7-1200/1500的TCP指令仿真但是你能不能从电脑上的调试助手去连一个PLCSIM仿真出来的PLC这跟你电脑的虚拟网卡配置有关系配置起来比较麻烦而且经常出现仿真能通、真机不通或者反过来仿真不通、真机能通的情况。我的建议是TCP通讯这玩意一旦程序逻辑写得差不多了直接上真机测试别在仿真上耗费太多时间仿真的价值在逻辑验证不在通讯验证。1.3 网络规划与IP地址分配网络规划这块看着简单实际错的人最多。TCP通讯的两台设备要想通信最基本的要求是处于同一个广播域内也就是IP地址在同一个网段子网掩码一致。常见错误是PLC配了192.168.1.10电脑配了192.168.2.5两个IP不在同一个网段又不经过路由器那肯定是PING不通的。现场测试时我一般建议用固定IP别用DHCP。PLC作为工业设备必须用固定IP这个没有争议电脑和调试助手这边也要手动指定一个跟PLC同一个网段的静态IP比如PLC是192.168.1.10电脑就设192.168.1.100掩码统一255.255.255.0网关可以留空不填因为同一个网段内通讯根本不经过网关。还有一点如果网上挂着其他设备比如无线AP、工控机、HMI要注意IP不能冲突。我遇到过最尴尬的情况是调试到一半突然发现有一台手机连了现场WiFiIP地址刚好跟PLC重了结果整个网络瘫痪了大半天。后来我学乖了每次到现场第一件事就是用Advanced IP Scanner把整个网段扫一遍确认没有占用再往下走。2. 通讯核心TSEND_C与TRCV_C指令的参数详解2.1 指令的本质与工作原理TSEND_C和TRCV_C这两个指令是西门子专门为开放式TCP通讯提供的简化接口。它们把传统S7通讯里那套TCON、TSEND、TDISCON单独调用的复杂流程封装到了一起从使用者的角度看一个指令就能完成连接建立、数据发送、连接断开三个动作。用TSEND_C举例它的内部状态机大致是首次调用时如果检测到没有建立连接会自动根据连接参数去发起TCP连接连接建立成功之后每次REQ信号从0变1就触发一次数据发送如果连接中途断了它会自动尝试重连。这些过程在后台都处理好了我们只需要关注外部管脚就行。TRCV_C同理只要EN_R一直为TRUE它就会持续监听端口一旦有数据到来就放进接收缓冲区并通过NDR信号告诉程序“有新数据到了”。这个封装在提升易用性的同时也带来了一个问题很多初学者把指令当黑盒遇到问题不知道从哪下手。实际上理解指令内部状态转换对排查故障特别有用。比如TRCV_C的STATUS返回7002意思是连接还没建立这时候数据当然传不过来问题就出在对方或者网络链路上而不是指令本身。2.2 连接参数的设置方法不同项目下使用TSEND_C/TRCV_C最核心的连接参数就在指令的属性面板里。在TIA Portal中插入指令后点击指令上方的“连接参数”按钮可以看到一个参数表关键项有这么几个Endpoint对方的IP地址也就是你通信对端的IP这个必须跟对端实际配置完全一致否则连接永远建立不了Partner port对方的端口号这个端口号要跟对端程序里设置的本地端口号相同比如主动端设置Partner port为2000被动端的本地端口就必须是2000Local port本地端口主动端可以选择不指定让系统自动分配被动端必须指定一个固定端口因为主动端要连的就是这个端口ActiveEstablishment选择Active表示主动连接选择Passive表示被动监听端口号的选择有一点要注意避免使用常见服务的默认端口比如80、8080、21这些避免跟现场其他软件冲突。工控通讯约定俗成一般用102S7协议、2000、2001、5001这类端口其实没有什么硬性规定只要双方约定一致就行。另外如果被动端和多个主动端都要通讯那每个连接对应不同的连接ID和本地端口不能共用一个被动端口否则数据会串台。2.3 连接ID的分配规则与数据缓冲区设计连接ID也就是指令上的ID管脚在同一个CPU内部必须唯一不同的连接需要分配不同的ID。这个ID并不需要在两个CPU之间一致只是用来在CPU内部区分是哪条连接。不同项目下双方各自定义自己的ID就行比如A站用ID1B站只要自己的程序里没有其他连接占用ID1它也可以用ID1两边互不影响。数据缓冲区这块就更有讲究了。TSEND_C的DATA管脚指向发送数据区TRCV_C的DATA管脚指向接收数据区。我最常用的做法是单独建一个全局数据块DB块比如DB_Com_Send和DB_Com_Recv里面定义好字节数组或者结构体然后让指令的数据指针指向这个DB。这样做的好处是监控方便在线表里直接看数组的值就知道数据对不对程序可读性好别人拿到你的程序打开DB一看就知道通讯数据结构长什么样。缓冲区大小要根据实际数据量来定不宜过大也不宜过小。S7-1200的TCP通讯单次发送的数据长度有限制一般是8KB左右S7-1500能做到更大。但实际工程中没人会一次发那么多数据都是按需求组帧比如每次发送50个字节、100个字节这样即使网络有瞬时抖动重发成本也低。2.4 字节序问题大小端的坑这是TCP通讯里最常见也最隐蔽的坑。西门子的PLC包括S7-1200/1500在MODBUS TCP等协议里遵循大端字节序但在开放式TCP通讯里你往发送缓冲区里丢什么它就发什么不会自动转换字节序。问题通常出现在PLC跟PC上位机通讯的时候PC的x86架构是小端PLC存储的大小端习惯跟PC不一样如果你在PLC里组了一个结构体包含一个INT类型变量值为0x0102然后在PC端用字节流解析收到的数据你会发现收到的两个字节可能是0x02、0x01的顺序这样解析出来的数值就不对了。解决方法是双方约定好字节序通常是在上位机端转换或者在PLC端组帧时手动调整。如果不想这么麻烦发送和接收都统一用字节数组然后自己拼接解析这样最不会出错也最容易排查。这个在后面测试环节里我会再演示一遍。3. 实操过程从PING通到程序级联调3.1 第一步网络连通性测试不管你多急着写程序TCP通讯测试的第一步永远是PING。先用网线把PLC和电脑接到同一个交换机上然后把电脑IP改成跟PLC同一个网段。很多人会忽略一个细节改完IP之后一定要在命令行里执行ipconfig确认一下修改生效了因为Windows有时候会同时开启两个网卡一个连外网一个连PLC系统的路由表会优先走有默认网关的那个网卡导致你PING PLC的时候数据包从另一个网卡出去了。确认IP没问题之后打开命令行输入ping 192.168.1.10 -t如果通会持续返回TTL响应。这里要注意观察TTL值西门子PLC的TCPIP协议栈TTL一般是64或者128如果看到TTL特别大比如255那说明中间隔了路由器或者NAT设备这种网络环境做TCP通讯会有额外的不确定性最好避免。如果PING不通从这几个方向排查网线插好没有交换机的指示灯亮不亮PLC的网口有没有被禁用电脑的防火墙有没有拦截ICMP回显。Windows防火墙默认会拦截PING请求但不一定拦截TCP连接有时候出现PING不通但TCP连接能建立的情况。反过来也有PING通但TCP端口连不上的情况。所以PING通了只代表链路层通不代表应用层能用PING不通也不代表TCP连不上。PING只是第一道筛查手段。3.2 第二步PLC与电脑调试助手的端到端测试链路通了之后先别急着两台PLC联调拿电脑上的TCP调试助手做中间验证这样你能清楚地看到数据内容排查起来比两台PLC对着调要快得多。测试场景一电脑做服务器PLC做主动端打开NetAssist协议类型选TCP Server本地端口填2000点击启动监听。然后写一个最简单的PLC测试程序用TSEND_C主动去连电脑连上之后每秒钟发送一次固定字符串。PLC端程序就三行逻辑一个1Hz的时钟脉冲作为REQ触发TSEND_C指令的连接参数填电脑的IP比如192.168.1.100和端口2000ActiveEstablishment选ActiveDATA指向一个包含20个字节的发送DB。按下启动按钮后观察电脑上的NetAssist窗口如果收到了来自PLC的数据说明PLC作为TCP客户端的逻辑完全正确。这个测试的价值在于把问题范围缩小到PLC单个方向如果电脑上收到了数据至少证明PLC侧的指令配置、连接建立、发送逻辑、数据内容都没问题。那么接下来要做的就是验证接收方向。测试场景二电脑做客户端PLC做被动端在PLC里写一个TRCV_C指令连接参数里ActiveEstablishment选Passive本地端口设为2000EN_R置TRUE数据区指向接收DB。然后电脑上的网络调试助手切到TCP Client模式远程IP填PLC的IP远程端口填2000点击连接。连上之后往里面发送一串字符观察PLC接收DB里的字节变化。如果数据能出现在接收DB里说明PLC作为TCP服务器的逻辑也通了。两个场景都跑通之后PLC跟电脑之间的TCP通讯就算彻底打通了接下来再去调两台PLC之间的通讯就轻松很多。3.3 第三步两台PLC程序级联调两台PLC联调前先在纸上或者记事本里约定好这些参数A站IP、B站IP、A站本地端口、B站本地端口、连接ID、数据帧格式、发送周期。双方程序写完分别下载到各自的CPU里。假设要做A站主动、B站被动。A站程序TSEND_CID1主动模式Partner端口指向B的2000DATA指向SendDB用1Hz脉冲触发。B站程序TRCV_CID1被动模式本地端口2000EN_R常ONDATA指向RecvDB。关键点来了分别打开两个PLC的在线监控同时看两侧的DB和指令状态。这也是“不同项目下”联调比较麻烦的地方——你没法在一个TIA项目里同时看到两台PLC的在线状态除非开两个TIA实例或者两台电脑。我通常的做法是一个工程师同时开着两个TIA项目窗口左边看A站发送DB右边看B站接收DB两边比对数据。联调时先看指令的Status状态字A站TSEND_C如果Status为0DONE周期性地为TRUE说明发送正常B站TRCV_C的Status为0NDR出现脉冲说明接收正常。数据内容对比A站SendDB里填一个标志数比如DB_Com_Send.Data[0] : 16#A5B站RecvDB对应位置能不能出现16#A5。能出现数据传输就打通了。3.4 第四步数据一致性验证这一步很多人不做但我强烈建议做。单纯传一个固定值不能证明通讯的可靠性真正到了现场网络有干扰、缓冲区有错位、两边扫描周期不同步都会导致数据异常。数据一致性验证的方法很简单发送端做一个计数器每发送一帧数据计数值加1同时把计数值填进数据帧的固定字节里接收端连续接收检查收到的计数值是不是连续的、有没有跳号、重号。我常用的验证帧结构是64个字节前4个字节放计数器中间放固定的同步字比如16#5354是ST的ASCII码后面填充递增或者递减的数据序列。接收端检查同步字来判断帧是否对齐检查计数器来判断有没有丢帧检查数据序列来判断有没有乱序。这个验证方法可以帮你发现很多隐蔽问题数据错位如果同步字跑到了错误的位置说明你的接收缓冲区和实际数据帧没有对齐多半是数据帧长度定义不一致数据跳号计数器出现跳号说明RS485式的链路层重传或者网络丢包TCP不会出现这种问题但如果计数器是累加的而且跳号了就要检查是不是发送端本身逻辑有问题数据串位数据序列跟预期不匹配可能是对端PLC的数据区内有另外一个程序在写同一个地址我这套方法用了很多年每次做新的PLC通讯项目都会先用这种方法把链路质量测一遍心里有底了再上正式的业务逻辑。4. 常见问题与排查技巧实录4.1 连接建立不了8180错误深度解析8180可能是最多人遇到的错误代码对应的信息是“连接建立失败”。这个错误字面上是TCP三次握手没有完成也就是主动端发出了连接请求但对端没有正确响应。排查这个错误有一个固定的思路先确认网络通不通用电脑PING对端PLC地址如果不通回到链路层排查确认对端程序在跑如果对端是PLC检查它的TRCV_C或TSEND_C指令所在的程序块有没有被调用是不是在OB1里是不是被条件跳过了。我遇到过一个案例对方把通讯指令放在一个FC里而这个FC只在某个特殊模式下才执行平时根本不在OB1调用链里那你这边再主动也连不上确认端口号一致主动端填的Partner端口必须跟被动端Local端口一致差一个数字都连不上确认防火墙电脑Windows防火墙默认会拦截外部TCP连接如果你用电脑做服务器记得在防火墙添加入站规则放行对应端口。工控机如果装了什么安全软件也先暂时关掉再测确认IP地址没有冲突之前用Advanced IP Scanner扫一遍确认没有第二台设备占用相同的IP按照这个顺序查80%的8180都能解决。剩下20%是那种诡异情况比如PLC的以太网口被配置成了两个IP或者对端PLC把连接数占满了S7-1200一般支持8到16个连接看固件型号这种只能慢慢深入排查。4.2 连接能建立但数据收发不正常连接建立成功说明TCP层没问题这时候数据出不来的问题通常出在指令调用和缓冲区上。TSEND_C的发送条件是REQ上升沿很多人直接在REQ上挂一个常TRUE以为会持续发送实际上REQ只会在第一次扫描时产生一个上升沿之后就一直保持TRUE不再触发新的发送。正确做法是用一个定时脉冲比如1Hz时钟位去触发REQ每次上升沿发送一帧。还有一种情况是DONE信号一直不出现说明发送请求没有完成。检查DATA指针指向的数据区长度够不够LEN参数填的长度有没有超过缓冲区。西门子S7-1200对TCP发送缓冲区最大限制大约8KB如果你填的LEN超过了上限指令会报错。接收方向最常见的错误是EN_R没有使能。很多人写TRCV_C的时候EN_R忘记接TRUE或者只在程序启动时给了一个短脉冲导致后续数据永远进不来。TRCV_C的EN_R必须保持TRUE才能持续监听。4.3 通讯时断时续时断时续这种问题最恶心因为不是每次都出现很难抓现场。根据经验通讯断断续续的主要原因有三个一是网络环境问题。现场有大功率电机、变频器启动时会对网线产生干扰尤其是屏蔽层接地不良的网线。排查方法用笔记本电脑在PLC旁边PING一下另一端的IP如果PING的丢包率在设备启动时明显上升基本就是网络干扰问题换好一点的屏蔽网线、把网线走向远离动力电缆能改善很多。二是通讯双方的程序扫描周期差异导致缓冲区溢出。比如发送端一个周期发一帧64字节接收端扫描周期比发送端长接收缓冲区如果设计得太小比如只有64字节下一帧数据到的时候上一帧还没被程序处理完缓冲区就会被覆盖或者丢弃。解决办法是把接收缓冲区设成数据帧长度的整数倍比如接收DB定义成10个64字节的数组程序每扫描一次取一个最新帧处理。三是连接被意外重置。有时候对端PLC的通讯指令所在的程序块出了问题重启了或者CPU从RUN切到STOP再切回RUN原来的TCP连接就断了。TSEND_C和TRCV_C有自动重连功能但重连需要几秒时间从使用者角度看就是“断了一下又自己好了”。如果业务要求不能断就要考虑用S7通讯如果两台都是西门子PLC或者做看门狗检测持续几十毫秒没收到数据就报警。4.4 8180之外的其他错误代码速查这里整理一份我在现场最常遇到的STATUS错误代码建议收藏到手机里到了现场照着查错误代码含义处理建议16#0000无错误正常16#7002连接未建立检查主动端是否在持续重连检查网络路径16#8180连接建立失败按上一节顺序排查16#8204连接中断对端关闭了连接检查对端程序是否有断开逻辑16#8206非法地址DATA指针指向的地址无效检查DB号是否正确16#8088指令配置错误检查LEN是否超出限制指令实例是否正确分配背景DB16#809C功能不受支持固件版本过低升级固件或者换用其他指令4.5 安全与稳定性注意事项最后再啰嗦几句TCP通讯测试打通只是第一步真正上线跑长期稳定性才是关键。几个经验点通讯数据帧里最好带上功能码、计数器、校验码不要裸发业务数据这样排查问题时有依据程序里对通讯状态做监控长时间没收到对端数据要触发报警不要让设备在“通信失效”的状态下继续运行太危险不要把所有的通讯逻辑写在循环中断里循环中断如果执行时间过长会触发监控错误严重时直接导致CPU停机如果PLC要同时跟多个设备通讯规划好连接ID和本地端口做好文档记录不然半年后你自己都不知道哪个端口对应哪台设备按照这套思路从物理链路到应用层一层一层剥开测PLC的TCP通讯其实没有那么玄乎。说白了TCP就是一个可靠传输管道你要做的就是确认管道两头都接对了数据格式都统一了剩下的事情协议栈会帮你搞定。踩过几次坑之后我现在做通讯项目都习惯先把测试环境和步骤写清楚再动手写业务逻辑这样后续出了问题自己排查起来也省很多时间。