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 如果有带网口模块有可能是1
        LinkRes = 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 连接PLC
                try
                {
                    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里面
                #endregion
				

            MYEND:
                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

  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工控程序狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值