C#与西门子PLC通讯 您所在的位置:网站首页 西门子plc基本数据类型实例图 C#与西门子PLC通讯

C#与西门子PLC通讯

2024-04-01 23:52| 来源: 网络整理| 查看: 265

提示1:参照本文,你可以快速搭建一个通讯交互实例,并完成一个项目演示用例。 提示2:如果你第一次来,请跳转到C#与西门子PLC通讯——新手快速入门了解背景信息。

关键词1:C#,.Net Core,S7 Net Plus,TIA Portal V17,PLCSIM Advanced V4,S7-1500。 关键词2:数据类型对照,DBX,DBB,DBW,DBD,面向对象编程,WinForm程序。

代码已同步至: Gitee:https://gitee.com/lukailin/sim-s71500 Github:https://github.com/Millance/SimS71500

自定义对象运行效果

文章目录 前言一、PLC与C# 基础数据类型1.1 数据类型对照表1.2 C# 读写PLC数据1.2.1 Plc.Read方法源码浅析1.2.2 PLC 中增加数据类型1.2.3 C# 读取PLC中不同类型的数据1.2.4 读取的代码解析1.2.4.1 基本数据类型的读取方法1.2.4.2 大端存储和小端存储的问题1.2.4.3 C# 读取中文乱码的问题 1.2.5 C# 写入PLC中不同类型的数据1.2.6 写入的代码解析 二、自定义数据类型2.1 自定义数据类型的创建2.2 C#读写自定义数据类型2.3 C#面向对象的模式读写PLC的自定义数据类型 三、WinForm项目示例3.1 新建项目3.1.1 新建窗体项目3.1.2 项目中添加S7NetPlus NuGet包 3.2 PLC连接测试功能3.2.1 添加PLC连接用的控件3.2.2 创建一个单例模式的PLC控制对象3.2.3 窗体中的PLC控制类的调用 3.3 读写PLC指定地址功能3.3.1 继续添加控件3.3.2 增加读写反馈类3.3.3 PLC控制类中增加读写操作3.3.4 窗体功能中调用PLC控制类的读写操作 3.4 读写PLC自定义数据类型功能3.4.1 增加有立体效果的自定义控件3.4.2 继续添加其他控件3.4.3 添加自定义数据类型相应的对象3.4.5 窗体中自定义类的读写操作 3.5 最终运行效果 总结

前言

翌日,斯电气之士大喜,言已成通讯之试,访吾欲构一物。余默思片刻,书此以为之。

本文基于C# .Net Core和西门子博图TIA Portal V17搭建。由于手边没有西门子PLC实物,所以采用S7-PLCSIM Advanced V4.0作为模拟PLC,以实现0成本完成通讯测试实例。 在实际通讯中,往往需要先确定地址,数据类型和读写规则。因此本文将侧重分析数据类型的读写,以及处理读写过程中容易出现的问题,并且扩展了在交互过程中遇到陌生数据类型的处理方式。 最后本文以一个桌面小程序抛砖引玉,重点实现了熟手需要学习的面向对象编程、设计模式和界面设计。

一、PLC与C# 基础数据类型 1.1 数据类型对照表

这个对应关系主要取决于PLC与C#之间进行数据交换或通信时,确保数据的一致性和正确性。因此需要定义一种映射关系,以便在两个系统之间传递数据时能够正确地解释和处理数据。 常用的对照关系如下:

PLC 数据类型C# 数据类型字节数Boolbool1/8Bytebyte1Charchar1Intshort2Wordushort2DIntint4DWorduint4Realfloat4LIntlong8LRealdouble8LWordulong8Stringstring256Array[0…n] of TypeType[n]n × \times × Type

不同数据类型在内存中占据不同的字节数。为了确保数据在两个系统之间传递时不会出现字节对齐、数据截断或者正负符号等问题,需要定义字节数对应关系。例如,一个PLC的Int类型在C#中被映射为short,因为它们都占据2个字节的内存空间。 Array[0…n] of Type中,需要根据Type的实际类型和数组长度n进行计算。 另外,其他的数据类型对照可以从字节数和有无符号的角度进行思考,字节数接近的可以进行尝试。

详细的PLC数据类型请参考西门子的在线帮助文档:基本数据类型以及char 和 string 的定义等。 或博图自带的帮助文档: 博图String变量结构

1.2 C# 读写PLC数据 1.2.1 Plc.Read方法源码浅析

先来扒一下S7 Net Plus源码。 调用plc.Read("DB1.DBX0.0")方法,会进行入下面的源码。

/// /// 从PLC读取单个变量,接受输入字符串如"DB1.DBX0.0","DB20.DBD200","MB20","T45"等。 /// 如果读取不成功,请检查LastErrorCode或LastErrorString。 /// /// 输入字符串如"DB1.DBX0.0","DB20.DBD200","MB20","T45"等。 /// 返回包含值的对象。必须根据需要对该对象进行类型转换。如果没有读取到数据,将返回null。 /// public object? Read(string variable) { var adr = new PLCAddress(variable); return Read(adr.DataType, adr.DbNumber, adr.StartByte, adr.VarType, 1, (byte)adr.BitNumber); }

其中PLCAddress方法的代码如下:

namespace S7.Net { internal class PLCAddress { ... public PLCAddress(string address) { Parse(address, out dataType, out dbNumber, out varType, out startByte, out bitNumber); } public static void Parse(string input, out DataType dataType, out int dbNumber, out VarType varType, out int address, out int bitNumber) { ... switch (input.Substring(0, 2)) { case "DB": string[] strings = input.Split(new char[] { '.' }); if (strings.Length 7) throw new InvalidAddressException("Bit can only be 0-7"); varType = VarType.Bit; return; default: throw new InvalidAddressException(); } ... } } } }

从PLCAddress的Parse方法可以看到,类似plc.Read("DB1.DBX0.0")、plc.Read("DB1.DBW2")这些读取指定地址的方法只能准确支持特定数据类型,如:Bit(DBX)、Byte(DBB)、Word(DBW)、DWord(DBD)。当数据类型的长度相同时,也可以支持相同长度的其他数据类型,但无法满足所有可能的情况。

Read方法还可以重载为:

/// /// 读取并解码提供的“VarType”指定字节数的数据。 /// 可用于读取同一类型(如Word、DWord、Int等)的多个连续变量。 /// 如果读取不成功,请检查LastErrorCode或LastErrorString。 /// /// 存储区域的数据类型,可以是DB、Timer、Counter、Merker(内存)、Input、Output。 /// 存储区域的地址(如果要读取DB1,设置为1)。对于其他存储区域类型(计数器、定时器等),也必须设置此参数。 /// 起始字节地址。如果要读取DB1.DBW200,设置为200。 /// 要读取的变量类型 /// 比特地址。如果要读取DB1.DBX200.6,将此参数设置为6。 /// 变量的数量 /// /// 返回包含值的对象。必须根据需要对该对象进行类型转换。 public object? Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0) { int cntBytes = VarTypeToByteLength(varType, varCount); byte[] bytes = ReadBytes(dataType, db, startByteAdr, cntBytes); return ParseBytes(varType, bytes, varCount, bitAdr); }

同时,在public object? Read(string variable)中也可以看到,经过PLCAddress解析之后,也是调用的这个重载的Read方法。方法中的VarType可以选择众多类型,请自行探索。因此,一些无法用DBX、DBB、DBW和DBD进行读写的数据类型,可以用重载方法进行读写。

1.2.2 PLC 中增加数据类型

在博图软件中增加一些测试数据类型,如下: PLC 中增加数据类型

配置信息拷贝出来,方便参考:

名称数据类型偏移量起始值监视值布尔量Bool0.0falseFALSE整形量Int2.000数组字Array[0…9] of Word4.0读写BoolBool24.0falseTRUE读写ByteByte25.016#016#01读写CharChar26.0’ ’‘a’读写IntInt28.003读写WordWord30.016#016#0004读写DIntDInt32.005读写DWordDWord36.016#016#0000_0006读写RealReal40.00.07.7读写LIntLInt44.008读写LRealLReal52.00.09.9读写LWordLWord60.016#016#0000_0000_0000_0010读写StringString68.0‘’‘你好!Hello PLC!’

这一步不会的,请跳转到C#与西门子PLC通讯——新手快速入门。

1.2.3 C# 读取PLC中不同类型的数据

我们继续改造新手入门的演示程序。

using S7.Net; using System.Text; namespace SimS71500 { internal class Program { static void Main(string[] args) { // 解决:“'GBK' is not a supported encoding name.”的方法 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); Plc plc = new Plc(CpuType.S71500, "192.168.0.100", 0, 1); plc.Open(); // 接收键入的值 string inputKey = ""; //存储区域的地址 int dbArea = 1; Task readPLCTask = Task.Factory.StartNew(() => { while (plc.IsConnected && inputKey != "q") { Console.Clear(); // plc.Read 参数分别为数据块类型,数据块,偏移量,读取类型,读取长度 // 布尔量 Console.WriteLine("布尔量\t" + plc.Read(DataType.DataBlock, dbArea, 0, VarType.Bit, 1)); // 整形量 Console.WriteLine("整形量\t" + plc.Read(DataType.DataBlock, dbArea, 2, VarType.Int, 1)); // 数组字中的第一个元素 Console.WriteLine("数组字中的第一个元素\t" + plc.Read(DataType.DataBlock, 1, 4, VarType.Word, 1)); // 数组字中的剩余元素 short[] remainArr = (short[])plc.Read(DataType.DataBlock, 1, 6, VarType.Word, 9); Console.Write("数组字中的剩余元素\t"); for (int i = 0; i { while (plc.IsConnected && inputKey != "q") { Console.Clear(); // plc.Read 参数分别为数据块类型,数据块,偏移量,读取类型,读取长度 // 布尔量 Console.WriteLine("布尔量\t" + plc.Read(DataType.DataBlock, dbArea, 0, VarType.Bit, 1)); // 整形量 Console.WriteLine("整形量\t" + plc.Read(DataType.DataBlock, dbArea, 2, VarType.Int, 1)); // 数组字中的第一个元素 Console.WriteLine("数组字中的第一个元素\t" + plc.Read(DataType.DataBlock, 1, 4, VarType.Word, 1)); // 数组字中的剩余元素 short[] remainArr = (short[])plc.Read(DataType.DataBlock, 1, 6, VarType.Word, 9); Console.Write("数组字中的剩余元素\t"); for (int i = 0; i { while (plc.IsConnected && inputKey != "q") { // 布尔量 plc.Write(DataType.DataBlock, dbArea, 0, boolFlag);//false表示写入的值 // 整形量 plc.Write(DataType.DataBlock, dbArea, 2, iCount); // 数组字中的第一个元素 plc.Write(DataType.DataBlock, dbArea, 4, (short)(iCount * 2)); // 数组字中的剩余元素 short[] arrValues = new short[9]; // 你要写入的新值数组 for (int i = 0; i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有