初识上位机(下):C#读写PLC数据块数据

plc · 浏览次数 : 0

小编点评

**引言** 本文介绍了如何使用C#编写一个简单的Windows Form窗体程序,实现S7 PLC的连接、数据读取和写入。 **程序设计** * 创建了一个Windows Form项目。 * 通过S7NetPlus库连接到PLC。 * 读取和写入数据块中的数据。 * 创建一个窗体应用界面,提供连接和断开PLC、读取和写入数据的功能。 **数据类型** * 针对bool和int类型,可以使用`Read`方法快速读取到,但需要告诉PLC准确的读写位置和数据类型。 * 针对string和wstring类型,需要先获取其长度后才能进行读取。 **代码示例** ```csharp // S7NETPlus组件 private static Plc s7Instance; // 窗体应用程序 public MainForm() { InitializeComponent(); InitializePLC(); } // 连接到PLC private void InitializePLC() { // 连接到PLC } // 读取数据 private void ReadData() { // 读取数据 } // 写数据 private void WriteData() { // 写数据 } ``` **效果演示** 该程序创建一个窗体应用程序,提供以下功能: * 连接到S7 PLC。 * 读取数据并将其显示在窗体中。 * 写数据并将其保存到PLC中。 **结论** 本文展示了如何使用C#编写一个简单的Windows Form窗体程序,实现了S7 PLC的连接、数据读取和写入。

正文

大家好,我是Edison。

作为一个工业自动化领域的程序员,不懂点PLC和上位机,貌似有点说不过去。这里我用两篇小文带你快速进入上位机开发领域。后续,我会考虑再出一个系列文章一起玩工控上位机。

上一篇:搭建PLC模拟仿真环境

复习一下

在上一篇中,我们通过PLCSIM Advanced软件创建了一个虚拟的西门子S7-1500 PLC如下所示:

然后,我们创建了一个博途的自动化项目,和我们的虚拟PLC进行了组态。在编译完成后,我们创建的数据块中的数据字段就得到了偏移量,如下图所示,0,2,4, 260就是所谓的偏移量,会在后面用到。

创建Windows Form项目

这里开始我们就开始使用C#创建一个Windows Form项目,然后通过S7NetPlus库来连接PLC,并读取和写入数据块中的数据,这是一个典型的上位机数据采集的场景。这里我们创建一个.NET Framework 4.8的Windows Form项目,并拖控件完成一个如下图所示的窗体应用界面:

这个窗体提供了连接和断开PLC,以及读取 和 写入 文本框中的数据,接下来我们就来实现这几个功能。

实现PLC的连接与断开

要实现S7 PLC的连接和操作,目前已经有很多较为成熟的组件了,我们这里使用S7NetPlus组件,直接通过NuGet安装最新版本即可。

然后编写Connect按钮的Click事件如下:

private static Plc s7Instance;

public MainForm()
{
  InitializeComponent();
}

private void btnConnect_Click(object sender, System.EventArgs e)
{
  if (btnConnect.Text == "Connect")
  {
    if (s7Instance == null)
      s7Instance = new Plc(CpuType.S71500, txtPlcIPAddress.Text.Trim(), 0, 1);

    s7Instance.Open();
    btnConnect.Text = "Disconnect";
  }
  else
  {
    s7Instance.Close();
    btnConnect.Text = "Connect";
    txtBool01.Clear();
    txtInt01.Clear();
    txtStr01.Clear();
    txtStr02.Clear();
  }
}

实现PLC数据块的读取

由于我们在博途项目中设置的数据块是DB01,且只有4个字段,所以这里我们编写ReadData按钮的Click事件如下,它通过指定参数读取到指定类型的数据并绑定到文本框的Text中。 

private void btnReadData_Click(object sender, System.EventArgs e)
{
  if (s7Instance == null || !s7Instance.IsConnected)
  {
    MessageBox.Show("Your PLC is not connected now!", "Error", MessageBoxButtons.OK);
    return;
  }

  // bool
  var boolData = (bool)s7Instance.Read(DataType.DataBlock, 1, 0, VarType.Bit, 1);
  txtBool01.Text = boolData ? "1" : "0";
  // int
  var intData = (short)s7Instance.Read(DataType.DataBlock, 1, 2, VarType.Int, 1);
  txtInt01.Text = intData.ToString();
  // string
  var count = (byte)s7Instance.Read(DataType.DataBlock, 1, 4 + 1, VarType.Byte, 1); // +1表示读取偏移值的长度
  var str01Data = Encoding.Default.GetString(s7Instance.ReadBytes(DataType.DataBlock, 1, 4 + 2, count)); // +2表示读取偏移值(跳过)的字符
  txtStr01.Text = str01Data;
  // wstring
  var str02Data = (string)s7Instance.Read(DataType.DataBlock, 1, 260, VarType.S7WString, 254);
  txtStr02.Text = str02Data;
}

要点解读:

(1)针对bool和int类型,我们可以直接通过Read方法快速读取到,但需要告诉PLC准确的读写位置和数据类型,主要是偏移量一定要给正确。

Read方法的参数分别为数据块类型,数据块,偏移量,读取类型,读取长度

(2)针对string和wstring类型,就稍微麻烦一些了:针对string,需要先获取string值的所占长度。再拿到具体byte值。转换为utf8格式的ascci码,具体代码中有体现。

+1 表示获取到长度

+2 表示获取到跳过偏移长度的字符

特别注意:string类型只能存储ascci码,需要注意,不能存储中文

针对wstring,稍微简单点,但是需要注意的是获取的字符需要为254个,因为符号占用了4个字节。

实现PLC数据块的写入

和读取一样,通过Write方法即可轻松实现写入,但针对string和wstring仍然是复杂一些,这里我封装了一个S7DataWriter的静态类,提供了两个方法来获取要写入的bytes,因为它无法直接接收C#程序中的string类型。

public static class S7DataWriter
{
  /// <summary>
  /// 获取西门子PLC字符串数组--String类型
  /// </summary>
  public static byte[] GetPlcStringByteArray(string str)
  {
    byte[] value = Encoding.Default.GetBytes(str);
    byte[] head = new byte[2];
    head[0] = Convert.ToByte(254);
    head[1] = Convert.ToByte(str.Length);
    value = head.Concat(value).ToArray();
    return value;
  }

  /// <summary>
  /// 获取西门子PLC字符串数组--WString类型
  /// </summary>
  public static byte[] GetPlcWStringByteArray(string str)
  {
    byte[] value = Encoding.BigEndianUnicode.GetBytes(str);
    byte[] head = BitConverter.GetBytes((short)508);
    byte[] length = BitConverter.GetBytes((short)str.Length);
    Array.Reverse(head);
    Array.Reverse(length);
    head = head.Concat(length).ToArray();
    value = head.Concat(value).ToArray();
    return value;
  }
}

然后,我们就可以编写Write Data按钮的Click事件了:

private void btnWriteData_Click(object sender, System.EventArgs e)
{
  if (s7Instance == null || !s7Instance.IsConnected)
  {
    MessageBox.Show("Your PLC is not connected now!", "Error", MessageBoxButtons.OK);
    return;
  }

  // bool
  var boolValue = txtBool01.Text.Trim() == "1" ? true : false;
  s7Instance.Write(DataType.DataBlock, 1, 0, boolValue);
  // int
  var intValue = Convert.ToInt16(txtInt01.Text);
  s7Instance.Write(DataType.DataBlock, 1, 2, intValue);
  // string
  s7Instance.Write(DataType.DataBlock, 1, 4, S7DataWriter.GetPlcStringByteArray(txtStr01.Text.Trim()));
  // wstring
  s7Instance.Write(DataType.DataBlock, 1, 260, S7DataWriter.GetPlcWStringByteArray(txtStr02.Text.Trim()));

  MessageBox.Show("Write data successfully!", "Info", MessageBoxButtons.OK);
}

效果演示

和读取一样,通过Write方法即可轻松实现写入,但针对string和wstring仍然是复杂一些,这里我封装了一个S7DataWriter的静态类,提供了两个方法来获取要写入的bytes,因为它无法直接接收C#程序中的string类型。

(1)读取数据

(2)写入数据

小结

本文通过使用C#开发了一个简单的WindowsForm窗体程序,实现了S7 PLC的连接、数据读取和写入。虽然只是一个简单的Demo,但是从中可以看见上位机的基本思想,就是对PLC的数据采集和监控。当然,实现这个目的,不止S7协议一条路,我们还可以通过ModBus、OPC UA等协议,这些就留到后面的专题吧,如果你感兴趣的话,就保持关注哦!

源码

GitHub:https://github.com/Coder-EdisonZhou/PLC-Connectors

 

与初识上位机(下):C#读写PLC数据块数据相似的内容:

初识上位机(下):C#读写PLC数据块数据

作为一个工业自动化领域的程序员,不懂点PLC和上位机,貌似有点说不过去。这里我用两篇小文带你快速进入上位机开发领域。上一篇,我们搭建了一个PLC的模拟仿真环境,本篇我们使用C#开发一个简单的PLC数据读取和写入的应用程序。

文章导读

Linux系统系列 Redis 初识Redis与桌面客户端 解读Redis常见命令 Redis持久化 (RDB和AOF) 梳理 JumpServer CentOS7下搭建JumpServer(v2.28.6) 堡垒机 JumpServer(v2.28.6) 堡垒机添加Linux资产 (图文教程) J

初识上位机(上):搭建PLC模拟仿真环境

作为一个工业自动化领域的程序员,不懂点PLC和上位机,貌似有点说不过去。这里我用两篇小文带你快速进入上位机开发领域。首先,我们先要搭建一个PLC的模拟仿真环境,以便后续能够使用C#开发上位机程序。

RHCE01-Redhat 8 的安装和初始配置

Redhat 8 的安装和初始配置 环境说明: 1.在VMWare Workstation上创建虚拟机安装RHEL 8先决条件:自己的物理机(电脑/工作站/服务器)的CPU的虚拟化功能要开启。Intel的CPU:Virtualization Technology(VT-x)AMD的CPU:SVM M

初识Redis与桌面客户端

Redis介绍 什么是Redis Redis(Remote Dictionary Server) 是一个使用 C 语言编写的,开源的(BSD许可)高性能非关系型(NoSQL)的键值对数据库。 Redis 可以存储键和五种不同类型的值之间的映射。键的类型只能为字符串,值支持五种数据类型:字符串、列表、

云图说丨初识云应用引擎CAE

摘要:开发运营一个应用软件,面临种种挑战:软件栈厚重、开发上线慢、资源易浪费、运维投入高、突发流量应对困难。 华为云应用引擎CAE面对挑战,一扫而光!! 本文分享自华为云社区《【云图说】 | 第266期 初识云应用引擎CAE》,作者: 阅识风云。 CAE(Cloud Application Engi

从零开始初识机器学习

本篇文章中我们将对机器学习做全面的了解与介绍,其中第一章 初识机器学习分为上下两个小章节,对机器学习是什么、机器学习由来以及机器学习的理论等展开说明。目的是能让即便完全没接触过机器学习的人也能在短时间对机器学习有一个全面了解。

学node 之前你要知道这些

初识nodejs 19年年底一个偶然的机会接到年会任务,有微信扫码登录、投票、弹幕等功能,于是决定用node 来写几个服务,结果也比较顺利。 当时用看了下koa2的官方文档,知道怎么连接数据库、怎么映射表实体,怎么处理http,怎么处理异常等,就可以直接写起来了。从应用层面上来说 nodejs 入门

[转帖]深入理解mysql-第十章 mysql查询优化-Explain 详解(上)

目录 一、初识Explain 二、执行计划-table属性 三、执行计划-id属性 四、执行计划-select_type属性 一条查询语句在经过MySQL查询优化器的各种基于成本和规则的优化会后生成一个所谓的执行计划,这个执行计划展示了接下来具体执行查询的方式,比如多表连接的顺序是什么,对于每个表采

云图说丨初识华为云安全云脑——新一代云安全运营中心

本文分享自华为云社区《【云图说】 | 第273期 初识华为云安全云脑——新一代云安全运营中心》,作者:阅识风云。 安全云脑(SecMaster)是华为云原生的新一代云安全运营中心,集华为云三十多年安全经验,基于云原生安全,提供云上资产管理、安全态势管理、安全信息和事件管理、安全编排与自动响应等能力,