在C#中使用s7Netplus实现与西门子PLC的数据通信
S7.Net Plus(简称s7Netplus)是一个开源的西门子PLC驱动程序,专为通过以太网连接与西门子PLC进行通信而设计。它完全用C#编写,使得开发者能够在不处理本地DLL的情况下轻松地进行调试。s7Netplus支持多种西门子PLC型号,包括S7-200、S7-300、S7-400、S7-1200和S7-1500。
如何获取s7Netplus
s7Netplus的官方代码库托管在GitHub上,地址为:
https://github.com/killnine/s7netplus。你也可以直接通过NuGet包管理器下载库:https://www.nuget.org/packages/S7netplus/。
s7Netplus的基本概念
在使用s7Netplus之前,你需要了解一些基本概念,包括CPU类型、IP地址、机架号和插槽号。这些概念将帮助你创建PLC实例并与之通信。
CPU类型(CpuType)
s7Netplus支持多种CPU类型,定义在一个名为CpuType的枚举中:
public enum CpuType
{
S7200 = 0,
Logo0BA8 = 1,
S7200Smart = 2,
S7300 = 10,
S7400 = 20,
S71200 = 30,
S71500 = 40,
}
IP地址、机架号和插槽号
IP地址:PLC或外部以太网卡的IP地址。
机架号:PLC的机架号,可以在Step7的硬件配置中找到。
插槽号:CPU的插槽号,也可以在Step7的硬件配置中找到。
开始使用s7Netplus
- 创建PLC实例
要创建PLC实例,首先需要使用以下构造函数:
public Plc(CpuType cpu, string ip, Int16 rack, Int16 slot)
例如,以下代码创建了一个连接到本地主机(IP地址为127.0.0.1)上机架0插槽2的S7-300 PLC的实例:
Plc plc = new Plc(CpuType.S7300, "127.0.0.1", 0, 2);
- 连接和断开PLC
连接到PLC使用Open方法,断开连接使用Close方法:
plc.Open();
// 执行操作...
plc.Close();
- 错误处理
Open方法返回一个ErrorCode枚举,用于检查操作是否成功。你应该始终检查它是否返回ErrorCode.NoError。
if (plc.Open() == ErrorCode.NoError)
{
// 连接成功
}
else
{
// 处理错误
}
- 读取和写入数据
s7Netplus提供了多种读取变量的方法。最基本的方法是ReadBytes和WriteBytes。
- 读取和写入字节
public byte[] ReadBytes(DataType dataType, int db, int startByteAdr, int count)
public ErrorCode WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value)
例如,以下代码读取DB1的前200个字节:
var bytes = plc.ReadBytes(DataType.DataBlock, 1, 0, 200);
- 读取和解码
如果你想要读取并直接得到解码后的结果,可以使用Read和Write方法。
public object Read(DataType dataType, int db, int startByteAdr, VarType varType, int count)
public ErrorCode Write(DataType dataType, int db, int startByteAdr, object value)
例如,以下代码读取DB1的前20个双字(DWords):
var dwords = plc.Read(DataType.DataBlock, 1, 0, VarType.DWord, 20);
- 读取和写入结构体
如果你想要读取或写入整个结构体,可以使用ReadStruct和WriteStruct方法。
public object ReadStruct(Type structType, int db, int startByteAdr = 0)
public ErrorCode WriteStruct(object structValue, int db, int startByteAdr = 0)
例如,假设你在PLC中定义了一个数据块,然后在.NET应用程序中添加了一个与之类似的结构体:
public struct TestStruct
{
public bool varBool0;
// ... 其他字段 ...
}
// 从DataBlock 1读取结构体
TestStruct test = (TestStruct)plc.ReadStruct(typeof(TestStruct), 1);
- 读取和写入类
类似地,你可以使用ReadClass和WriteClass方法来读取和写入类。
public void ReadClass(object sourceClass, int db, int startByteAdr = 0)
public ErrorCode WriteClass(object classValue, int db, int startByteAdr = 0)
例如,假设你在PLC中定义了一个数据块,然后在.NET应用程序中添加了一个与之类似的类:
public class TestClass
{
public bool varBool0 { get; set; }
// ... 其他属性 ...
}
// 从DataBlock 1读取类
TestClass testClass = new TestClass();
plc.ReadClass(testClass, 1);
- 值转换
s7Netplus提供了一些辅助方法来转换C#和S7 PLC之间的值。
读取S7 Word:
ushort result = (ushort)plc.Read("DB1.DBW0");
写入S7 Word:
ushort val = 40000;
plc.Write("DB1.DBW0", val);
读取S7 DWord:
uint result = (uint)plc.Read("DB1.DBD40");
写入S7 DWord:
uint val = 1000;
plc.Write("DB1.DBD40", val);
下面是一个简单的C#示例,演示如何使用S7.Net与S7-300 PLC进行通信,使用之前,确保已经通过NuGet安装了S7netplus包。
using S7.Net;
using System;
class Program
{
static void Main(string[] args)
{
Plc plc = new Plc(CpuType.S7300, "192.168.0.1", 0, 2);
try
{
plc.Open();
byte[] bytes = plc.ReadBytes(DataType.DataBlock, 1, 0, 200);
ushort result = (ushort)plc.Read("DB1.DBW0");
plc.Write("DB1.DBW0", (ushort)500);
plc.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
}
这个示例首先创建一个Plc对象,然后打开连接,读取DB1的前200个字节,读取DB1.DBW0变量,并将其写入DB1.DBW0,最后关闭连接。通过S7.Net库,可以轻松地实现与西门子PLC的以太网通信,无需了解底层的S7协议细节。
S7-1200/1500的注意事项
对于S7-1200/1500,外部设备只能使用S7 "base"协议访问CPU,且仅限于基本数据传输。所有其他PG操作(控制/目录等)必须遵循扩展协议,目前s7Netplus尚未支持。
结论
s7Netplus是一个功能强大的库,它使得与西门子PLC的通信变得简单而高效。通过上述示例,你可以在C#应用程序中轻松地实现与PLC的通信,无论是读取和写入单个变量,还是整个结构体或类的读写。s7Netplus的易用性和灵活性使其成为处理西门子PLC通信的优选工具。