使用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);
}
}
}