using System; using System.Collections.Generic; using System.Linq; using System.Text; using Mesnac.Equips; namespace Mesnac.Equip.OMRON.HostLink.COM { /// /// 三菱通讯封装设备类 /// public class Equip : BaseEquip { private SerialPortFactory _serialPortFactory = null; //SerialPortFactory.GetInstance("00", "COM3", 9600, "Even", 7, "2", 1024); private bool _isOpen = false; //是否打开连接 /// /// 获取串口工厂 /// /// private SerialPortFactory GetSerialPortFactory() { Mesnac.Equips.Connection.COM.ConnType connType = (Mesnac.Equips.Connection.COM.ConnType)this.Main.ConnType; string stationNum = connType.StationNum; string portName = connType.PortName; int baudRate = connType.BaudRate; string parity = connType.Parity; int dataBits = connType.DataBits; string stopBits = connType.StopBits; int buffSize = connType.BuffSize; this._serialPortFactory = SerialPortFactory.GetInstance(stationNum, portName, baudRate, parity, dataBits, stopBits, buffSize); return this._serialPortFactory; } /// /// 打开PLC设备 /// /// public override bool Open() { lock (this) { try { if (this._isOpen == true || (_serialPortFactory != null && _serialPortFactory.MainSerialPort.IsOpen)) { return true; } this.State = false; this._serialPortFactory = this.GetSerialPortFactory(); this._serialPortFactory.MainSerialPort.Open(); if (!_serialPortFactory.MainSerialPort.IsOpen) { ICSharpCode.Core.LoggingService.Warn("PLC连接失败:串口未打开失败!"); this.State = false; return this.State; } else { this.State = true; this._isOpen = true; //Console.WriteLine("连接成功!"); return this.State; } } catch (Exception ex) { this.State = false; this._isOpen = false; Console.WriteLine(ex.Message); return this.State; } } } /// /// PLC数据读取方法 /// /// 要读取的块号 /// 要读取的起始字 /// 要读取的长度,最大255,超过255则不读取 /// /// public override bool Read(string block, int start, int len, out object[] buff) { lock (this) { buff = new object[len]; try { if (len > 256) { for (int i = 0; i < len; i++) { buff[i] = 0; } base.State = false; return false; } int maxOneLen = 20; //单次允许读取的最大长度,欧姆龙限制为20个字 int count = len / maxOneLen; //要读取的次数 int mod = len % maxOneLen; //剩余的长度 bool flag = true; //保存读取标志 for (int i = 0; i < count; i++) { object[] _buff = new object[maxOneLen]; flag = this.ReadByLen(block, start + i * maxOneLen, maxOneLen, out _buff); if (flag == false) { base.State = flag; return false; } for (int k = i * maxOneLen; k < (i + 1) * maxOneLen; k++) { buff[k] = _buff[k - i * maxOneLen]; } } if (mod > 0) { object[] _buff = new object[mod]; flag = this.ReadByLen(block, start + count * maxOneLen, mod, out _buff); if (flag == false) { base.State = flag; return false; } for (int k = count * maxOneLen; k < count * maxOneLen + mod; k++) { buff[k] = _buff[k - count * maxOneLen]; } } base.State = flag; return flag; } catch (Exception ex) { ICSharpCode.Core.LoggingService.Error(String.Format("读取PLC(OMRON)设备失败-({0})!", ex.Message)); base.State = false; return false; } } } /// /// 单次读取最长20个字的方法 /// /// 块号 /// 起始字 /// 长度,最长不超过100 /// 数据缓冲区,存放读取的数据 /// 读取成功返回true,读取失败返回false private bool ReadByLen(string block, int start, int len, out object[] buff) { lock (this) { buff = new object[len]; if (!this.Open()) { return false; } int state = len; int[] _buff = new int[len]; int iblock = Convert.ToInt32(block); //iblock = iblock + start; string result = this._serialPortFactory.Read(iblock, start, len, out _buff); if (result != "00") { ICSharpCode.Core.LoggingService.Warn("PLC读取失败:" + this.GetErrInfo(result)); this.State = false; return false; } else { this.State = true; } int iReadLen = len; if (iReadLen > state) { iReadLen = state; } for (int i = 0; i < iReadLen; i++) { int value = _buff[i]; if (value > ushort.MaxValue) { value = ushort.MaxValue - value; } buff[i] = value; } return true; } } private ushort ToValue(object obj, ushort defaultValue) { ushort result = 0; if (obj != null && obj != DBNull.Value && ushort.TryParse(obj.ToString(), out result)) { return result; } return defaultValue; } /// /// PLC数据写入方法 /// /// 要写入的块号 /// 起始字 /// 要写入PLC的数据 /// 写入成功返回true,失败返回false public override bool Write(int block, int start, object[] buff) { lock (this) { try { if (buff.Length > 256) { return false; } int len = buff.Length; int maxOneLen = 25; //单次允许读取的最大长度,OMRON限制为25个字 int count = len / maxOneLen; //要读取的次数 int mod = len % maxOneLen; //剩余的长度 bool flag = true; //保存写入标志 for (int i = 0; i < count; i++) { object[] _buff = new object[maxOneLen]; for (int k = i * maxOneLen; k < (i + 1) * maxOneLen; k++) { _buff[k - i * maxOneLen] = buff[k]; } flag = this.WriteMax25(block, start + i * maxOneLen, _buff); if (flag == false) { return false; } } if (mod > 0) { object[] _buff = new object[mod]; for (int k = count * maxOneLen; k < count * maxOneLen + mod; k++) { _buff[k - count * maxOneLen] = buff[k]; } flag = this.WriteMax25(block, start + count * maxOneLen, _buff); } return flag; } catch (Exception ex) { ICSharpCode.Core.LoggingService.Error(String.Format("写入PLC(OMRON)设备失败-({0})!", ex.Message)); //Console.WriteLine(ex.Message); return false; } } } /// /// 单次写入最多25个字至PLC /// /// 要写入的块号 /// 要写入的起始字 /// 要写入的数据 /// 写入成功返回true,失败返回false private bool WriteMax25(int block, int start, object[] buff) { lock (this) { if (!this.Open()) { return false; } int state = buff.Length; int[] _buff = new int[buff.Length]; for (int i = 0; i < buff.Length; i++) { int value = 0; int.TryParse(buff[i].ToString(), out value); _buff[i] = value; } string result = this._serialPortFactory.Write(block, start, _buff); if (result != "00") { ICSharpCode.Core.LoggingService.Error("PLC【欧姆龙】写入失败:" + this.GetErrInfo(result)); return false; } return true; } } /// /// 关闭PLC设备 /// public override void Close() { lock (this) { try { this._serialPortFactory.MainSerialPort.Close(); if (this._serialPortFactory.MainSerialPort.IsOpen) { ICSharpCode.Core.LoggingService.Warn("PLC【欧姆龙】关闭失败:端口处于打开状态"); } else { this.State = false; this._isOpen = false; //Console.WriteLine("关闭成功!"); } } catch (Exception ex) { ICSharpCode.Core.LoggingService.Error("PLC【欧姆龙】关闭失败:" + ex.Message); } } } #region 根据错误代码返回错误信息 /// 根据错误代码返回错误信息 /// /// 错误码 /// 错误信息 public string GetErrInfo(string errCode) { string result = "未知错误"; switch (errCode) { case "00": result = "正常完成!"; break; case "01": result = "在RUN模式下不可执行!"; break; case "02": result = "在MONITOR模式下不可执行"; break; case "04": result = "地址越界"; break; case "0B": result = "在PROGRAM模式下不可执行"; break; case "13": result = "FCS错误"; break; case "14": result = "格式错误"; break; case "15": result = "入口号数据错误"; break; case "16": result = "命令不支持"; break; case "18": result = "帧长度错误"; break; case "19": result = "不可执行"; break; case "23": result = "用户存储区写保护"; break; case "A3": result = "由于数据传送中FCS错误而终止"; break; case "A4": result = "由于数据传送中格式错误而终止"; break; case "A5": result = "由于数据传送中入口号数据错误而终止"; break; case "A8": result = "由于数据传送中帧长错误而终止"; break; default: result = "未知错误"; break; } return result; } #endregion } }