当前位置:   article > 正文

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

c# s7.net

001准备工作

  1. 准备工作安装Visual Studio 2022

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

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

点击该选项

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

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

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

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. 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。

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

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

  1. //创建可以自定义CPU类型和IP地址的实例化
  2. 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. 创建你想要交互的实体类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using S7.Net;//西门子通讯驱动包
  11. using S7.Net.Types;
  12. namespace S7LinkTest
  13. {
  14. internal class PlcShowDate: INotifyPropertyChanged//建立PlcDate的class ,并未其赋予接口属性(属性改变通知)
  15. {
  16. private float actPos_PN1;
  17. public float ActPos_PN1
  18. {get{ return actPos_PN1; }set{if (value != actPos_PN1){ actPos_PN1 = value; Change(nameof(ActPos_PN1)); }}}
  19. private float actPos_PN2;
  20. public float ActPos_PN2
  21. {get { return actPos_PN2; }set { if (value != actPos_PN2) { actPos_PN2 = value; Change(nameof(ActPos_PN2)); } }}
  22. private float actPos_PN3;
  23. public float ActPos_PN3
  24. {get { return actPos_PN3; }set { if (value != actPos_PN3) { actPos_PN3 = value; Change(nameof(ActPos_PN3)); } }}
  25. private float actPos_PN4;
  26. public float ActPos_PN4
  27. {get { return actPos_PN4; }set { if (value != actPos_PN4) { actPos_PN4 = value; Change(nameof(ActPos_PN4)); } }}
  28. private float actPos_PTO1;
  29. public float ActPos_PTO1
  30. { get { return actPos_PTO1; } set { if (value != actPos_PTO1) { actPos_PTO1 = value; Change(nameof(ActPos_PTO1)); } } }
  31. private float actPos_PTO2;
  32. public float ActPos_PTO2
  33. { get { return actPos_PTO2; } set { if (value != actPos_PTO2) { actPos_PTO2 = value; Change(nameof(ActPos_PTO2)); } } }
  34. private float actPos_PTO3;
  35. public float ActPos_PTO3
  36. { get { return actPos_PTO3; } set { if (value != actPos_PTO3) { actPos_PTO3 = value; Change(nameof(ActPos_PTO3)); } } }
  37. private float actPos_PTO4;
  38. public float ActPos_PTO4
  39. { get { return actPos_PTO4; } set { if (value != actPos_PTO4) { actPos_PTO4 = value; Change(nameof(ActPos_PTO4)); } } }
  40. private float actPos_PTO5;
  41. public float ActPos_PTO5
  42. { get { return actPos_PTO5; } set { if (value != actPos_PTO5) { actPos_PTO5 = value; Change(nameof(ActPos_PTO5)); } } }
  43. private float actPos_PTO6;
  44. public float ActPos_PTO6
  45. { get { return actPos_PTO6; } set { if (value != actPos_PTO6) { actPos_PTO6 = value; Change(nameof(ActPos_PTO6)); } } }
  46. private float actPos_PTO7;
  47. public float ActPos_PTO7
  48. { get { return actPos_PTO7; } set { if (value != actPos_PTO7) { actPos_PTO7 = value; Change(nameof(ActPos_PTO7)); } } }
  49. private float actPos_PTO8;
  50. public float ActPos_PTO8
  51. { get { return actPos_PTO8; } set { if (value != actPos_PTO8) { actPos_PTO8 = value; Change(nameof(ActPos_PTO8)); } } }
  52. #region 方法:属性改变通知
  53. /*
  54. *internal class PlcDate: INotifyPropertyChanged //INotifyPropertyChanged 通知客户端属性值已更改
  55. * 建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
  56. */
  57. public event PropertyChangedEventHandler? PropertyChanged;//建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
  58. public void Change(string PropertyName)
  59. {
  60. if (PropertyChanged != null)
  61. {
  62. PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
  63. }
  64. }
  65. #endregion 方法:属性&值改变通知
  66. }
  67. }
  1. 开始数据交互

  1. private void BtnS7OpenLink_Click(object sender, EventArgs e)
  2. {
  3. S71200 = new Plc(CpuType.S71200, txtAddress.Text, Convert.ToInt16(txtRack.Text), Convert.ToInt16(txtSlot.Text));
  4. if (!S71200.IsConnected)
  5. {
  6. try { S71200.Open(); }
  7. catch (Exception ex)
  8. { MessageBox.Show(ex.Message); }
  9. }
  10. if (S71200.IsConnected)//通讯建立,建立多线程交互数据
  11. {
  12. try
  13. {
  14. Task.Run(() =>
  15. {
  16. while (true)
  17. {
  18. /*以下属性值受 属性改变通知 影响,会改变主线程的UI。
  19. * 多线程运行的程序是不能直接修改主线程UI的
  20. */
  21. this.Invoke(new Action(() => // 调用 this.Invoke(new Action(() => {******})); 可以修改主线程UI
  22. {
  23. if (S71200.IsConnected)
  24. {
  25. #pragma warning disable CS8605 // 取消装箱可能为 null 的值。
  26. plcDate.ActPos_PN1 = ((uint)S71200.Read("DB61.DBD0")).ConvertToFloat();
  27. plcDate.ActPos_PN2 = ((uint)S71200.Read("DB61.DBD4")).ConvertToFloat();
  28. plcDate.ActPos_PN3 = ((uint)S71200.Read("DB61.DBD8")).ConvertToFloat();
  29. plcDate.ActPos_PN4 = ((uint)S71200.Read("DB61.DBD12")).ConvertToFloat();
  30. S71200.ReadClass(weightDate, 21);
  31. #pragma warning restore CS8605 // 取消装箱可能为 null 的值。
  32. }
  33. }));
  34. Thread.Sleep(200);
  35. }
  36. });
  37. }
  38. catch (Exception ex) { MessageBox.Show(ex.Message); }
  39. MessageBox.Show("通讯成功" + S71200.IP);
  40. }
  41. else { MessageBox.Show("连接失败"); }
  42. }

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

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

  1. public LinkControl()//初始化程序段落
  2. {
  3. InitializeComponent();
  4. #region 轴数据数据绑定
  5. labelPosX1.DataBindings.Add("Text", plcDate, "ActPos_PN1");
  6. labelPosY1.DataBindings.Add("Text", plcDate, "ActPos_PN3");
  7. labelPosX2.DataBindings.Add("Text", plcDate, "ActPos_PN2");
  8. labelPosY2.DataBindings.Add("Text", plcDate, "ActPos_PN4");
  9. #endregion 轴数据数据绑定
  10. }

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

  1. #region 方法:属性改变通知
  2. /*
  3. *internal class PlcDate: INotifyPropertyChanged //INotifyPropertyChanged 通知客户端属性值已更改
  4. * 建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
  5. */
  6. public event PropertyChangedEventHandler? PropertyChanged;//建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
  7. public void Change(string PropertyName)
  8. {
  9. if (PropertyChanged != null)
  10. {
  11. PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
  12. }
  13. }
  14. #endregion 方法:属性&值改变通知

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/290114
推荐阅读
相关标签
  

闽ICP备14008679号