C#通过S7.NET库实现与西门子PLC数据交互

在这里插入图片描述
拉了换一个简单的界面

PLC端设置

在这里插入图片描述
我新建了一个DB数据块【DB1】,右键【DB1】,点击【属性】项,【优化的块访问】默认是勾选,要想显示数据块中地址偏移量,需要把【优化的块访问】勾选取消

PLC与C#数据类型对应

Bit  	=> 	bool
Byte 	=> 	byte
word 	=> 	ushort
DWord 	=> 	uint
Int 	=> 	short
DInt 	=> 	int
Real 	=> 	float
LReal 	=> 	double
String 	=> 	string

VS2019添加S7.NET库引用


1、右键项目名,选择图中【管理NuGet程序包】
在这里插入图片描述2、在搜索框输入【S7netplus】,我安装的是第一个。
在这里插入图片描述
3、安装完成引用里面会自动添加【S7.NET】引用,如上图所示。

连接PLC

public void Open();

                this.myPlc.Open();
                if (this.myPlc.PlcObject.IsConnected)
                {
                    this.btnOpen.Enabled = false;
                    this.btnClose.Enabled = true;
                    this.tsslblIsConnected.BackColor = Color.Green;
                    this.tsslblIsConnected.Text = "PLC已连接";

                    this.tsslblIP.Text = this.myPlc.PlcObject.IP.ToString();

                    this.btnRead.Enabled = true;
                    this.btnWrite.Enabled = true;

                    switch (this.myPlc.PlcObject.CPU)
                    {
                        case CpuType.S7300:
                            this.tsslblCpuType.Text = "S7-300";
                            break;
                        case CpuType.S7400:
                            this.tsslblCpuType.Text = "S7-400";
                            break;
                        case CpuType.S71200:
                            this.tsslblCpuType.Text = "S7-1200";
                            break;
                        case CpuType.S71500:
                            this.tsslblCpuType.Text = "S7-1500";
                            break;
                    }
                }

对于S7-1200和S7-1500,默认为机架= 0,槽位= 0;对于S7-300和S7-400是默认的机架= 0,槽位= 2;端口号默认为102。

断开PLC

public void Close();

                this.myPlc.Close();
                if (!this.myPlc.PlcObject.IsConnected)
                {
                    this.btnOpen.Enabled = true;
                    this.btnClose.Enabled = false;
                    this.tsslblIsConnected.BackColor = Color.Red;
                    this.tsslblIsConnected.Text = "PLC未连接";

                    this.tsslblIP.Text = "***********";
                    this.tsslblCpuType.Text = "******";

                    this.btnRead.Enabled = false;
                    this.btnWrite.Enabled = false;
                }

读取单个数据

public object? Read(string variable);

            if (this.tabControlRead.SelectedTab == this.tabControlRead.TabPages[0])  //读取单个数据
            {
                try
                {
                    this.txtReadResult.Text = DateTime.Now.ToString() + ":" + this.myPlc.Read(this.txtReadSingleAdr.Text.Trim().ToUpper()).ToString();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("读取单个数据出现错误!" + ex.Message, "提示信息");
                }
            }

我这里把输入的地址的转换为大写字母;如果不转换,输入小写字母会出现报错。

读取数组数据

public object? Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0);

switch (this.cboReadVarType.Text.Trim())
{
    case "Bit":
        foreach (var item in (System.Collections.BitArray)this.myPlc.Read(dataType, db, startByteAdr, VarType.Bit, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "Byte":
        foreach (var item in (byte[])this.myPlc.Read(dataType, db, startByteAdr, VarType.Byte, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "Word":
        foreach (var item in (ushort[])this.myPlc.Read(dataType, db, startByteAdr, VarType.Word, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "DWord":
        foreach (var item in (uint[])this.myPlc.Read(dataType, db, startByteAdr, VarType.DWord, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "Int":
        foreach (var item in (short[])this.myPlc.Read(dataType, db, startByteAdr, VarType.Int, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "DInt":
        foreach (var item in (int[])this.myPlc.Read(dataType, db, startByteAdr, VarType.DInt, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "Real":
        foreach (var item in (float[])this.myPlc.Read(dataType, db, startByteAdr, VarType.Real, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "LReal":
        foreach (var item in (double[])this.myPlc.Read(dataType, db, startByteAdr, VarType.LReal, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "String":
        foreach (var item in (string)this.myPlc.Read(dataType, db, startByteAdr, VarType.String, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "S7String":
        foreach (var item in (string[])this.myPlc.Read(dataType, db, startByteAdr, VarType.S7String, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "S7WString":
        foreach (var item in (string[])this.myPlc.Read(dataType, db, startByteAdr, VarType.S7WString, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "DateTime":
        foreach (var item in (DateTime[])this.myPlc.Read(dataType, db, startByteAdr, VarType.DateTime, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
    case "DateTimeLong":
        foreach (var item in (DateTime[])this.myPlc.Read(dataType, db, startByteAdr, VarType.DateTimeLong, varCount, bitAdr))
        {
            this.rtxtReadResult.Text += item.ToString() + " ";
        }
        break;
}

读取BIT数组时我这里使用【System.Collections.BitArray】强制转换

读取字节数组

public byte[] ReadBytes(DataType dataType, int db, int startByteAdr, int count);

var bytes = this.myPlc.PlcObject.ReadBytes(DataType.DataBlock, 1, 0, 120);
string str = string.Empty;

str  = "DB1.DBX0.0:\t" + Convert.ToBoolean(bytes[0].SelectBit(0)).ToString() + "\n";
str += "DB1.DBX0.1:\t" + Convert.ToBoolean(bytes[0].SelectBit(1)).ToString() + "\n";
str += "DB1.DBX0.2:\t" + Convert.ToBoolean(bytes[0].SelectBit(2)).ToString() + "\n";

str += "DB1.DBB1.0:\t" + Convert.ToString(S7.Net.Types.Byte.FromByteArray(bytes.Skip(1).Take(1).ToArray()), 16) + "\n";
str += "DB1.DBB2.0:\t" + Convert.ToString(S7.Net.Types.Byte.FromByteArray(bytes.Skip(2).Take(1).ToArray()), 16) + "\n";
str += "DB1.DBB3.0:\t" + Convert.ToString(S7.Net.Types.Byte.FromByteArray(bytes.Skip(3).Take(1).ToArray()), 16) + "\n";

str += "DB1.DBW4.0:\t" + Convert.ToInt16(S7.Net.Types.Int.FromByteArray(bytes.Skip(4).Take(2).ToArray())) + "\n";
str += "DB1.DBW6.0:\t" + Convert.ToInt16(S7.Net.Types.Int.FromByteArray(bytes.Skip(6).Take(2).ToArray())) + "\n";
str += "DB1.DBW8.0:\t" + Convert.ToInt16(S7.Net.Types.Int.FromByteArray(bytes.Skip(8).Take(2).ToArray())) + "\n";

str += "DB1.DBW10.0\t:" + Convert.ToUInt16(S7.Net.Types.Word.FromByteArray(bytes.Skip(10).Take(2).ToArray())) + "\n";
str += "DB1.DBW12.0\t:" + Convert.ToUInt16(S7.Net.Types.Word.FromByteArray(bytes.Skip(12).Take(2).ToArray())) + "\n";
str += "DB1.DBW14.0\t:" + Convert.ToUInt16(S7.Net.Types.Word.FromByteArray(bytes.Skip(14).Take(2).ToArray())) + "\n";

str += "DB1.DBW16.0:\t" + Convert.ToString(S7.Net.Types.Word.FromByteArray(bytes.Skip(16).Take(2).ToArray()), 16) + "\n";
str += "DB1.DBW18.0:\t" + Convert.ToString(S7.Net.Types.Word.FromByteArray(bytes.Skip(18).Take(2).ToArray()), 16) + "\n";
str += "DB1.DBW20.0:\t" + Convert.ToString(S7.Net.Types.Word.FromByteArray(bytes.Skip(20).Take(2).ToArray()), 16) + "\n";

str += "DB1.DBD22.0:\t" + Convert.ToString(S7.Net.Types.DWord.FromByteArray(bytes.Skip(22).Take(4).ToArray()), 16) + "\n";
str += "DB1.DBD26.0:\t" + Convert.ToString(S7.Net.Types.DWord.FromByteArray(bytes.Skip(26).Take(4).ToArray()), 16) + "\n";
str += "DB1.DBD30.0:\t" + Convert.ToString(S7.Net.Types.DWord.FromByteArray(bytes.Skip(30).Take(4).ToArray()), 16) + "\n";

str += "DB1.DBD34.0:\t" + Convert.ToInt32(S7.Net.Types.DInt.FromByteArray(bytes.Skip(34).Take(4).ToArray())) + "\n";
str += "DB1.DBD38.0:\t" + Convert.ToInt32(S7.Net.Types.DInt.FromByteArray(bytes.Skip(38).Take(4).ToArray())) + "\n";
str += "DB1.DBD42.0:\t" + Convert.ToInt32(S7.Net.Types.DInt.FromByteArray(bytes.Skip(42).Take(4).ToArray())) + "\n";

str += "DB1.DBD46.0:\t" + Convert.ToUInt32(S7.Net.Types.DWord.FromByteArray(bytes.Skip(46).Take(4).ToArray())) + "\n";
str += "DB1.DBD50.0:\t" + Convert.ToUInt32(S7.Net.Types.DWord.FromByteArray(bytes.Skip(50).Take(4).ToArray())) + "\n";
str += "DB1.DBD54.0:\t" + Convert.ToUInt32(S7.Net.Types.DWord.FromByteArray(bytes.Skip(54).Take(4).ToArray())) + "\n";

str += "DB1.DBD58.0:\t" + Convert.ToSingle(S7.Net.Types.Real.FromByteArray(bytes.Skip(58).Take(4).ToArray())) + "\n";
str += "DB1.DBD62.0:\t" + Convert.ToSingle(S7.Net.Types.Real.FromByteArray(bytes.Skip(62).Take(4).ToArray())) + "\n";
str += "DB1.DBD66.0:\t" + Convert.ToSingle(S7.Net.Types.Real.FromByteArray(bytes.Skip(66).Take(4).ToArray())) + "\n";

str += "DB1.DBD70.0:\t" + Convert.ToDouble(S7.Net.Types.LReal.FromByteArray(bytes.Skip(70).Take(8).ToArray())) + "\n";
str += "DB1.DBD78.0:\t" + Convert.ToDouble(S7.Net.Types.LReal.FromByteArray(bytes.Skip(78).Take(8).ToArray())) + "\n";
str += "DB1.DBD86.0:\t" + Convert.ToDouble(S7.Net.Types.LReal.FromByteArray(bytes.Skip(86).Take(8).ToArray())) + "\n";

str += "LocalTime:\t" + Convert.ToDateTime(S7.Net.Types.DateTimeLong.FromByteArray(bytes.Skip(96).Take(12).ToArray())) + "\n";
str += "SYSTime: \t\t" + Convert.ToDateTime(S7.Net.Types.DateTimeLong.FromByteArray(bytes.Skip(108).Take(12).ToArray())) + "\n";
str += "----------***********************-----------------\n";

我这里是读取DB1数据块的前120个字节的数据,我这里使用了Skip()和Take()函数,要使用这两个函数需要添加
using System.Linq;

修改单个数据

if (this.tabControlWrite.SelectedTab == this.tabControlWrite.TabPages[0])   //写入单个数据
{
    try
    {
        switch (this.cboWriteVarType.Text.Trim())
        {
            case "Bit":
                this.myPlc.Write(this.txtWriteSingleAdr.Text.Trim(), Convert.ToBoolean(this.rtxtWriteData.Text.Trim()));
                break;
            case "Byte":
                this.myPlc.Write(this.txtWriteSingleAdr.Text.Trim(), Convert.ToByte(this.rtxtWriteData.Text.Trim()));
                break;
            case "Word":
            case "Int":
                this.myPlc.Write(this.txtWriteSingleAdr.Text.Trim(), Convert.ToInt16(this.rtxtWriteData.Text.Trim()));
                break;
            case "DWord":
            case "DInt":
                this.myPlc.Write(this.txtWriteSingleAdr.Text.Trim(), Convert.ToInt32(this.rtxtWriteData.Text.Trim()));
                break;
            case "Real":
                this.myPlc.Write(this.txtWriteSingleAdr.Text.Trim(), Convert.ToSingle(this.rtxtWriteData.Text.Trim()));
                break;
            case "LReal":
                this.myPlc.Write(this.txtWriteSingleAdr.Text.Trim(), Convert.ToDouble(this.rtxtWriteData.Text.Trim()));
                break;
            case "String":
            case "S7String":
            case "S7WString":
                this.myPlc.Write(this.txtWriteSingleAdr.Text.Trim(), this.rtxtWriteData.Text.Trim());
                break;
            case "Timer":
                break;
            case "Counter":
                break;
            case "DateTime":
            case "DateTimeLong":
                this.myPlc.Write(this.txtWriteSingleAdr.Text.Trim(), Convert.ToDateTime(this.rtxtWriteData.Text.Trim()));
                break;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("写入单个数据出现错误!" + ex.Message, "提示信息");
    }

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐