当前位置: 首页 > news >正文

南宁学网站开发上海互联网网站建设公司

南宁学网站开发,上海互联网网站建设公司,襄阳做淘宝网站推广,参考文献网站开发1、A-1E报文回顾 具体细节请看#xff1a; C#上位机与三菱PLC的通信03--MC协议之A-1E报文解析 C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试 2、为何要开发自己的通讯库 前面使用了第3方的通讯库实现了与三菱PLC的通讯#xff0c;实现了数据的读写#xff0c;对于通…1、A-1E报文回顾 具体细节请看 C#上位机与三菱PLC的通信03--MC协议之A-1E报文解析 C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试 2、为何要开发自己的通讯库 前面使用了第3方的通讯库实现了与三菱PLC的通讯实现了数据的读写对于通讯库我们只要引用并调用相关的方法即可实现目的为什么别人可以封装通讯库dll文件自己能不能做到当然可以但写一个通讯库需要非凡的技术需要考虑的东西很多比如扩展性通用性等等之类的。通过封装通讯库达到更高的层次想想别人使用自己的东西说明自己牛XXXX啊大师就是这样锻造出来的接下来马上安排鸿鹄之志从小事做起振兴工业自动化匹夫有责。 3、空谈误国实干兴邦 1、创建vs项目 2、添加类库项目 3、创建目录及基础类  AreaCode.cs代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace Mitsubishi.Communication.MC.Mitsubishi.Base {/// summary/// 存储区枚举/// /summarypublic enum AreaCode{D 0xA8,X 0x9C,Y 0x9D,M 0x90,R 0xAF,S 0x98,TS 0xC1,CN 0xC5} }MelsecBase.cs代码 using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks;namespace Mitsubishi.Communication.MC.Mitsubishi.Base {/// summary/// mc协议基类/// /summarypublic class MelsecBase{/// summary/// plc的ip地址/// /summarypublic string _ip;/// summary/// plc的端口号/// /summarypublic int _port;/// summary/// socket对象/// /summarypublic Socket socket null;/// summary/// 超时事件/// /summaryManualResetEvent TimeoutObject new ManualResetEvent(false);/// summary/// 连接状态/// /summarybool connectState false;/// summary/// 构造方法/// /summary/// param nameip/param/// param nameport/parampublic MelsecBase(string ip, short port){_ip ip;_port port;// 初始化一个通信对象socket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);}/// summary/// 连接PLC/// /summary/// param nametimeout超时时间/param/// returns/returnspublic Result Connect(int timeout 50){TimeoutObject.Reset();Result result new Result();try{if (socket null){socket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);}int count 0;while (count timeout){if (!(!socket.Connected || (socket.Poll(200, SelectMode.SelectRead) (socket.Available 0)))){return result;}try{socket?.Close();socket.Dispose();socket null;socket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//异步连接 socket.BeginConnect(_ip, _port, callback {connectState false;var cbSocket callback.AsyncState as Socket;if (cbSocket ! null){connectState cbSocket.Connected;if (cbSocket.Connected){cbSocket.EndConnect(callback);}}TimeoutObject.Set();}, socket);TimeoutObject.WaitOne(2000, false);if (!connectState){throw new Exception();}else{break;}}catch (SocketException ex){if (ex.ErrorCode 10060){throw new Exception(ex.Message);}}catch (Exception ex){throw new Exception(ex.Message);}finally{count;}}if (socket null || !socket.Connected || ((socket.Poll(200, SelectMode.SelectRead) (socket.Available 0)))){throw new Exception(网络连接失败);}}catch (Exception ex){result.IsSuccessed false;result.Message ex.Message;}return result;}/// summary/// 构建开始地址/// /summary/// param nameareaCode存储区/param/// param namestartAddr开始地址/param/// returns/returns/// exception crefException/exceptionpublic Listbyte StartToBytes(AreaCode areaCode, string startAddr){Listbyte startBytes new Listbyte();if (areaCode AreaCode.X || areaCode AreaCode.Y){string str startAddr.ToString().PadLeft(8, 0);for (int i str.Length - 2; i 0; i - 2){string v str[i].ToString() str[i 1].ToString();startBytes.Add(Convert.ToByte(v, 16));}}else{int addr 0;if (!int.TryParse(startAddr, out addr)){throw new Exception(软元件地址不支持);}startBytes.Add((byte)(addr % 256));startBytes.Add((byte)(addr / 256 % 256));startBytes.Add((byte)(addr / 256 / 256 % 256));startBytes.Add((byte)(addr / 256 / 256 / 256 % 256));}return startBytes;}/// summary/// 发送报文/// /summary/// param namereqBytes字节集合/param/// param namecount字节长度/param/// returns/returnspublic virtual Listbyte Send(Listbyte reqBytes, int count){return null;}/// summary/// 数据解析/// /summary/// typeparam nameT读取的数据类型/typeparam/// param namedatas数据列表/param/// param nametypeLen类型长度/param/// returns/returns/// exception crefException/exceptionpublic ListT AnalysisDatasT(Listbyte datas, int typeLen){ListT resultDatas new ListT();if (typeof(T) typeof(bool))//bool类型{for (int i 0; i datas.Count; i){// 10 10 10 10 10string binaryStr Convert.ToString(datas[i], 2).PadLeft(8, 0);dynamic state binaryStr.Substring(0, 4) 0001;resultDatas.Add(state);state binaryStr.Substring(4) 0001;resultDatas.Add(state);}}else//其他类型ushort,short,float{for (int i 0; i datas.Count;){Listbyte valueByte new Listbyte();for (int sit 0; sit typeLen * 2; sit){valueByte.Add(datas[i]);}Type tBitConverter typeof(BitConverter);MethodInfo method tBitConverter.GetMethods(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(mi mi.ReturnType typeof(T)) as MethodInfo;if (method null){throw new Exception(未找到匹配的数据类型转换方法);}resultDatas.Add((T)method?.Invoke(tBitConverter, new object[] { valueByte.ToArray(), 0 }));}}return resultDatas;}/// summary/// 计算长度/// /summary/// typeparam nameT读取的数据类型/typeparam/// returns/returnspublic int CalculatLengthT(){int typeLen 1;if (!typeof(T).Equals(typeof(bool))){typeLen Marshal.SizeOfT() / 2;// 每一个数据需要多少个寄存器}return typeLen;}/// summary/// 获取数据的字节列表/// /summary/// typeparam nameT数据类型/typeparam/// param namevalues数据列表/param/// returns/returnspublic Listbyte GetDataBytesT(ListT values){Listbyte datas new Listbyte();int count values.Count;if (typeof(T) typeof(bool))//bool类型的数据{dynamic value false;// 添加一个填充数据保存一个完整字节if (values.Count % 2 0){values.Add(value);}for (int i 0; i values.Count; i 2){byte valueByte 0;if (bool.Parse(values[i].ToString())){valueByte | 16;}if (bool.Parse(values[i 1].ToString())){valueByte | 1;}datas.Add(valueByte);}}else //其他类型floatshortint16{for (int i 0; i values.Count; i){dynamic value values[i];datas.AddRange(BitConverter.GetBytes(value)); // MC不需要字节的颠倒}}return datas;}} }Result.cs代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace Mitsubishi.Communication.MC.Mitsubishi.Base {/// summary/// 结果类/// /summary/// typeparam nameT/typeparampublic class ResultT{/// summary/// 状态/// /summarypublic bool IsSuccessed { get; set; }/// summary/// 对应的消息/// /summarypublic string Message { get; set; }/// summary/// 数据列表/// /summarypublic ListT Datas { get; set; }public Result() : this(true, OK) { }public Result(bool state, string msg) : this(state, msg, new ListT()) { }public Result(bool state, string msg, ListT datas){this.IsSuccessed state; Message msg; Datas datas;}}public class Result : Resultbool { } }确保上面的三个类文件编译成功继续干 4、编写核心的通信类A1E.cs  A1E.cs完整代码  using Mitsubishi.Communication.MC.Mitsubishi.Base; using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading.Tasks;namespace Mitsubishi.Communication.MC.Mitsubishi {/// summary/// A1E报文通讯库/// /summarypublic class A1E : MelsecBase{/// summary/// 构造方法/// /summary/// param nameip/param/// param nameport/parampublic A1E(string ip, short port) : base(ip, port){}#region 读取数据/// summary/// 读取数据/// /summary/// typeparam nameT读取的数据类型/typeparam/// param nameaddress开始地址/param/// param namecount读取长度/param/// returns/returnspublic ResultT ReadT(string address, short count){AreaCode areaCode;string start;(areaCode, start) this.AnalysisAddress(address);return ReadT(areaCode, start, count);}/// summary/// 读取数据/// /summary/// typeparam nameT读取的数据类型/typeparam/// param nameareaCode存储区代码/param/// param namestartAddr开始地址/param/// param namecount读取长度/param/// returns/returnspublic ResultT ReadT(AreaCode areaCode, string startAddr, short count){ResultT result new ResultT();try{var connectState this.Connect();if (!connectState.IsSuccessed){throw new Exception(connectState.Message);}//读取类型byte readCode (byte)(typeof(T) typeof(bool) ? 0x00 : 0x01);//起始地址Listbyte startBytes this.StartToBytes(areaCode, startAddr);//存储区代码Listbyte areaBytes this.AreaToBytes(areaCode);//读取长度int typeLen this.CalculatLengthT();//组装报文Listbyte command new Listbyte {readCode,///读取类型0xFF,0x0A,0x00,//0xFF指PLC编号0x0A,0x00指超时时间超时时间是以250ms为单位 startBytes[0],startBytes[1],startBytes[2],startBytes[3], // 起始地址占4个字节areaBytes[0],areaBytes[1], // 存储区占2个字节(byte)(typeLen*count%256),// 读取长度低位(byte)(typeLen*count/256%256) // 读取长度高位};//计算响应报文的长度int respLen typeLen * 2 * count;if (typeof(T) typeof(bool)){respLen (int)Math.Ceiling(typeLen * count * 1.0 / 2);}//发送报文Listbyte respBytes this.Send(command, respLen);//数据解析result.Datas this.AnalysisDatasT(respBytes, typeLen);}catch (Exception ex){result new ResultT(false, ex.Message);}return result;}#endregion #region 写入数据/// summary/// 写数据/// /summary/// typeparam nameT写入的数据类型/typeparam/// param namevalues数据值列表/param/// param nameaddr开始地址/param/// returns/returnspublic Result WriteT(ListT values, string addr){AreaCode areaCode; string start;(areaCode, start) this.AnalysisAddress(addr);return this.WriteT(values, areaCode, start);}/// summary/// 写数据/// /summary/// typeparam nameT写入的数据类型/typeparam/// param namevalues数据值列表/param/// param nameareaCode存储区代码/param/// param namestartAddr开始地址/param/// returns/returnspublic Result WriteT(ListT values, AreaCode areaCode, string startAddr){Result result new Result();try{var connectState this.Connect();if (!connectState.IsSuccessed){throw new Exception(connectState.Message);}// 写操作的类型 //0x00 批量位读取 //0x01 批量字读取 //0x02 批量位写入 //0x03 批量字写入 //0x04 随机位写入 //0x05 随机字写入byte writeCode (byte)(typeof(T) typeof(bool) ? 0x02 : 0x03);//开始地址Listbyte startBytes this.StartToBytes(areaCode, startAddr);//存储区代码Listbyte areaBytes this.AreaToBytes(areaCode);//构建数据的字节列表int count values.Count;Listbyte datas this.GetDataBytesT(values);//判断写入的长度如果是float类型则长度要扩大2倍int length count;//长度等于值的个数 if (typeof(T) typeof(float)){length length * 2;}//拼装报文Listbyte command new Listbyte {writeCode,0xFF, 0x0A, 0x00,//0xFF指PLC编号0x0A,0x00指超时时间超时时间是以250ms为单位 startBytes[0], startBytes[1], startBytes[2], startBytes[3], // 起始地址areaBytes[0], areaBytes[1], // 存储区 //写入的长度的低位和高位 (byte)(length % 256),(byte)(length / 256 % 256),};command.AddRange(datas);//写入的具体数据//发送报文socket.Send(command.ToArray());// 判断写入的结果 byte[] respBytes new byte[2];socket.Receive(respBytes);if (respBytes[0] ! (writeCode | 0x80)){throw new Exception(响应报文结构异常。 respBytes[0].ToString());}if (respBytes[1] ! 0x00){throw new Exception(响应异常。 respBytes[1].ToString());}}catch (Exception ex){result.IsSuccessed false;result.Message ex.Message;}return result;}#endregion#region PLC启停,区别功能码 0x13,0x14public Result Run(){return PlcState(0x13);}public Result Stop(){return PlcState(0x14);}private Result PlcState(byte commandCode){Result result new Result();try{var connectState this.Connect();if (!connectState.IsSuccessed){throw new Exception(connectState.Message);}Listbyte commandBytes new Listbyte{commandCode,0xFF,0x0A,0x00};socket.Send(commandBytes.ToArray());// 先判断响应状态byte[] respBytes new byte[2];socket.Receive(respBytes);if (respBytes[0] ! (commandCode | 0x80)){throw new Exception(响应报文结构异常。 respBytes[0].ToString());}if (respBytes[1] ! 0x00){throw new Exception(响应异常。 respBytes[1].ToString());}}catch (Exception ex){result.IsSuccessed false;result.Message ex.Message;}return result;}#endregion#region 内部方法/// summary/// 构建存储区代码/// /summary/// param nameareaCode存储区代码/param/// returns/returnsprivate Listbyte AreaToBytes(AreaCode areaCode){Listbyte areaBytes new Listbyte();string areaStr areaCode.ToString();areaBytes.AddRange(Encoding.ASCII.GetBytes(areaStr));if (areaBytes.Count 1){areaBytes.Add(0x20);}areaBytes.Reverse(); //字节反转return areaBytes;}/// summary/// 发送报文/// /summary/// param namereqBytes报文字节集合/param/// param namelen报文字节长度/param/// returns/returns/// exception crefException/exceptionpublic override Listbyte Send(Listbyte reqBytes, int len){socket.Send(reqBytes.ToArray()); //发送报文// 先判断响应状态byte[] respBytes new byte[2];socket.Receive(respBytes);if (respBytes[0] ! (reqBytes[0] | 0x80)){throw new Exception(响应报文结构异常。 respBytes[0].ToString());}if (respBytes[1] ! 0x00){throw new Exception(响应异常。 respBytes[1].ToString());}respBytes new byte[len];socket.Receive(respBytes, 0, len, SocketFlags.None);return new Listbyte(respBytes);}/// summary/// 地址解析输入的地址X100 X1A0 M100 D100 TN10/// /summary/// param nameaddress地址字符串/param/// returns返回元组/returnspublic TupleAreaCode, string AnalysisAddress(string address){// 取两个字符string area address.Substring(0, 2);if (!new string[] { TN, TS, CS, CN }.Contains(area)){area address.Substring(0, 1);}string start address.Substring(area.Length);// 返回元组一个对象该对象包括编号和地址var obj new TupleAreaCode, string((AreaCode)Enum.Parse(typeof(AreaCode), area), start);return obj;}#endregion } }确保项目编译成功可以进行下一步 4、测试通讯库 1、添加项目引用     2、启动MC服务器  3、利用通讯库读写数据 1 读取X区100开始的4个bool数据 2、读取D区100开始的5个float数据 3、读取M区200开始的2个short数据 4、写入M区200开始的2个short数据  5、写入D区200开始的5个float数据  4、完整代码 using Mitsubishi.Communication.MC.Mitsubishi; using Mitsubishi.Communication.MC.Mitsubishi.Base; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace Mitsubishi.Communication.Test {internal class Program{static void Main(string[] args){MCLibTestA1E(); Console.WriteLine(执行完成!);Console.ReadKey();}/// summary/// 测试A-1E通讯库/// /summarystatic void MCLibTestA1E(){A1E a1E new A1E(192.168.1.7, 6000);#region 读数据Console.WriteLine(读取X区100开始的4个bool数据);var result1 a1E.Readbool(AreaCode.X, 100, 4);if (result1.IsSuccessed){result1.Datas.ForEach(d Console.WriteLine(d));}else{Console.WriteLine(result1.Message);}Console.WriteLine(读取D区200开始的5个float数据);var result2 a1E.Readfloat(AreaCode.D, 200, 5);if (result2.IsSuccessed){result2.Datas.ForEach(d Console.WriteLine(d));}else{Console.WriteLine(result2.Message);}Console.WriteLine(读取M区200开始的2个short数据);var result3 a1E.Readshort(AreaCode.M, 200, 2);if (result3.IsSuccessed){result3.Datas.ForEach(d Console.WriteLine(d));}else{Console.WriteLine(result3.Message);}#endregion#region 写数据Console.WriteLine(写入M区200开始的2个short数据);var result4 a1E.Writeshort(new Listshort { 61, 72 }, M200);if (result4.IsSuccessed){Console.WriteLine(result4.Message);}Console.WriteLine(写入D区200开始的5个float数据);var result5 a1E.Writefloat(new Listfloat { 3.2f, -2.5f, 0, 35, -98 }, D200);if (result5.IsSuccessed){Console.WriteLine(result5.Message);}#endregion}} }5、小结 原创真的不容易走过路过不要错过点赞关注收藏又圈粉共同致富。 原创真的不容易走过路过不要错过点赞关注收藏又圈粉共同致富。 原创真的不容易走过路过不要错过点赞关注收藏又圈粉共同致富
http://www.ho-use.cn/article/10819635.html

相关文章:

  • 域名做非法网站wordpress+h5幻灯片
  • 学畅留学招聘网站开发主管ps软件免费下载安装
  • 成都网站建设索q479185700杭州网络
  • 鹰潭市网站建设公司ftp网站服务器
  • 廊坊网站建设推广服务北京百度推广投诉电话
  • html5 手机 网站目前网站软件
  • 营口电商平台网站建设免费flash网站源码带后台
  • 在线海报设计网站哪个网站可以做封面
  • 北京最好的网站建设多国语言网站
  • 金华网站建设yw126互联网行业最有前景的十大职业
  • 深圳做二维码网站设计嵌入式软件开发工程师待遇
  • wordpress主题识别南宁seo 网站收录
  • 通辽网站设计网站建设 阳江
  • 百度网站地址提交软件下载网站免费大全
  • 铁岭免费移动网站建设免费域名freenom
  • 手机网站对企业用户的好处河南新乡做网站公司
  • 国外大神的平面设计网站有哪些初中生怎么做网站
  • 微信公众号开发是否需要建立网站官方网站建设银行信用卡
  • 深圳网站设计与制作公司wordpress文章多个分类显示不出来
  • cms网站设计国外开源 企业网站
  • 青岛响应式网站设计公司网站制作需要什么步骤
  • 设计logo网站推荐网站推广怎么做优化
  • 电影网站膜拜一般小程序开发多少钱
  • 移动端网站建设的尺寸汕头网站设计价格
  • 推荐郑州网站建设公司优秀vi设计网站
  • 公司网站建设外包流程图湖南宁乡建设局网站
  • 电子商务网站建设培训课件中国最新军事新闻最新消息视频
  • 外贸营销网站建设介绍在哪进入网站后台
  • 天津营销类网站设计做fpga的网站
  • 网站搭建实训总结知乎怎么申请关键词推广