资讯详情

PLC通讯实现-C#实现AB5000 PLC以太网通讯DTL32(八)

PLC通讯实现-C#实现AB5000 PLC以太网通讯DTL32(八)

  • 背景
  • 抽象设计

背景

我过去十年的工作与工业软件有关,其中工业控制系统开发的必要环节之一是与主要制造商有关PLC通信,对于从互联网行业进入工业互联网行业的员工来说,要实现各种型号PLC通信仍然需要一个过程,我在这里对主流型号PLC总结通信实现,供大家参考。

抽象设计

首先,我们应该进行抽象设计。首先,我们应该设计一个抽象类(界面也可以,因为其他业务使用抽象类)BaseEquip,对PLC定义常规操作,即Open、Read、Write、Close,调用业务代码BaseEquip进行PLC读写,然后实现各种型号Equip类,对Open、Read、Write、Close在业务代码中根据配置实现BaseEquip实例化,以便以后更改PLC型号完成后,只需修改配置,无需修改业务代码。

#AB实现5000以太网通信DTL32

实现语言C#

抽象基类BaseEquip

public class BaseEquip { 
          /// <summary>     /// 打开设备     /// </summary>     /// <returns>成功返回true,失败返回false</returns>  public abstract bool Open();  /// <summary>     /// 读取信息     /// </summary>     /// <param name="block">数据块</param>     /// <param name="start">起始地址</param>     /// <param name="len">长度</param>     /// <param name="buff">读取返回信息</param>     /// <returns>成功返回true,失败返回false</returns>     public abstract bool Read(string block, int start, int len, out object[] buff);     /// <summary>     /// 写入信息     /// </summary>     /// <param name="block">数据块</param>     /// <param name="start">起始地址</param>     /// <param name="buff">要写的数据</param>     /// <returns>成功返回true,失败返回false</returns>     public abstract bool Write(int block, int start, object[] buff);     /// <summary>     /// 关闭设备     /// </summary>     public abstract void Close(); } 

设备实现类Equip实现

using System; using System.IO;
using Mesnac.Equips;
using Mesnac.Equips.BaseInfo;
using System.Runtime.InteropServices;

namespace Mesnac.Equip.AllenBradley.AB5000.Net
{ 
        
    public class Equip : BaseEquip
    { 
        
        private IntPtr structToIntPtr<T>(T[] lst)
        { 
        
            int nSizeOfT = Marshal.SizeOf(typeof(T));
            int nSizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr));
            IntPtr Result = Marshal.AllocHGlobal(nSizeOfIntPtr * lst.Length);
            for (int i = 0; i < lst.Length; i++)
            { 
        
                Marshal.StructureToPtr(lst[i], (IntPtr)((UInt32)Result + i * nSizeOfIntPtr), true);
            }
            return Result;
        }
        private T[] IntPtrTostruct<T>(IntPtr p, T[] lst)
        { 
        
            int nSizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr));
            for (int i = 0; i < lst.Length; i++)
            { 
        
                T r = (T)Marshal.PtrToStructure((IntPtr)((UInt32)p + i * nSizeOfIntPtr), typeof(T));
                lst[i] = r;
            }
            return lst;
        }
        private string getDriveNameFileFullName()
        { 
        
            return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log", "AB5000.DriverName.bin");
        }
        private void saveDriveName(string name)
        { 
        
            if (string.IsNullOrWhiteSpace(name))
            { 
        
                return;
            }
            string path = getDriveNameFileFullName();
            FileInfo fi = new FileInfo(path);
            if (!fi.Directory.Exists)
            { 
        
                fi.Directory.Create();
            }
            if (fi.Exists)
            { 
        
                fi.Delete();
            }
            System.IO.StreamWriter sw = new System.IO.StreamWriter(fi.FullName, false);
            sw.WriteLine(name);
            sw.Close();
        }
        private string getDriveName()
        { 
        
            string path = getDriveNameFileFullName();
            FileInfo fi = new FileInfo(path);
            if (!fi.Directory.Exists)
            { 
        
                fi.Directory.Create();
            }
            if (!fi.Exists)
            { 
        
                return string.Empty;
            }
            System.IO.StreamReader sw = new System.IO.StreamReader(fi.FullName);
            string ss = sw.ReadToEnd();
            sw.Close();
            return ss;
        }
        public override bool Open()
        { 
        
            lock (this)
            { 
        
                getIP();
                this.State = false;
                ICSharpCode.Core.LoggingService.Info("DTL_INIT");
                int iResult = 0;
                uint id = 0;
                iResult = DTL32.DTL_INIT(2048);
                ICSharpCode.Core.LoggingService.Info("DTL_INIT Result=" + iResult.ToString());
                if ((iResult != 0) && (iResult != 39))  // 39已经初始化
                { 
        
                    this.State = false;
                    return this.State;
                }
                string driveName = getDriveName();
                if (string.IsNullOrWhiteSpace(driveName))
                { 
        
                    ICSharpCode.Core.LoggingService.Info("get szDriverName");
                    uint drivers = 0;
                    DTL32.DtlDriver[] dtlDriver = new DTL32.DtlDriver[16];
                    IntPtr pDriver = structToIntPtr<DTL32.DtlDriver>(dtlDriver);
                    ICSharpCode.Core.LoggingService.Info("DTL_DRIVER_LIST");
                    iResult = DTL32.DTL_DRIVER_LIST(pDriver, ref drivers, 1000);
                    ICSharpCode.Core.LoggingService.Info("DTL_DRIVER_LIST Result=" + iResult.ToString());
                    dtlDriver = IntPtrTostruct<DTL32.DtlDriver>(pDriver, dtlDriver);
                    ICSharpCode.Core.LoggingService.Info("IntPtrTostruct");
                    driveName = new string(dtlDriver[id].szDriverName);
                    ICSharpCode.Core.LoggingService.Info("szDriverName=" + driveName);
                    saveDriveName(driveName);
                    Marshal.FreeHGlobal(pDriver);
                    ICSharpCode.Core.LoggingService.Info("FreeHGlobal");
                    if ((iResult != 0))
                    { 
        
                        this.State = false;
                        return this.State;
                    }
                }
                iResult = DTL32.DTL_DRIVER_OPEN(id, driveName, 5000);
                ICSharpCode.Core.LoggingService.Info("DTL_DRIVER_OPEN Result=" + iResult.ToString());
                if ((iResult == 0) || (iResult == 47))  // 47已经连接上
                { 
        
                    this.State = true;
                }
                return this.State;
            }
        }
        private string getIP()
        { 
        
            string result = string.Empty;
            string ip = ((Mesnac.Equips.Connection.Net.ConnType)this.Main.ConnType).IP;
            int iplen = ip.Length;
            if (ip.Length % 2 != 0)
            { 
        
                iplen++;
            }
            result = iplen.ToString();
            foreach (char s in ip)
            { 
        
                result += "." + Convert.ToInt32(s).ToString();
            }
            if (ip.Length % 2 != 0)
            { 
        
                result += ".0";
            }
            return result;
        }
        public override bool Read(string block, int start, int len, out object[] buff)
        { 
        
            lock (this)
            { 
        
                buff = new object[len];
                if (!this.Open())
                { 
        
                    return false;
                }
                int state = 0;
                ushort[] _buff = new ushort[len];
                string ss = "$N" + block.ToString() + ":" + start.ToString() + "," +
                       len.ToString() + ",WORD,READ,AB:CIP,16." + getIP() + ".1.0,PLC5,0";
                ICSharpCode.Core.LoggingService.Info("DTL_C_DEFINE=" + ss);
                uint id = 0;
                int iResult = DTL32.DTL_C_DEFINE(ref id, ss);
                ICSharpCode.Core.LoggingService.Info("DTL_C_DEFINE Result=" + iResult.ToString());
                if (iResult != 0)
                { 
        
                    return false;
                }
                iResult = DTL32.DTL_READ_W(id, _buff, ref state, 1000);
                ICSharpCode.Core.LoggingService.Info("DTL_READ_W Result=" + iResult.ToString());
                DTL32.DTL_UNDEF(id);
                if (iResult != 0)
                { 
        
                    return false;
                }
                for (int i = 0; i < len; i++)
                { 
        
                    int value = _buff[i];
                    if (value > ushort.MaxValue)
                    { 
        
                        value = ushort.MaxValue - value;
                    }
                    buff[i] = value;
                }
                ICSharpCode.Core.LoggingService.Info("Read True");
                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;
        }
        public override bool Write(int block, int start, object[] buff)
        { 
        
            lock (this)
            { 
        
                if (buff.Length == 0)
                { 
        
                    return true;
                }
                ICSharpCode.Core.LoggingService.Info("Open");
                if (!this.Open())
                { 
        
                    return false;
                }
                int state = 0;
                ushort[] _buff = new ushort[buff.Length];
                for (int i = 0; i < buff.Length; i++)
                { 
        
                    _buff[i] = ToValue(buff[i], 0);
                }
                string ss = "$N" + block.ToString() + ":" + start.ToString() + "," +
                       buff.Length.ToString() + ",WORD,MODIFY,AB:CIP,16." + getIP() + ".1.0,PLC5,0";
                uint id = 0;
                int iResult = DTL32.DTL_C_DEFINE(ref id, ss);
                if (iResult != 0)
                { 
        
                    return false;
                }
                iResult = DTL32.DTL_WRITE_W(id, _buff, ref state, 1000);
                DTL32.DTL_UNDEF(id);
                if (iResult != 0)
                { 
        
                    return false;
                }
                return true;
            }
        }
        public override void Close()
        { 
        
            lock (this)
            { 
        
                try
                { 
        
                    DTL32.DTL_UNINIT(0);
                    DTL32.DTL_UNDEF(0);
                    DTL32.DTL_DRIVER_CLOSE(0, 100);
                }
                catch
                { 
        
                }
            }
        }
    }
}

DTL32类定义

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;

namespace Mesnac.Equip.AllenBradley.AB5000.Net
{ 
        
    public class DTL32
    { 
        
        public struct DtlDriver
        { 
        
            public ushort wType;
            public ushort wLength;
            public ushort wMfgMask;
            public ushort wNetworkType;
            public ushort wDriverID;
            public ushort wDstDriverID;
            public uint dwHandle;
            public uint dwStation;
            public uint dwMaxStation;
            public ushort wCapabilities;
            public ushort wMTU;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            public char[] szDriverName;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            public char[] szDriverAlias;
            public byte bAddrRadix;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public byte[] bReserved;
        }
        private class DllImport
        { 
        
            [DllImport("DTL32.dll")]
            public extern static int DTL_INIT(uint id);
            [DllImport("DTL32.dll")]
            public extern static int DTL_UNINIT(uint dwError);
            [DllImport("DTL32.dll")]
            public extern static int DTL_DRIVER_LIST(IntPtr dtlDriver, ref uint drivers, int timeout);
            [DllImport("DTL32.dll")]
            public extern static int DTL_DRIVER_OPEN(uint id, string name, int timeout);
            [DllImport("DTL32.dll")]
            public extern static int DTL_DRIVER_CLOSE(uint id, int timeout);
            [DllImport("DTL32.dll")]
            public extern static int DTL_C_DEFINE(ref uint id, StringBuilder defString);
            [DllImport("DTL32.dll")]
            public extern static int DTL_UNDEF(uint id);
            [DllImport("DTL32.dll")]
            public extern static int DTL_READ_W(uint name_id, ushort[] buff, ref int state, int timeout);
            [DllImport("DTL32.dll")]
            public extern static int DTL_WRITE_W(uint name_id, ushort[] buff, ref int state, int timeout);
        }

        public static int DTL_INIT(uint tableSize)
        { 
        
            new UIPermission(UIPermissionWindow.AllWindows).Demand();
            return DllImport.DTL_INIT(tableSize);
        }
        public static int DTL_UNINIT(uint dwError)
        { 
        
            new UIPermission(UIPermissionWindow.AllWindows).Demand();
            return DllImport.DTL_UNINIT(dwError);
        }
        public static int DTL_DRIVER_LIST(IntPtr dtlDriver, ref uint drivers, int timeout)
        { 
        
            new UIPermission(UIPermissionWindow.AllWindows).Demand();
            return DllImport.DTL_DRIVER_LIST(dtlDriver, ref drivers, timeout);
        }
        public static int DTL_DRIVER_OPEN(uint id, string name, int timeout)
        { 
        
            new UIPermission(UIPermissionWindow.AllWindows).Demand();
            return DllImport.DTL_DRIVER_OPEN(id, name, timeout);
        }
        public static int DTL_DRIVER_CLOSE(uint id, int timeout)
        { 
        
            new UIPermission(UIPermissionWindow.AllWindows).Demand();
            return DllImport.DTL_DRIVER_CLOSE(id, timeout);
        }
        public static int DTL_C_DEFINE(ref uint id, string defString)
        { 
        
            new UIPermission(UIPermissionWindow.AllWindows).Demand();
            StringBuilder def = new StringBuilder();
            def.Append(defString);
            return DllImport.DTL_C_DEFINE(ref id, def);
        }
        public static int DTL_UNDEF(uint id)
        { 
        
            new UIPermission(UIPermissionWindow.AllWindows).Demand();
            return DllImport.DTL_UNDEF(id);
        }
        public static int DTL_READ_W(uint name_id, ushort[] buff, ref int state, int timeout)
        { 
        
            new UIPermission(UIPermissionWindow.AllWindows).Demand();
            return DllImport.DTL_READ_W(name_id, buff, ref state, timeout);
        }
        public static int DTL_WRITE_W(uint name_id, ushort[] buff, ref int state, int timeout)
        { 
        
            new UIPermission(UIPermissionWindow.AllWindows).Demand();
            return DllImport.DTL_WRITE_W(name_id, buff, ref state, timeout);
        }
    }
}

完整案例下载

标签: allenbradley继电器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台