001准备工作
-
准备工作安装visual studio 2022
-
新建一个基于 windows 的窗体应用,其余选项跟着下一步进行

-
获取s7.net 的函数库文件

点击该选项

检索,获得,安装 s7netplus 到你的项目中
-
引用 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数据交互
-
西门子plc处建立对应的db块




-
创建你想要交互的实体类

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 方法:属性&值改变通知
}
}
-
开始数据交互
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 的的判断可以帮助我门在变量值改变时才启动数据转化操作,如果没有这种判断会损耗性能,加大程序的工作量。
发表评论