C# 上位机连西门子 S7-1200/1500,绕来绕去就三条路:走 S7 协议(Sharp7 / S7.Net 这类开源库)、走 PLC 自带的 OPC UA Server、走西门子官方 .NET 通信库。选型一句话:点位少、要快、不想花钱,用 S7 协议;车间里不止西门子一种 PLC、或者要跨网段跨防火墙,用 OPC UA;预算充足又想要官方兜底,上官方库。真正让新手卡住的是前两条路上的两个开关——PUT/GET 和"优化的块访问",这篇把坑位和代码一起交代清楚。
三条路各是什么脾气?先看这张对比
直接说 S7comm 协议,读写 DB 区、I/Q/M 区,一个 TCP 连接(102 端口)搞定。开源免费,读写延迟毫秒级,是定制上位机的默认选择。
1200/1500 固件里自带 OPC UA 服务器,变量在博图里导出成节点。协议开放,以后换 AB、三菱也能一套代码吃下来,还带证书加密。
SIMATIC S7 Communication Library for .NET,官方维护、有技术支持,但按站点授权收费,且绑定西门子生态,小项目性价比不高。
| 对比项 | S7 协议 | OPC UA | 官方库 |
|---|---|---|---|
| 费用 | 0(开源) | 0(固件自带) | 按站点授权 |
| 单次读延迟 | 2~8 ms(同网段) | 10~30 ms(订阅模式更低) | 与 S7 协议相当 |
| 跨品牌能力 | 无,只认西门子 | 强,协议国际标准 | 无 |
| PLC 侧前置条件 | 勾选 PUT/GET、关优化块访问 | 激活 OPC UA 服务器、配证书 | 同 S7 协议 |
| 适合场景 | 定制上位机、产线专机 | 多品牌车间、MES 对接 | 甲方点名要官方支持 |
▲ 我们近两年的项目里,八成走路线 A,两成走路线 B。路线 B 越来越多是因为甲方 MES 团队想直接订阅变量,不想让上位机当二传手。
为什么连上了却读不到数?两个开关先查
说实话,S7-1200 项目一半的"通信故障"根本不是通信问题,是博图里两个默认设置在拦你。第一次去现场,程序连上了、读 DB 却报错,排查半天最后发现是这两个地方:
开关一:PUT/GET 访问没勾
博图 → 设备组态 → CPU 属性 → 防护与安全 → 连接机制,勾选 允许来自远程对象的 PUT/GET 通信。不勾,第三方客户端一律吃闭门羹。1500 同理,且 1500 还有访问级别密码,通信库要填对密码等级。
开关二:数据块勾了"优化的块访问"
博图里新建 DB 默认勾选 优化的块访问,此时变量没有绝对偏移地址,只有符号,S7 协议按地址读直接失败。给上位机用的 DB,右键属性里把这个勾去掉,让每个变量露出 DB1.DBW0 这种偏移地址。
这两个设置改完都要重新下载并重启 PLC 才生效——现场经常有人改了没下载,白忙一场。另外 1500 的 DB 若开了"仅符号访问",效果和优化块一样,第三方库读不了,一并关掉。
Sharp7 还是 S7.Net?连接与读写代码长这样
两个库我们都大量用过:Sharp7 轻、无依赖、一个 cs 文件就能塞进项目;S7.Net 的 API 更顺手,支持异步,类型转换帮你做了。小工具选 Sharp7,正经上位机选 S7.Net。连接和读写的骨架代码:
// S7.Net 方式(NuGet: S7netplus) var plc = new Plc(CpuType.S71200, "192.168.0.10", 0, 1); // 机架0 槽1 if (plc.Open() != ErrorCode.NoError) throw new IOException($"连接失败: {plc.Open()}"); // 读:DB1 偏移0处的 float、DB1.DBW10 的 short、M0.0 的 bool float temp = (float)plc.Read("DB1.DBD0"); short count = (short)plc.Read("DB1.DBW10"); bool run = (bool)plc.Read("M0.0"); // 写:启动命令位 plc.Write("DB1.DBX12.0", true); // Sharp7 方式:一个类文件,手动管缓冲区 var cli = new S7Client(); int err = cli.ConnectTo("192.168.0.10", 0, 1); byte[] buf = new byte[4]; cli.DBRead(1, 0, 4, buf); // DB1 偏移0 读4字节 float v = S7.GetFloatAt(buf, 0); // 手动转 float
轮询 200 个点卡成 PPT?批量读与重连是必修课
S7 协议一次 PDU 能带的数据量有限(1200 协商下来通常 240 字节左右),200 个点如果一个个读,就是 200 次 TCP 往返,轮询一圈秒级起步。做法很简单:把地址连续的点合并成段,一段一笔读。比如 DB1 里 0~199 字节全是采集数据,一笔 DBRead(1, 0, 200) 全拿回来,再在内存里按偏移解析,200 个点一笔解决。我们有个昆山的项目,合并前后轮询周期从 3.2 秒掉到 90 毫秒,就这一招。
再就是断线重连。车间交换机重启、网线被叉车碰掉、PLC 停机下载程序,连接断是常态。S7.Net 的 Plc 对象断了之后 Open 状态不可靠,我们的惯例是:读操作包一层捕获,失败即 Close + 重建对象 + 重连,重连间隔 2 秒起步指数退避,别拿死循环 100ms 重试去轰 PLC。还有一点容易漏:重连成功后第一笔读要丢弃或校验,防止拿到半截缓冲数据。
收尾:去现场前对着这张表过一遍
| 检查项 | 位置 / 动作 |
|---|---|
| PUT/GET | CPU 属性 → 防护与安全 → 勾选,下载重启 |
| 优化块访问 | 上位机用的每个 DB → 属性 → 取消勾选,下载重启 |
| IP 与网段 | 工控机与 PLC 同网段,ping 通再谈通信 |
| 机架/槽号 | 1200/1500 一律机架 0 槽 1(或 0),别照抄 300 的 0/2 |
| 防火墙 | 102 端口放行;OPC UA 走 4840 |
| 连接数上限 | 1200 的连接资源有限,上位机 + 触摸屏 + 网关别超限 |
选型这事其实没有玄学:单一西门子设备、要低延迟、预算紧,就 S7 协议;多品牌、要长期演进,一开始就上 OPC UA。如果你手上正好有个 1200 连不上,先别怀疑代码,去博图里把上面两个开关看一眼——我打赌八成在那。
