一.设置
1.S7-PLCSIM Advanced V5.0 配置
1.1S7-PLCSIM Advanced 配置

2.设置 PG/PC 接口
在西门子 PLC 编程或仿真时,设置 PG/PC 接口是确保电脑与 PLC(或仿真器)正常通信

- 打开 Windows 控制面板 (可通过 Win+R 输入
control
快速打开)。 - 切换到 "小图标" 视图,找到并点击 "Set PG/PC Interface"(西门子专用设置,安装 TIA Portal 或 PLCSIM 后会出现)。

-
Siemens PLCSIM Virtual Ethernet Adapter.TCPIP.1
- 基于TCP/IP 协议 的虚拟接口,支持标准 S7 协议(端口 102),是连接 PLCSIM 仿真 PLC(如 S7-1200/1500)的首选接口,兼容性好,支持 PUT/GET 通信。
-
Siemens PLCSIM Virtual Ethernet Adapter.TCPIP.Auto.1
- 自动适配的 TCP/IP 虚拟接口,会尝试自动匹配通信参数,适合新手或不确定具体配置的场景,但稳定性略逊于
TCPIP.1
。
- 自动适配的 TCP/IP 虚拟接口,会尝试自动匹配通信参数,适合新手或不确定具体配置的场景,但稳定性略逊于
-
Siemens PLCSIM Virtual Ethernet Adapter.
ISO.1
,但 S7-1200/1500 通常无需此接口
3.配置网络

选择接口后,点击 "属性" 按钮,确认以下设置:
- IP 地址 :确保虚拟网卡的 IP 与仿真 PLC 在同一网段(如 PLC 为
192.168.1.25
,虚拟网卡可设为192.168.1.10
)。 - 子网掩码 :统一设为
255.255.255.0
。 - 其他参数:保持默认(无需修改网关、DNS 等)

2.PLC的配置
2.1修改IP

2.2 允许 PUT/GET 通信访问
- 在设备组态界面中,选中左侧机架上的PLC(如 S7-1500 CPU)。
- 在右侧 "属性" 面板中,找到 **"常规"→ "防护与安全"→"连接机制"**。
- 勾选 **"允许来自远程伙伴的 PUT/GET 通信访问"**(该选项用于开启外部设备的读写权限)。

2.3 启用 "块编译过程中支持仿真" 选项
- 在 TIA Portal 项目树中,右键点击项目名称(如 "CPSim"),选择 **"属性"**。
- 在弹出的属性窗口中,选择 **"PLC 保护和优化"** 选项卡。
- 勾选 **"块编译过程中支持仿真"**(需确保该选项在项目属性的 "PLC 保护和优化" 中可见,不同版本界面可能略有差异)。
- 点击 **"确定"** 保存设置。
3.VisionStudio 中添加 S7NetPlus 管理
3.1 使用 NuGet 包管理器控制台
-
打开 Visual Studio,点击顶部菜单「工具 」→「NuGet 包管理器 」→「程序包管理器控制台」。
-
在控制台中输入以下命令并回车:
Install-Package S7NetPlus
二.代码
- I 区(输入) :
I[字节].[位]
(如 I0.0),通常为只读 - Q 区(输出) :
Q[字节].[位]
(如 Q0.0),可读写 - V 区(变量存储) :字节
V[字节]
、字VW[字节]
(16 位)、双字VD[字节]
(32 位) - W 区(临时工作存储) :位
W[字节].[位]
、字WW[字节]
、双字WD[字节]
- DW 区(双字) :
DW[字节]
(32 位,部分 PLC 中为通用数据区) - R 区(过程映像) :位
R[字节].[位]
、双字RD[字节]
(32 位)
-
注意事项:
- I 区:输入区通常由外部信号控制,写入可能失败(取决于 PLC 型号)
- W 区:临时变量区,仅在 PLC 程序执行时有效,不保存数据
- 兼容性:部分区域(如 V 区)主要用于 S7-200/200SMART,S7-1200/1500 更常用 DB 区和 M 区
- 权限:确保 PLC 已开启 "允许 PUT/GET 通信"(见之前的配置步骤)
-
数据类型对应:
- 位(bool):
I0.0
、Q0.0
等 - 字节(byte):
V0
、R0
等 - 字(16 位整数):
VW2
、WW2
等 - 双字(32 位整数):
VD4
、RD4
等
- 位(bool):
cs
using System;
using S7.Net;
class PlcMemoryAccess
{
static void Main(string[] args)
{
// 配置PLC连接参数(根据实际情况修改)
string plcIp = "192.168.1.25";
int rack = 0;
int slot = 1; // S7-1500默认槽号为1,S7-1200通常为0
Plc plc = new Plc(CpuType.S71500, plcIp, rack, slot);
try
{
Console.WriteLine("连接PLC中...");
plc.Open();
if (plc.IsConnected)
{
Console.WriteLine("PLC连接成功!\n");
// 1. 读写输入区(I点):数字量输入,通常为只读
bool i0_0 = (bool)plc.Read("I0.0"); // 读取I0.0
Console.WriteLine($"I0.0 原始值: {i0_0}");
// 注意:I区为输入区,通常不建议写入,部分PLC可能禁止写入
// plc.Write("I0.0", true); // 多数情况下会失败
// 2. 读写输出区(Q点):数字量输出
bool q0_0 = (bool)plc.Read("Q0.0"); // 读取Q0.0
Console.WriteLine($"Q0.0 原始值: {q0_0}");
plc.Write("Q0.0", !q0_0); // 翻转Q0.0的值
Console.WriteLine($"Q0.0 新值: {plc.Read("Q0.0")}\n");
// 3. 读写变量存储区(V区,S7-200/200SMART常用)
// 读取V区字节(8位)
byte v0 = (byte)plc.Read("V0.0", 1); // 读取V0开始的1个字节
// 读取V区字(16位整数)
short v2 = (short)plc.Read("VW2"); // 读取VW2(V2.0-V3.7)
Console.WriteLine($"V0 原始值: {v0}, VW2 原始值: {v2}");
plc.Write("V0.0", (byte)0xAA); // 写入V0字节
plc.Write("VW2", (short)1234); // 写入VW2字
Console.WriteLine($"V0 新值: {plc.Read("V0.0", 1)}, VW2 新值: {plc.Read("VW2")}\n");
// 4. 读写工作存储区(W区,S7-1200/1500的临时变量区)
// 注意:W区为临时变量,仅在块执行时有效,断电丢失
bool w0_0 = (bool)plc.Read("W0.0");
short w2 = (short)plc.Read("WW2");
Console.WriteLine($"W0.0 原始值: {w0_0}, WW2 原始值: {w2}");
plc.Write("W0.0", true);
plc.Write("WW2", (short)5678);
Console.WriteLine($"W0.0 新值: {plc.Read("W0.0")}, WW2 新值: {plc.Read("WW2")}\n");
// 5. 读写数据字(DW区,通常指双字32位,不同PLC定义可能不同)
int dw4 = (int)plc.Read("DW4"); // 读取DW4(32位整数)
Console.WriteLine($"DW4 原始值: {dw4}");
plc.Write("DW4", 123456); // 写入32位整数
Console.WriteLine($"DW4 新值: {plc.Read("DW4")}\n");
// 6. 读写过程映像区(R区,S7-1200/1500的过程数据区)
bool r0_0 = (bool)plc.Read("R0.0");
int r4 = (int)plc.Read("RD4"); // 读取R区双字(32位)
Console.WriteLine($"R0.0 原始值: {r0_0}, RD4 原始值: {r4}");
plc.Write("R0.0", true);
plc.Write("RD4", 98765);
Console.WriteLine($"R0.0 新值: {plc.Read("R0.0")}, RD4 新值: {plc.Read("RD4")}");
}
}
catch (Exception ex)
{
Console.WriteLine($"操作失败: {ex.Message}");
}
finally
{
if (plc.IsConnected)
{
plc.Close();
Console.WriteLine("\nPLC连接已关闭");
}
}
Console.WriteLine("按任意键退出...");
Console.ReadKey();
}
}
python
import snap7
from snap7.util import *
import time
class PlcCommunication:
def __init__(self, ip, rack=0, slot=1):
self.plc = snap7.client.Client()
self.ip = ip
self.rack = rack
self.slot = slot
self.connected = False
def connect(self):
"""连接到PLC"""
try:
self.plc.connect(self.ip, self.rack, self.slot)
self.connected = True
print(f"成功连接到PLC: {self.ip}")
return True
except Exception as e:
print(f"连接PLC失败: {str(e)}")
self.connected = False
return False
def disconnect(self):
"""断开与PLC的连接"""
if self.connected:
self.plc.disconnect()
self.connected = False
print("已断开与PLC的连接")
def read_write_i_area(self):
"""读写输入区(I点)- 通常为只读"""
if not self.connected:
print("未连接到PLC")
return
try:
# 读取I区:读取从字节0开始的1个字节(包含I0.0-I0.7)
data = self.plc.read_area(snap7.client.Areas.PE, 0, 0, 1)
i0_0 = get_bool(data, 0, 0) # 获取I0.0的值
print(f"I0.0 原始值: {i0_0}")
# 注意:I区为输入区,通常不建议写入,多数PLC会禁止写入
# 以下代码可能失败,仅作示例
try:
set_bool(data, 0, 0, True) # 尝试设置I0.0为True
self.plc.write_area(snap7.client.Areas.PE, 0, 0, data)
print("尝试写入I0.0为True(可能失败)")
except Exception as e:
print(f"写入I区失败: {str(e)}")
except Exception as e:
print(f"操作I区出错: {str(e)}")
def read_write_q_area(self):
"""读写输出区(Q点)"""
if not self.connected:
print("未连接到PLC")
return
try:
# 读取Q区:读取从字节0开始的1个字节(包含Q0.0-Q0.7)
data = self.plc.read_area(snap7.client.Areas.PA, 0, 0, 1)
q0_0 = get_bool(data, 0, 0) # 获取Q0.0的值
print(f"Q0.0 原始值: {q0_0}")
# 写入Q0.0:翻转当前值
new_value = not q0_0
set_bool(data, 0, 0, new_value)
self.plc.write_area(snap7.client.Areas.PA, 0, 0, data)
# 验证写入结果
data = self.plc.read_area(snap7.client.Areas.PA, 0, 0, 1)
print(f"Q0.0 新值: {get_bool(data, 0, 0)}")
except Exception as e:
print(f"操作Q区出错: {str(e)}")
def read_write_v_area(self):
"""读写变量存储区(V区)- S7-200/200SMART常用"""
if not self.connected:
print("未连接到PLC")
return
try:
# 读取V区:字节(V0)和字(VW2)
# 读取从V0开始的4个字节(V0-V3)
data = self.plc.read_area(snap7.client.Areas.MK, 0, 0, 4)
v0 = data[0] # V0字节值
vw2 = get_int(data, 2) # VW2(V2-V3)的16位整数
print(f"V0 原始值: {v0}, VW2 原始值: {vw2}")
# 写入V区
data[0] = 0xAA # 写入V0字节
set_int(data, 2, 1234) # 写入VW2字
self.plc.write_area(snap7.client.Areas.MK, 0, 0, data)
# 验证写入结果
data = self.plc.read_area(snap7.client.Areas.MK, 0, 0, 4)
print(f"V0 新值: {data[0]}, VW2 新值: {get_int(data, 2)}")
except Exception as e:
print(f"操作V区出错: {str(e)}")
def read_write_r_area(self):
"""读写过程映像区(R区)- S7-1200/1500常用"""
if not self.connected:
print("未连接到PLC")
return
try:
# 读取R区:位(R0.0)和双字(RD4)
data = self.plc.read_area(snap7.client.Areas.DB, 0, 4, 4) # 读取RD4开始的4字节
# 读取R0.0(需要先读取R0所在的字节)
r0_data = self.plc.read_area(snap7.client.Areas.DB, 0, 0, 1)
r0_0 = get_bool(r0_data, 0, 0)
rd4 = get_dword(data, 0) # RD4的32位整数
print(f"R0.0 原始值: {r0_0}, RD4 原始值: {rd4}")
# 写入R区
set_bool(r0_data, 0, 0, True) # 设置R0.0为True
self.plc.write_area(snap7.client.Areas.DB, 0, 0, r0_data)
set_dword(data, 0, 98765) # 设置RD4为98765
self.plc.write_area(snap7.client.Areas.DB, 0, 4, data)
# 验证写入结果
r0_data = self.plc.read_area(snap7.client.Areas.DB, 0, 0, 1)
data = self.plc.read_area(snap7.client.Areas.DB, 0, 4, 4)
print(f"R0.0 新值: {get_bool(r0_data, 0, 0)}, RD4 新值: {get_dword(data, 0)}")
except Exception as e:
print(f"操作R区出错: {str(e)}")
def read_write_memory_areas(self):
"""批量测试各存储区的读写操作"""
print("\n=== 测试I区 ===")
self.read_write_i_area()
print("\n=== 测试Q区 ===")
self.read_write_q_area()
print("\n=== 测试V区 ===")
self.read_write_v_area()
print("\n=== 测试R区 ===")
self.read_write_r_area()
if __name__ == "__main__":
# 配置PLC连接参数(根据实际情况修改)
PLC_IP = "192.168.1.25"
RACK = 0
SLOT = 1 # S7-1500默认槽号为1,S7-1200通常为0
plc_comm = PlcCommunication(PLC_IP, RACK, SLOT)
if plc_comm.connect():
plc_comm.read_write_memory_areas()
plc_comm.disconnect()