本文章旨在说明TwinCAT3的ADS通讯应用,利用C#对倍福中常见数据类型(INT、BOOL、STRING、WSTRING、ARRAY、STRUCT等)变量进行读写操作。 (备注:此部分大家可以前往倍福虚拟学堂进行学习: https://tr.beckhoff.com.cn/course/view.php?id=150) 本例中采用按变量名方式进行读写调试。其具体实现方法如下: 建立c#的项目工程、Twincat3 项目工程,在c#中实现对Twincat3 中的变量进行读写。 在C#工程中引入 TwinCAT.Ads.dll 库文件(此文件可到BECKHOFF官网下载) 1)TC3变量创建 2)设计Form 4)连接PLC 5)创建句柄 6)释放句柄 TwinCAT.Ads.dll 库文件中提供了多个重载读写方法,本例中主要运用演示了: 1)ReadAny/WriteAny 实现 2)Read/Write 实现 WSTRING的读写 值得注意的是,如果在C#中直接将WSTING通过string字符串的形式进行读写,会存在乱码问题,此问题的具体解决方案如下: step1: {attribute ‘TcEncoding’:=‘UTF-8’} 的用法参照:https://infosys.beckhoff.com/english.php?content=…/content/1033/tc3_plc_intro/5873680907.html&id=6249601214176997827 step2: 关于此处,本人也尝试用WriteAny进行实现,但是总会遇到编码解码不完全,或者写入TC3时覆盖不完全等问题,所以弃用了WriteAny方法,如有读者利用WriteAny测试成功,还请留言指点(抱拳)。 链接:https://pan.baidu.com/s/12ly_fzMBRk7I5DQUUQTV6Q 后记:笔者才疏学浅,如有错误,望读者指正。
TC3与C#ADS通讯进行数据读写
1. TwinCAT ADS技术
2. ADS通讯方式及命令参数
2.1 ADS通讯方式
2.2 ADS命令参数
3. 程序实现
step1 建立工程
step2 添加引用
step3 前期工作
TYPE StructAxis : STRUCT Triggle: BOOL:=TRUE; Velocity: LREAL:=200; //Acceleration: LREAL; //Jrek: LREAL; //Deceleration: LREAL; //Done: BOOL; //Busy: BOOL; //Error: BOOL; //ErrorID: LREAL; END_STRUCT END_TYPE PROGRAM MAIN VAR //c# test Date_Int: INT:=10; Date_Bool: BOOL:=FALSE; Date_Array: ARRAY[0..2] OF INT; Date_Struct: StructAxis; Date_string: STRING:='Made by dashuaixiaoping'; {attribute 'TcEncoding':='UTF-8'} Date_wstring: STRING:=wsLiteral_TO_UTF8("大帅小平制作"); END_VAR
本例添加以下控件进行调试:(比较粗糙,请忽略)
3)创建Adsclientpublic TcAdsClient _client = new TcAdsClient();
_client.Connect(851);
public int _myIntHand = 0; public int _myBoolHand = 0; public int _myStringHand = 0; public int _myWstringHand = 0; public int _myArrayHand = 0; public int _myStructHand = 0; _myIntHand = _client.CreateVariableHandle("MAIN.Date_Int"); _myBoolHand = _client.CreateVariableHandle("MAIN.Date_Bool"); _myStringHand = _client.CreateVariableHandle("Main.Date_string"); _myWstringHand = _client.CreateVariableHandle("Main.Date_wstring"); _myArrayHand = _client.CreateVariableHandle("Main.Date_Array"); _myStructHand = _client.CreateVariableHandle("Main.Date_Struct");
//释放句柄 _client.DeleteVariableHandle(_myIntHand); _client.DeleteVariableHandle(_myBoolHand); _client.DeleteVariableHandle(_myStringHand); _client.DeleteVariableHandle(_myWstringHand); _client.DeleteVariableHandle(_myArrayHand); _client.DeleteVariableHandle(_myStructHand);
step4 开始读写
public object ReadAny(int variableHandle, Type type, int[] args); public int Read(int variableHandle, AdsStream dataStream, int offset, int length); public void WriteAny(int variableHandle, object value, int[] args); public void Write(int variableHandle, AdsStream dataStream, int offset, int length);
//读 //INT rInttb.Text = _client.ReadAny(_myIntHand, typeof(short)).ToString(); //BOOL rBooltb.Text = _client.ReadAny(_myBoolHand, typeof(bool)).ToString(); //STRING rStrtb.Text = _client.ReadAny(_myStringHand, typeof(string), new int[] { 16 }).ToString(); //WSTRING Encoding defaultEncoding = Encoding.Default; //当前系统默认用"BGK"进行解码与编码 Encoding utf8Encoding = Encoding.UTF8; string temStr = _client.ReadAny(_myWstringHand, typeof(string), new int[] { 32 }).ToString(); byte[] tempBytes = defaultEncoding.GetBytes(temStr); //解码:将字符、符号等转换为二进制机器语言 string str = utf8Encoding.GetString(tempBytes); //编码:将二进制机器语言转换为字符、符号等 rWstrtb.Text = str; //ARRAY short[] tempArr = (short[])_client.ReadAny(_myArrayHand, typeof(short[]), new int[] { 4 }); rArr0tb.Text = tempArr[0].ToString(); rArr1tb.Text = tempArr[1].ToString(); rArr2tb.Text = tempArr[2].ToString(); //STRUCT Mystruct struct1 = (Mystruct)_client.ReadAny(_myStructHand, typeof(Mystruct)); rStruct1tb.Text = struct1.Triggle.ToString(); rStruct2tb.Text = struct1.Velocity.ToString(); //写 //INT _client.WriteAny(_myIntHand, Convert.ToInt16(wInttb.Text)); //BOOL _client.WriteAny(_myBoolHand, Convert.ToBoolean(wBooltb.Text)); //STRING _client.WriteAny(_myStringHand, wStrtb.Text, new int[] { 16 }); //WSTRING string str = wWstrtb.Text; byte[] tempBytes = Encoding.UTF8.GetBytes(str); _client.WriteAny(_myWstringHand,tempBytes); //ARRAY short[] temArr = new short[3]; temArr[0] = short.Parse(wArr0tb.Text); temArr[1] = short.Parse(wArr1tb.Text); temArr[2] = short.Parse(wArr2tb.Text); _client.WriteAny(_myArrayHand, temArr); //STRUCT Mystruct tempStruct = new Mystruct(); tempStruct.Triggle = Boolean.Parse(wStruct1tb.Text); tempStruct.Velocity = double.Parse(wStruct2tb.Text); _client.WriteAny(_myStructHand, tempStruct);
这里用到stream类,其具体含义与用法可参考博文:C# 温故而知新:Stream篇(—)。//读 AdsStream rStream = new AdsStream(100); AdsBinaryReader reader = new AdsBinaryReader(rStream); //INT _client.Read(_myIntHand, rStream); rStream.Seek(0, System.IO.SeekOrigin.Begin); //初始化流的当前位置( 等效于stream.Position = 0;) rInttb.Text = reader.ReadInt16().ToString(); //读取两位数,同时position后移两位(ReadInt16的作用) //BOOL _client.Read(_myBoolHand, rStream); rStream.Seek(0, System.IO.SeekOrigin.Begin); rBooltb.Text = reader.ReadBoolean().ToString(); //ARRAY _client.Read(_myArrayHand, rStream); rStream.Seek(0, System.IO.SeekOrigin.Begin); rArr0tb.Text = reader.ReadInt16().ToString(); rArr1tb.Text = reader.ReadInt16().ToString(); rArr2tb.Text = reader.ReadInt16().ToString(); //STRUCT _client.Read(_myStructHand, rStream); rStream.Seek(0, System.IO.SeekOrigin.Begin); rStruct1tb.Text = reader.ReadBoolean().ToString(); //因为struct中每个成员的数据类型不一样, //系统默认将读到的每个成员以成员中长度最长的位数存储在stream中 //如此处的结构体中成员长度最长的数据类型为Double(对于倍福中的LREAL),占8位 //所以需将stream向后移动8位 rStream.Seek(8, System.IO.SeekOrigin.Begin); rStruct2tb.Text = reader.ReadDouble().ToString(); //STRING _client.Read(_myStringHand, rStream); rStream.Seek(0, System.IO.SeekOrigin.Begin); rStrtb.Text = reader.ReadPlcString(81, Encoding.Default); //WSTRING _client.Read(_myWstringHand, rStream); rStream.Seek(0, System.IO.SeekOrigin.Begin); //在倍福那边将WSTRING定义成UTF8格式的STRING,C#中以byte[]形式读取,然后以UTF8编码 rWstrtb.Text = Encoding.UTF8.GetString(reader.ReadBytes(81)); //写 AdsStream wStream = new AdsStream(100); AdsBinaryWriter writer = new AdsBinaryWriter(wStream); //INT wStream.Seek(0, System.IO.SeekOrigin.Begin); writer.Write(short.Parse(wInttb.Text)); _client.Write(_myIntHand, wStream, 0, 2); //BOOL wStream.Seek(0, System.IO.SeekOrigin.Begin); writer.Write(Boolean.Parse(wBooltb.Text)); _client.Write(_myBoolHand, wStream, 0, 1); //ARRAY wStream.Seek(0, System.IO.SeekOrigin.Begin); writer.Write(Int16.Parse(wArr0tb.Text)); writer.Write(Int16.Parse(wArr1tb.Text)); writer.Write(Int16.Parse(wArr2tb.Text)); _client.Write(_myArrayHand, wStream, 0, 6); //STRUCT wStream.Seek(0, System.IO.SeekOrigin.Begin); writer.Write(Boolean.Parse(wStruct1tb.Text)); byte[] tempBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0 }; //占位,使得BOOL和Double都占位8个 writer.Write(tempBytes); writer.Write(Double.Parse(wStruct2tb.Text)); _client.Write(_myStructHand, wStream, 0, 16); //STRING wStream.Seek(0, System.IO.SeekOrigin.Begin); byte[] tempBytes1 = Encoding.Default.GetBytes(wStrtb.Text); writer.Write(tempBytes1); _client.Write(_myStringHand, wStream, 0, 81); //WSTRING wStream.Seek(0, System.IO.SeekOrigin.Begin); byte[] tempBytes2 = Encoding.UTF8.GetBytes(wWstrtb.Text); writer.Write(tempBytes2); _client.Write(_myWstringHand, wStream, 0, 81);
4. 注意事项
WSTRING是TC3中的变量,主要用于存放中文字符,其详细介绍请参考博文:
BECKHOFF TwinCAT3 常见问题2
在TC3中将带中文的字符的变量命名为UTF-8编码规则下的STRING型;如: {attribute 'TcEncoding':='UTF-8'} Date_wstring: STRING:=wsLiteral_TO_UTF8("大帅小平制作");
如需深入了解Unicode/UTF-8/UTF-16等解码编码问题可参考博文:
从字节理解Unicode(UTF8/UTF16)
在C#中接收string,然后用UTF-8进行编码,如下://Write方法 AdsStream rStream = new AdsStream(100); AdsBinaryReader reader = new AdsBinaryReader(rStream); _client.Read(_myWstringHand, rStream); rStream.Seek(0, System.IO.SeekOrigin.Begin); //在倍福那边将WSTRING定义成UTF8格式的STRING,C#中以byte[]形式读取,然后以UTF8编码 rWstrtb.Text = Encoding.UTF8.GetString(reader.ReadBytes(81));
5. 完整工程项目文件
提取码:aihx
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算