使用PLCcom.dll操作西门子系列PLC
工作中经常需要了解plcdb块的数据!由于工作使用OPC类库进行通讯,开发,配置,使用都比较麻烦,
特在网上找到一个名为PLCcom.dll的类库,可以实现PLC读写操作,下面演示C#如何使用PLCcom.dll类库
首先看一下封装对PLCcom调用的帮助类:
using System; using PLCcom; using System.Data; //using System.Windows.Forms; namespace GetPlcInfo { /// <summary> /// Description of PLCReadWriteHelper. /// </summary> public class PLCReadWriteHelper { #region 变量定义 private static PLCReadWriteHelper instance=null;//当前类实例 private ePLCType cpu = ePLCType.S7_300_400_compatibel;//cpu类型 private string ip = "192.168.150.201";//CpuIP private short rack = 0;//机架号 private short slot = 3;//插槽号 public TCP_ISO_Device plc = null;//Plc对象 private const string user = "111";//用户 private const string serial = "51135-21193-754111-1111111";//系列号 public delegate void OnErrorHandler(OnErrorEventArgs e);//发生错误委托 public event OnErrorHandler OnError;//发生错误事件 public delegate void SuccessHandler(SuccessedEventArgs e);//成功委托 public event SuccessHandler success;//成功事件 #endregion #region 构造函数 public PLCReadWriteHelper(ePLCType type,string plcip,string plcRack,string plcsolt) { this.cpu=ePLCType.S7_300_400_compatibel; this.ip=plcip; this.rack=short.Parse( plcRack ); this.slot=short.Parse( plcsolt ); plc=new TCP_ISO_Device(ip,rack,slot,cpu); authentication.User=user; authentication.Serial =serial ; } #endregion #region 连接 public void TestConnect() { try { if (instance!=null) { ConnectResult cr=plc.Connect(); //连接失败 if (!cr.HasConnected) { if (OnError!=null) { OnError (new OnErrorEventArgs(string.Format("连接到PLC:{0}时,发生错误!{1}",this.ip,cr.Message))); } } //成功! else { if(success!=null) { success(new SuccessedEventArgs("PLC"+this.ip+"连接成功!"+cr.Message)); } } } } catch(Exception ex) { WriteError("连接失败:"+ex.Message); } } public void disconnect() { plc.DisConnect(); } #endregion #region 获取时间 public DateTime GetCpuTime() { if (instance == null) { instance = GetInstance(ePLCType.Other,"192.168.0.4", "0", "1"); instance.plc.Connect(); } ReadRequest[] request = new ReadRequest[1]; request[0] = new ReadRequest(); request[0].Region = eRegion.DataBlock; request[0].StartByte = 0; request[0].Len = 37; request[0].DB = 10; ReadResult[] res = plc.read(request); if (!res[0].HasWorked) { WriteError("读取CPU时间失败:" + res[0].Message); return DateTime.MinValue; } else { return res[0].get_DATE_AND_TIME(); } } #endregion #region 获得当前类的实例 /// <summary> /// 静态方法获得此帮助类的实例 /// </summary> /// <param name="type">cpu类型</param> /// <param name="plcip">ip地址</param> /// <param name="plcRack">机架号</param> /// <param name="plcsolt">插槽号</param> /// <returns></returns> public static PLCReadWriteHelper GetInstance(ePLCType type,string plcip,string plcRack,string plcsolt)//此处偷了个懒写了最简单的单例,此处线程不安全! { lock (typeof(PLCReadWriteHelper)) { if (instance == null) { instance = new PLCReadWriteHelper(type,plcip,plcRack,plcsolt ); return instance; } else { return instance; } } } #endregion #region 读PLC信息 public byte[] ReadPLC(int db,int Start,int Length) { byte[]readbytes=null; try{ if (this.plc==null) { plc=new TCP_ISO_Device (ip,rack,slot,cpu); plc.Connect(); } ReadRequest[]request=new ReadRequest[1] ; request[0]=new ReadRequest (); request[0].Region=eRegion.DataBlock; request[0].DB=db; request[0].StartByte=Start; request[0].Len=Length; ReadResult[]res=plc.read(request); if (!res[0].HasWorked) { this.plc=null; } readbytes=new byte[res[0].getBufferLen()]; int index=0; while (res[0].dataAvailable()) { readbytes[index++]+=res[0].get_Byte(); } plc.DisConnect(); if (success !=null) { success(new SuccessedEventArgs("读取CPU信息成功!")); string result = null; foreach(var n in readbytes) { result+=n.ToString()+"|"; } if(result!=null) { success(new SuccessedEventArgs(result)); } } return readbytes; } catch(NullReferenceException) { return null; } catch(Exception ex) { WriteError("读取指定信息错误:"+ex.Message); return null; } } #endregion #region 写信息到DB块 public WriteResult WritePLC(int db,int Start,byte[]wValue) { try { if (plc==null) { plc=new TCP_ISO_Device (ip,rack,slot,cpu); plc.Connect(); } WriteRequest[]writes=new WriteRequest[1]; writes[0]=new WriteRequest (); writes[0].Region=eRegion.DataBlock; writes[0].DB=db; writes[0].StartByte=Start; writes[0].addByte(wValue); WriteResult[]wrs=plc.write(writes ); if (wrs[0].HasWorked != true) { this.plc = null; } return wrs[0]; } catch (Exception ex) { WriteError("写入信息错误:"+ex.Message); return new WriteResult (); } } #endregion #region 抛出异常 void WriteError(string errmsg) { if (OnError!=null) { OnError(new OnErrorEventArgs (errmsg)); } } #endregion #region byte数组转换为字 public int[]ConvertToints(byte[]bt) { try { int []result = new int[(bt.Length / 2)]; for (int ii = 0; ii < result.Length; ii++) { result[ii] = Convert.ToInt16(bt[ii * 2]) * 256 + Convert.ToInt16(bt[ii * 2 + 1]); } return result; } catch(Exception ex) { WriteError("字节数组转换成int数组失败:"+ex.Message); return null; } } #endregion #region 自定义事件类 /// <summary> /// 发生错误 /// </summary> public class OnErrorEventArgs { string errMsg=string.Empty; public OnErrorEventArgs(string errmsg) { this.errMsg=errmsg; } public string ErrMsg {get{return this. errMsg;} } } /// <summary> /// 成功 /// </summary> public class SuccessedEventArgs { string errMsg=string.Empty; public SuccessedEventArgs(string errmsg) { this.errMsg=errmsg; } public string ErrMsg { get{return this. errMsg;} } } #endregion #region 读取IO public DateTime GetTime() { ReadResult rs= plc.GetPLCTime(); DateTime dt= rs.get_DATE_AND_TIME(); return dt; } public void readIO() { ReadRequest[] re = new ReadRequest[1]; re[0].Region = eRegion.Input; re[0].Bit = 1; re[0].StartByte = 253; re[0].Len = 1; ReadResult []rr= plc.read(re); if ( rr[0].isBit) { // MessageBox.Show(rr[0].Buffer.ToString()); } } #endregion public LEDInfoResult GetLEDINFO() { return plc.GetLEDInfo(); } } }
下面看看如何进行调用:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using Gaofajin.LogWrite; namespace GetPlcInfo { class Program { static Timer t; static TimerCallback tc; static int time = 50; static PLCReadWriteHelper helper; static string last; // public static object TxtLog { get; private set; } static void Main(string[] args) { if(args.Length<=0) { Console.WriteLine("必须输入IP地址:"); return; } if(args.Length==2) { int.TryParse(args[1],out time); } helper=new PLCReadWriteHelper(PLCcom.ePLCType.S7_300_400_compatibel,args[0],"0","2");//此示例演示的PLC为300系列故此处写死槽号2,机架号0 helper.OnError+=new PLCReadWriteHelper.OnErrorHandler(error); helper.success+=new PLCReadWriteHelper.SuccessHandler(success); tc=new TimerCallback(getContent); t=new Timer(tc,helper,0,time); Console.WriteLine("后台程序捕获进程运行中!请勿关闭程序!"); Console.ReadLine(); } private static void success(PLCReadWriteHelper.SuccessedEventArgs e) { Console.WriteLine(e.ErrMsg); } private static void error(PLCReadWriteHelper.OnErrorEventArgs e) { Console.WriteLine(e.ErrMsg); } private static void getContent(object obj) { try { t.Change(-1,-1); helper.TestConnect(); byte[]bts= helper.ReadPLC(53,20,51); string str = null; foreach(byte b in bts) { str+=byteTostringChar(b).ToString()+"|"; } if(last!=str) { TxtLog.WriteLineToTimeFile(str); } last=str; } catch(Exception ex) { // Console.WriteLine("发生错误:"+ex.Message); } finally { t.Change(0,time); } } public static char byteTostringChar(byte b) { return ((Char)b); } } }