C#跨平台上位机Windows/Linux双端跑通:S7-1200 PLC通信全攻略

📅 发布时间:2026/7/7 22:08:27 👁️ 浏览次数:
C#跨平台上位机Windows/Linux双端跑通:S7-1200 PLC通信全攻略
大家好我是威哥。最近在做一个工业视觉项目现场要求上位机既能在Windows上跑又能在Linux工控机上运行还得和S7-1200 PLC稳定通信。折腾了一周踩了不少坑终于把双端都调通了。今天把整个过程整理出来希望能帮到有同样需求的朋友。一、为什么选这个方案先聊聊背景。工业现场现在越来越多Linux设备成本低、稳定性好但很多工程师还是习惯用C#开发上位机。好在.NET Core/.NET 5已经完全跨平台配合成熟的S7通信库完全能满足需求。我这次的需求很明确读写S7-1200的DB块、I区、M区Windows 10/11和Ubuntu 22.04双端稳定运行代码尽量简洁方便后续维护二、环境准备踩坑从这里开始2.1 硬件与软件清单先列一下我用的环境大家可以参考PLCS7-1214C固件版本V4.4开发环境Windows 11 Visual Studio 2022Linux环境Ubuntu 22.04 LTS虚拟机/工控机都行.NET版本.NET 8 SDK长期支持版稳定通信库S7netplusGitHub上最火的S7通信库没有之一2.2 PLC端必须做的设置很多人一开始连不上PLC都是因为这里没设对。用TIA Portal打开你的项目检查这几点IP地址设置确保PLC和电脑在同一网段比如我设的是192.168.0.1。启用PUT/GET通信在PLC属性里找到“保护与安全”→“连接机制”勾选“允许来自远程伙伴的PUT/GET通信访问”。DB块设置如果要读写DB块记得把DB块的“优化的块访问”关掉在DB块属性里取消勾选否则S7netplus读不到。三、核心代码实现Windows先跑通我习惯先在Windows上把通信调通再移到Linux这样能排除平台差异的干扰。3.1 新建项目并安装依赖打开VS2022新建一个.NET 8控制台应用名字随便起比如S7CrossPlatformDemo。然后通过NuGet安装S7netplusInstall-Package S7netplus3.2 写一个简单的通信测试类直接上代码我加了详细注释都是踩坑后总结的usingS7.Net;usingSystem;namespaceS7CrossPlatformDemo{classProgram{// PLC实例IP地址、机架号、槽号S7-1200一般是0和1staticPlcplcnewPlc(CpuType.S71200,192.168.0.1,0,1);staticvoidMain(string[]args){Console.WriteLine( S7-1200 跨平台通信测试 );try{// 1. 连接PLCConsole.WriteLine(正在连接PLC...);plc.Open();if(plc.IsConnected){Console.WriteLine(✅ PLC连接成功);// 2. 测试读写TestReadWrite();}else{Console.WriteLine(❌ PLC连接失败);}}catch(Exceptionex){Console.WriteLine($❌ 发生错误{ex.Message});}finally{// 3. 关闭连接if(plc.IsConnected){plc.Close();Console.WriteLine( PLC连接已关闭);}}Console.WriteLine(按任意键退出...);Console.ReadKey();}staticvoidTestReadWrite(){Console.WriteLine(\n--- 开始读写测试 ---);try{// 测试1读取DB1.DBD0REAL类型对应C#的floatfloatrealValue(float)plc.Read(DB1.DBD0);Console.WriteLine($ DB1.DBD0 (REAL) {realValue});// 测试2写入DB1.DBD4REAL类型floatwriteValue123.45f;plc.Write(DB1.DBD4,writeValue);Console.WriteLine($✍️ 已写入 DB1.DBD4 (REAL) {writeValue});// 测试3读取M区MW10WORD类型对应ushortushortmValue(ushort)plc.Read(MW10);Console.WriteLine($ MW10 (WORD) {mValue});// 测试4读取I区I0.0BOOL类型booliValue(bool)plc.Read(I0.0);Console.WriteLine($ I0.0 (BOOL) {iValue});}catch(Exceptionex){Console.WriteLine($❌ 读写测试失败{ex.Message});}}}}3.3 Windows端调试直接按F5运行如果你PLC设置没问题应该能看到连接成功和读写数据。我第一次运行时连不上后来发现是Windows防火墙把102端口S7通信端口挡住了临时关了防火墙就好了生产环境记得单独开放端口。四、Linux端部署重点踩坑区Windows跑通后移到Linux本以为很简单结果踩了三个大坑一个个说。4.1 第一步在Linux上安装.NET 8 SDK我用的是Ubuntu 22.04按照微软官方文档安装# 添加Microsoft包仓库wgethttps://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.debsudodpkg -i packages-microsoft-prod.debrmpackages-microsoft-prod.deb# 安装.NET 8 SDKsudoapt-getupdatesudoapt-getinstall-y dotnet-sdk-8.0安装完验证一下dotnet --version能看到版本号就说明装好了。4.2 第二步发布项目在Windows的VS2022里右键项目→“发布”选择“文件夹”然后配置发布参数配置Release目标运行时linux-x64部署模式独立这样Linux上不用装.NET运行时也能跑更方便文件发布选项勾选“生成单个文件”或者直接用命令行发布更高效dotnet publish -c Release -r linux-x64 --self-containedtrue-p:PublishSingleFiletrue发布完成后会在bin/Release/net8.0/linux-x64/publish文件夹里生成一个可执行文件和项目名一样比如S7CrossPlatformDemo。4.3 第三步把文件传到Linux并运行我用的是WinSCP把publish文件夹里的所有文件传到Linux的/home/user/s7demo目录下。然后给可执行文件加权限cd/home/user/s7demochmodx S7CrossPlatformDemo重点来了我第一次运行时直接报错Unhandled exception. System.Net.Sockets.SocketException (13): Permission denied查了半天原来是Linux的非root用户不能直接访问102以下的端口S7用的是102端口。解决方法有两个用root运行不推荐生产环境用sudo./S7CrossPlatformDemo给程序开放端口权限推荐sudosetcapcap_net_bind_serviceep/home/user/s7demo/S7CrossPlatformDemo这样普通用户也能运行了。刚解决权限问题又遇到连接超时。检查了IP、PLC设置都没问题最后发现是Linux的防火墙没开102端口# 开放102端口sudoufw allow102/tcp# 重启防火墙sudoufw reload终于运行成功了和Windows上的输出一模一样。五、进阶优化让代码更工程化上面的代码只是个Demo实际项目里还得优化我分享两个常用的5.1 封装一个PLC通信服务用单例模式封装一下方便在ASP.NET Core或Avalonia UI里调用publicclassPlcService{privatestaticPlcService_instance;privatePlc_plc;privatestring_ip192.168.0.1;privatebool_isConnecting;publicstaticPlcServiceInstance_instance??newPlcService();privatePlcService(){_plcnewPlc(CpuType.S71200,_ip,0,1);}publicboolIsConnected_plc.IsConnected;// 断线重连publicasyncTaskboolConnectAsync(){if(_isConnecting)returnfalse;_isConnectingtrue;try{if(!_plc.IsConnected){awaitTask.Run(()_plc.Open());}return_plc.IsConnected;}catch(Exceptionex){Console.WriteLine($连接失败{ex.Message});returnfalse;}finally{_isConnectingfalse;}}// 封装读写方法加上异常处理publicTReadT(stringaddress){if(!_plc.IsConnected)thrownewException(PLC未连接);return(T)_plc.Read(address);}publicvoidWrite(stringaddress,objectvalue){if(!_plc.IsConnected)thrownewException(PLC未连接);_plc.Write(address,value);}}5.2 加上日志用Serilog记录通信日志方便排查问题// 安装Serilog.AspNetCore和Serilog.Sinks.ConsoleLog.LoggernewLoggerConfiguration().MinimumLevel.Debug().WriteTo.Console().WriteTo.File(logs/plc-.txt,rollingInterval:RollingInterval.Day).CreateLogger();// 在PlcService里用Log.Information()记录连接、读写操作六、总结整个流程走下来最大的感受是.NET跨平台现在真的很成熟了只要注意Linux下的权限和防火墙问题双端跑通并不难。最后给大家几个建议先Windows后Linux排除平台差异调试更高效。PLC设置要仔细PUT/GET和优化块访问是最容易踩的坑。Linux权限和防火墙这两个是跨平台的拦路虎一定要处理好。如果大家有问题欢迎在评论区交流我会尽量回复。后续我还会写如何把这个通信方案集成到Avalonia跨平台UI里感兴趣的朋友可以关注一下。