基于C#的上位机开发第一期:S7.NET

001准备工作

  1. 准备工作安装Visual Studio 2022

  1. 新建一个基于 windows 的窗体应用,其余选项跟着下一步进行

  1. 获取S7.NET 的函数库文件

点击该选项

检索,获得,安装 s7netplus 到你的项目中

  1. 引用 s7netplus 到命名空间中去


using S7.Net;//西门子通讯驱动包
using S7.Net.Types;

别忘了一些常用的库也要引用到项目中


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

至此,基本的文件已经备妥

002建立S71200的通讯

S7.Net与 S7 200 S7 300 S7 400 S7 1200 和 S7 1500 兼容。本文以S71200为例子

public Plc(CpuType cpu, string ip, Int16 rack, Int16 slot)

CpuType {S7200 = 0,S7300 = 10,S7400 = 20,S71200 = 30,S71500 = 40}

Ip: 包含外部以太网卡CPU 的 IP 地址

Rack:它包含PLC 的机架,您可以在 Step7 的硬件配置中找到该机架,可默认0。

Slot : 这是CPU 的插槽,您可以在 Step7 的硬件配置中找到它,可默认1。


//创建实例化
Plc S71200 = new(CpuType.S71200, "192.168.0.33", 0, 1);

带地址修改的实例化,请在设计器中配置好textBox控件的文本内容


//创建可以自定义CPU类型和IP地址的实例化
S71200 = new Plc(CpuType.S71200, txtAddress.Text, Convert.ToInt16(txtRack.Text), Convert.ToInt16(txtSlot.Text));

Plc 实例话后,会生成如下方法

  • S71200.Open(); 启动Plc通讯连接

  • S71200.Close(); 停止Plc通讯连接

  • S71200.IsConnected 该bool值可用于检查Plc是否处于通信连接中

003数据交互

  1. 西门子PLC处建立对应的DB块

允许PUT/GET通讯
  1. 创建你想要交互的实体类


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using S7.Net;//西门子通讯驱动包
using S7.Net.Types;

namespace S7LinkTest
{
    internal class PlcShowDate: INotifyPropertyChanged//建立PlcDate的class  ,并未其赋予接口属性(属性改变通知)
    {
        private float actPos_PN1;
        public float ActPos_PN1
        {get{ return actPos_PN1; }set{if (value != actPos_PN1){ actPos_PN1 = value; Change(nameof(ActPos_PN1)); }}}
        private float actPos_PN2;
        public float ActPos_PN2
        {get { return actPos_PN2; }set { if (value != actPos_PN2) { actPos_PN2 = value; Change(nameof(ActPos_PN2)); } }}
        private float actPos_PN3;
        public float ActPos_PN3
        {get { return actPos_PN3; }set { if (value != actPos_PN3) { actPos_PN3 = value; Change(nameof(ActPos_PN3)); } }}
        private float actPos_PN4;
        public float ActPos_PN4
        {get { return actPos_PN4; }set { if (value != actPos_PN4) { actPos_PN4 = value; Change(nameof(ActPos_PN4)); } }}
        private float actPos_PTO1;
        public float ActPos_PTO1
        { get { return actPos_PTO1; } set { if (value != actPos_PTO1) { actPos_PTO1 = value; Change(nameof(ActPos_PTO1)); } } }
        private float actPos_PTO2;
        public float ActPos_PTO2
        { get { return actPos_PTO2; } set { if (value != actPos_PTO2) { actPos_PTO2 = value; Change(nameof(ActPos_PTO2)); } } }
        private float actPos_PTO3;
        public float ActPos_PTO3
        { get { return actPos_PTO3; } set { if (value != actPos_PTO3) { actPos_PTO3 = value; Change(nameof(ActPos_PTO3)); } } }
        private float actPos_PTO4;
        public float ActPos_PTO4
        { get { return actPos_PTO4; } set { if (value != actPos_PTO4) { actPos_PTO4 = value; Change(nameof(ActPos_PTO4)); } } }
        private float actPos_PTO5;
        public float ActPos_PTO5
        { get { return actPos_PTO5; } set { if (value != actPos_PTO5) { actPos_PTO5 = value; Change(nameof(ActPos_PTO5)); } } }
        private float actPos_PTO6;
        public float ActPos_PTO6
        { get { return actPos_PTO6; } set { if (value != actPos_PTO6) { actPos_PTO6 = value; Change(nameof(ActPos_PTO6)); } } }
        private float actPos_PTO7;
        public float ActPos_PTO7
        { get { return actPos_PTO7; } set { if (value != actPos_PTO7) { actPos_PTO7 = value; Change(nameof(ActPos_PTO7)); } } }
        private float actPos_PTO8;
        public float ActPos_PTO8
        { get { return actPos_PTO8; } set { if (value != actPos_PTO8) { actPos_PTO8 = value; Change(nameof(ActPos_PTO8)); } } }
        #region 方法:属性改变通知
        /*
         *internal class PlcDate: INotifyPropertyChanged            //INotifyPropertyChanged 通知客户端属性值已更改
         * 建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
         */

        public event PropertyChangedEventHandler? PropertyChanged;//建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
        public void Change(string PropertyName)
        { 
            if (PropertyChanged != null) 
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
        #endregion 方法:属性&值改变通知
    }
}
  1. 开始数据交互


 private void BtnS7OpenLink_Click(object sender, EventArgs e)
        {
            S71200 = new Plc(CpuType.S71200, txtAddress.Text, Convert.ToInt16(txtRack.Text), Convert.ToInt16(txtSlot.Text));
            if (!S71200.IsConnected)
            {
                try { S71200.Open(); }
                catch (Exception ex)
                { MessageBox.Show(ex.Message); }
            }
            if (S71200.IsConnected)//通讯建立,建立多线程交互数据
            {
                try
                {
                    Task.Run(() =>
                    {
                        while (true)
                        {
                            /*以下属性值受  属性改变通知  影响,会改变主线程的UI。
                             * 多线程运行的程序是不能直接修改主线程UI的
                             */
                            this.Invoke(new Action(() =>   //  调用   this.Invoke(new Action(() => {******}));    可以修改主线程UI            
                            {
                                if (S71200.IsConnected)
                                {
#pragma warning disable CS8605 // 取消装箱可能为 null 的值。
                                    plcDate.ActPos_PN1 = ((uint)S71200.Read("DB61.DBD0")).ConvertToFloat();
                                    plcDate.ActPos_PN2 = ((uint)S71200.Read("DB61.DBD4")).ConvertToFloat();
                                    plcDate.ActPos_PN3 = ((uint)S71200.Read("DB61.DBD8")).ConvertToFloat();
                                    plcDate.ActPos_PN4 = ((uint)S71200.Read("DB61.DBD12")).ConvertToFloat();
                                    S71200.ReadClass(weightDate, 21);
#pragma warning restore CS8605 // 取消装箱可能为 null 的值。
                                }
                            }));
                            Thread.Sleep(200);
                        }
                    });
                }
                catch (Exception ex) { MessageBox.Show(ex.Message); }
                MessageBox.Show("通讯成功" + S71200.IP);
            }
            else { MessageBox.Show("连接失败"); }
        }

在本项目中,该类中数据是设备的轴实际位置数据,需要在窗口中设置对应 label 控件来显示实际位置

该处位置显示用上了数据绑定的方法


        public LinkControl()//初始化程序段落
        {
            InitializeComponent();
            #region 轴数据数据绑定
            labelPosX1.DataBindings.Add("Text", plcDate, "ActPos_PN1");
            labelPosY1.DataBindings.Add("Text", plcDate, "ActPos_PN3");
            labelPosX2.DataBindings.Add("Text", plcDate, "ActPos_PN2");
            labelPosY2.DataBindings.Add("Text", plcDate, "ActPos_PN4");
            #endregion 轴数据数据绑定 
        }

在这个数据绑定中我们不难发现 labelPosX1 的 Text 属性值是string,而ActPos_PN1的数据属性是float ,这两者值属性不同是不能直接绑定的,因此调用了一个当属性发生改变时,强制将 float 属性转变成 string ,然后把值赋予 labelPosX1.Text ,该方法函数如下,使用方法上面代码中也有展示。


        #region 方法:属性改变通知
        /*
         *internal class PlcDate: INotifyPropertyChanged            //INotifyPropertyChanged 通知客户端属性值已更改
         * 建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
         */

        public event PropertyChangedEventHandler? PropertyChanged;//建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
        public void Change(string PropertyName)
        { 
            if (PropertyChanged != null) 
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
        #endregion 方法:属性&值改变通知

这个 IF 的的判断可以帮助我门在变量值改变时才启动数据转化操作,如果没有这种判断会损耗性能,加大程序的工作量。

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Envis_liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值