C#各种PLC调用例子教程
前言
好久没发博文了,发了这么多的通讯协议源码,在此贴一下,PLC寄存器数据的读写程序,各种PLC都是换汤不换药的,至于如何标准起来,各位筒子们自行发挥,在此以西门子的PLC为例,贴上使用的源程序,读写各自以心跳为例,带上各种格式转换的方法程序。
声明变量
项目程序当中,正常是一个PLC CPU一个线程,所以举例以一个线程为例,这样不会占用太多的PLC CPU的通讯性能,防止PLC CPU的扫码周期边长,更有甚者,会导致看门狗直接挂掉
/// <summary>
/// PLC通讯线程
/// </summary>
Thread PlcLinkTd;/// <summary>
/// 西门子连接对象
/// </summary>
SimencePlcLinkHelper simenceLink;/// <summary>
/// PLC配置模型
/// </summary>
public static PlcEquipMentModel PlcModel;
下面贴一下PLC配置模型类的代码:
/// <summary>
/// PLC配置模型类
/// </summary>
public class PlcEquipMentModel
{/// <summary>/// PLC对应名称/// </summary>public string PlcName { get; set; }/// <summary>/// IP地址/// </summary>public string PlcIpAddr { get; set; }/// <summary>/// PLC端口/// </summary>public int PlcPort { get; set; }/// <summary>/// PLC型号300或者1200/// </summary>public int PLCSiemenceType { get; set; }/// <summary>/// PLC槽号/// </summary>public int SoltNo { get; set; }/// <summary>/// 连接标志位/// </summary>public bool LinkRes { get; set; }/// <summary>/// 连接状态/// </summary>public int link_Status { get; set; }
}
变脸声明完了需要进行一个初始化的一个操作,将变量赋值
/// <summary>
/// 初始化PLC的配置数据,可以做成配置文件进行加载
/// </summary>
private void InitialPlcConfig()
{PlcModel = new PlcEquipMentModel(){PlcName = "XXXXPLC",PlcIpAddr = "192.168.1.100",//PLC的IP地址PlcPort = 102,//西门子开放的OPC默认端口PLCSiemenceType = 1200,//1200系列PLC和1500可以公用一套通讯协议SoltNo = 0,//槽号正常是0 如果有带网口模块有可能是1LinkRes = false};
}
变量赋值完之后,我们程序运行起来就可以将线程启动,下面是线程启动的代码
/// <summary>
/// PLC通讯线程启动方法,可以在程序初始化完成之后启动
/// </summary>
private void TheadLoadStart()
{PlcLinkTd = new Thread(PlcLinkFunc);PlcLinkTd.Start();
}
再下面就是我们的一个PLC寄存器数据的一个读写线程
#region PLC线程处理
/// <summary>
/// PLC线程处理
/// </summary>
/// <param name="sender"></param>
private void PlcLinkFunc(object sender)
{Ping p = new Ping();simenceLink = new SimencePlcLinkHelper(PlcModel.PlcIpAddr, PlcModel.PlcPort, PlcModel.PLCSiemenceType, PlcModel.SoltNo);int check_plc_link = 0;int check_plc_link_1 = 0;int re_link = 0;int recordOnce = 0;while (_continue){try{if (!PlcModel.LinkRes){#region 连接PLCtry{if (p.Send(PlcModel.PlcIpAddr, 200).Status == IPStatus.Success){recordOnce = 0;simenceLink.CloseLinkPLC();Thread.Sleep(10);simenceLink = new SimencePlcLinkHelper(PlcModel.PlcIpAddr, PlcModel.PlcPort, PlcModel.PLCSiemenceType, PlcModel.SoltNo);bool res = simenceLink.OpenLinkPLC();if (res){PlcModel.LinkRes = true;if (check_plc_link == 0){check_plc_link = 1;string logStr = string.Format("PLC 连接成功");SaveLogStrRunTime(logStr);}}else{if (check_plc_link_1 == 0){check_plc_link_1 = 1;PlcModel.link_Status = -1;string logStr = string.Format("PLC 连接失败");SaveLogStrRunTime(logStr);}}}else{if (recordOnce == 0){recordOnce = 1;string logStr = string.Format("PLC 连接 失败 原因Ping异常");SaveLogStrRunTime(logStr);}PlcModel.link_Status = -2;PlcModel.LinkRes = false;}}catch (Exception ex){PlcModel.link_Status = -1;PlcModel.LinkRes = false;}#endregion}else{int RET = 0;#region 读值int readOnceLen = 200;#region 读取PLC部分寄存器值int[] PLC_UZ_W = new int[10];//用于存放读取上来的字节数据RET = simenceLink.ReadPlcDBValue(10, 100, 0, out PLC_UZ_W);//10表示读取的字节长度个数 100表示读取的DB块索引 DB100 0表示寄存器读取的起始偏移量 总的为读取DB100.DBB0读取10个字节数据if (RET != 0){goto MYEND;}#endregion#endregion//认定为读值成功PlcModel.link_Status = 1;re_link = 0;#region 此处做你需要的逻辑处理 读取的数据都存放在 PLC_UZ_W里面#endregionMYEND:if (RET != 0){re_link++;if (re_link > 3){re_link = 0;PlcDataAllLineModel = new PlcDataLineValue[DeviceConfigAll.Length];PlcModel.LinkRes = false;PlcModel.link_Status = -1;simenceLink.CloseLinkPLC();}}}}catch (Exception ex){SaveLogStrErr(ex.ToString());}Thread.Sleep(600);}
}
#endregion
以上就是西门子PLC CPU的一个寄存器数据读取的线程
下面说一下字节数组转换成不同的类型方法
1、字节数组转成PLC内部的DINT方法
/// <summary>
/// 字节数组转成PLC内部的DINT方法
/// </summary>
private int byteArr4ToDint(byte[] byteData)
{byte[] bt_0 = new byte[4]; for (int j = 0; j < bt_0.Length; j++){bt_0[j] = (byte)intValueArr[3 - j];}int intTemp = BitConverter.ToInt32(bt_0, 0).ToString();return intTemp;
}
2、字节数组转成PLC内部的INT方法
/// <summary>
/// 字节数组转成PLC内部的INT方法
/// </summary>
private int byteArr4ToDint(byte[] byteData)
{byte[] bt_0 = new byte[2]; for (int j = 0; j < bt_0.Length; j++){bt_0[j] = (byte)intValueArr[1 - j];}int intTemp = BitConverter.ToInt16(bt_0, 0).ToString();return intTemp;
}
3、字节数据转成二进制的方法
#region 十进制转二进制
/// <summary>
/// 十进制转二进制 低位在前 1就是10000000
/// </summary>
/// <param name="intIn"></param>
/// <returns></returns>
public string OctoberToBinaryStr(int intIn)
{string strIn = Convert.ToString(intIn, 2).PadLeft(8, '0');string strTemp = "";for (int i = 0; i < strIn.Length; i++){strTemp += strIn[strIn.Length - i - 1];}return strTemp;
}
#endregion