PLC通讯实现-C#实现西门子PLC以太网通讯Sharp7(六)

本文介绍了作者在工业软件开发中如何通过C#实现与西门子PLC的以太网通讯,采用Sharp7库进行实现。文章提出了抽象设计思路,定义了一个基础类(BaseEquip)来封装Open、Read、Write、Close等基本操作,方便业务代码调用,并详细阐述了具体实现步骤和设备实现类(Equip)的构造。此外,还提供了完整的案例下载链接。
摘要由CSDN通过智能技术生成

PLC通讯实现-C#实现西门子PLC以太网通讯Sharp7(六)

背景

本人近十年的工作都与工业软件相关、其中工控系统开发过程中有一个必要环节就是跟各大厂商的PLC进行通讯,而对于从互联网行业跨入工业互联网行业的从业人员来说要实现各型号PLC通讯还是需要一个过程的,本人在此对主流型号PLC通讯实现进行总结以便大家参考。

抽象设计

首先我们要进行一下抽象设计,先设计一个抽象类(接口也可以,此处因为还有其他业务使用了抽象类)BaseEquip,对PLC的常规操作进行定义,即Open、Read、Write、Close,业务代码调用BaseEquip进行PLC的读写,然后在实现各型号的Equip类,对Open、Read、Write、Close进行实现,根据配置在业务代码中对BaseEquip进行实例化,这样后期更改PLC型号后,只需修改配置即可,不用修改业务代码。

西门子以太网通讯实现Sharp7

实现语言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.Runtime.InteropServices;
using System.Text;
using Mesnac.Equips;
using Mesnac.Equips.BaseInfo;

namespace Mesnac.Equip.Siemens.S7.Net
{
   
    /// <summary>
    /// 西门子S7系列以太网通讯类
    /// </summary>
    public class Equip : BaseEquip
    {
   
        #region 字段定义

        private string _ip = "192.168.0.250";       //PLC IP Address
        private int _rack = 0;                      //机架号
        private int _slot = 0;                      //槽号,1200~1500设置为0,300系列设置为2

        private bool _isOpen = false;   //是否打开连接
        private int _errorCount = 0;    //记录读取失败次数
        private int _openErrorCount = 0;    //打开PLC失败的次数
        private S7Client _client = new S7Client();

        private int[] _area = 
            {
    
                 S7Consts.S7AreaPE,
                 S7Consts.S7AreaPA,
                 S7Consts.S7AreaMK,
                 S7Consts.S7AreaDB,
                 S7Consts.S7AreaCT,
                 S7Consts.S7AreaTM
            };
        private int[] _wordLen =
            {
   
                 S7Consts.S7WLBit,
                 S7Consts.S7WLByte,
                 S7Consts.S7WLChar,
                 S7Consts.S7WLWord,
                 S7Consts.S7WLInt,
                 S7Consts.S7WLDWord,
                 S7Consts.S7WLDInt,
                 S7Consts.S7WLReal,
                 S7Consts.S7WLCounter,
                 S7Consts.S7WLTimer
            };

        #endregion

        #region 属性定义

        /// <summary>
        /// IP
        /// </summary>
        private string IP
        {
   
            get
            {
   
                
                return this._ip;
            }
        }

        /// <summary>
        /// 机架号
        /// </summary>
        private int Rack
        {
   
            get
            {
   
                return this._rack;
            }
        }

        /// <summary>
        /// 插槽号
        /// </summary>
        private int Slot
        {
   
            get
            {
   
                return this._slot;
            }
        }

        #endregion

        private int Swap(int a)
        {
   
            return (a >> 8 & 0xFF) + (a << 8 & 0xFF00);
        }

        #region 实现BaseEquip成员

        /// <summary>
        /// 建立与PLC的连接
        /// </summary>
        /// <returns></returns>
        public override bool Open()
        {
   
            lock (this)
            {
   
                if (this._isOpen == true)
                {
   
                    return true;
                }
                this.State = false;
                /
                int result = this._client.ConnectTo(this.IP, this.Rack, this.Slot);
                ///
                if (result != 0)
                {
   
                    Console.WriteLine("PLC连接失败:" + this.GetErrInfo(result));
                    this.State = false;
                    if (this._openErrorCount > 1)
                    {
   
                        System.Threading.Thread.Sleep(10000);   //2次连接不上暂停10秒
                        this._openErrorCount = 0;
                    }
                    this._openErrorCount++;
                    return this.State;
                }
                else
                {
   
                    Console.WriteLine("PLC连接成功!");
                    this.State = true;
                    this._isOpen = true;
                }
                return this.State;
            }
        }
        /// <summary>
        /// PLC数据读取方法
        /// </summary>
        /// <param name="block">要读取的块号</param>
        /// <param name="start">要读取的起始字</param>
        /// <param name="len">要读取的长度</param>
        /// <param name="buff"></param>
        /// <returns></returns>
        public override bool Read(string block, int start, int len, out object[] buff)
        {
   
            lock (this)
            {
   
                int sizeRead = 0;
                int iblock = Convert.ToInt32(block);
                buff = new object[len];
                for (int i = 0; i < len; i++)
                {
   
                    buff[i] = 0;
                }
                if (!this.Open())
                {
   
                    return false;
                }
                byte[] _buff = new byte[len * 2];
                int result = this._client.ReadArea(S7Consts.S7AreaDB, iblock, start * 2, len, S7Consts.S7WLInt, _buff, ref sizeRead);
                if (result != 0)
                {
   
                    Console.WriteLine(this.GetErrInfo(result) + "\t" + String.Format("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now));
                    if (this._errorCount > 5)
                    {
   
                        this.Close();       //5次读取失败,关闭PLC,再次读取自动连接
                    }
                    this._errorCount++;
                }
                if (sizeRead != len * 2)
                {
   
                    Console.WriteLine(String.Format("block={0}, start={1}, len={2} 读取的字节数与设置的字数不成2倍关系!", block, start, len));
                }
                else
                {
   
                    for (int i = 0; i < len; i++)
                    {
   
                        byte[] curr = new byte[2];
                        //高低位对调
                        //curr[0] = _buff[i * 2];
                        //curr[1] = _buff[i * 2 + 1];
                        //buff[i] = this.Swap(BitConverter.ToInt16(curr, 0));
                        curr[1] = _buff[i * 2];
                        curr[0] = _buff[i * 2 + 1];
                        buff[i] = BitConverter.ToInt16(curr, 0);
                    }
                    //ICSharpCode.Core.LoggingService<Equip>.Warn("内部处理完毕" + "\t" + String.Format("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now));
                }
                if (result != 0)
                {
   
                    return false;
                }
                else
                {
   
                    return true;
                }
            }
        }

        /// <summary>
        /// PLC数据写入方法
        /// </summary>
        /// <param name="block">要写入的块号</param>
        /// <param name="start">起始字</param>
        /// <param name="buff">要写入PLC的数据</param>
        /// <returns>写入成功返回true,失败返回false</returns>
        public override bool Write(int block, int start, object[] buff)
        {
   
            lock (this)
            {
   
                if (!this.Open())
                {
   
                    return false;
                }
                int iblock = Convert.ToInt32(block);
                int sizeWrite = 0;
                byte[] _buff = new byte[buff.Length * 2];
                for (int i = 0; i < buff.Length; i++)
                {
   
                    System.Int16 value = 0;
                    System.Int16.TryParse(buff[i].ToString(), out value);
                    byte[] curr = BitConverter.GetBytes(value);
                    //高低位对调
                    _buff[i * 2] = curr[1];
                    _buff[i * 2 + 1] = curr[0];
                }
                int result = this._client.WriteArea(S7Consts.S7AreaDB, iblock, start * 2, buff.Length, S7Consts.S7WLInt, _buff, ref sizeWrite);
                if (result != 0)
                {
   
                    Console.WriteLine(this.GetErrInfo(result) + "\t" + String.Format("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now));
                }

                if (sizeWrite != buff.Length * 2)
                {
   
                    Console.WriteLine(String.Format("block={0}, start={1}, len={2} 写入的字节数与设置的字数不成2倍关系!", block, start, buff.Length));
                }
                if (result != 0)
                {
   
                    return false;
                }
                return true;
            }
        }

        /// <summary>
        /// 断开与PLC的连接
        /// </summary>
        public override void Close()
        {
   
            lock (this)
            {
   
                try
                {
   
                    int result = this._client.Disconnect();
                    if (result != 0)
                    {
   
                        Console.WriteLine("PLC关闭失败:" + this.GetErrInfo(result));
                    }
                    else
                    {
   
                        Console.WriteLine("PLC已断开连接!");
                        this._errorCount = 0;
                        this.State = false;
                        this._isOpen = false;
                    }
                }
                catch (Exception ex)
                {
   
                    Console.WriteLine("PLC关闭失败:" + ex.Message);
                }
            }
        }

        #endregion

        #region 辅助方法

        /// <summary>根据错误代码返回错误信息
        /// 例如int errCode=ActiveConn(1);  sring errInfo = GetErrInfo(err);
        /// </summary>
        /// <param name="errCode">错误码</param>
        /// <returns>错误信息</returns>
        public string GetErrInfo(int errCode)
        {
   
            if (errCode == 0)
                return " Success(" + this._client.ExecutionTime.ToString() + " ms)";
            else
                return this._client.ErrorText(errCode);
        }

        #endregion
    }
}

Sharp7类实现

/*=============================================================================|
|  PROJECT Sharp7                                                        1.0.0 |
|==============================================================================|
|  Copyright (C) 2016 Davide Nardella                                          |
|  All rights reserved.                                                        |
|==============================================================================|
|  Sharp7 is free software: you can redistribute it and/or modify              |
|  it under the terms of the Lesser GNU General Public License as published by |
|  the Free Software Foundation, either version 3 of the License, or           |
|  (at your option) any later version.                                         |
|                                                                              |
|  It means that you can distribute your commercial software which includes    |
|  Sharp7 without the requirement to distribute the source code of your        |
|  application and without the requirement that your application be itself     |
|  distributed under LGPL.                                                     |
|                                                                              |
|  Sharp7 is distributed in the hope that it will be useful,                   |
|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |
|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
|  Lesser GNU General Public License for more details.                         |
|                                                                              |
|  You should have received a copy of the GNU General Public License and a     |
|  copy of Lesser GNU General Public License along with Sharp7.                |
|  If not, see  http://www.gnu.org/licenses/                                   |
|=============================================================================*/
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
//------------------------------------------------------------------------------
// If you are compiling for UWP verify that WINDOWS_UWP or NETFX_CORE are 
// defined into Project Properties->Build->Conditional compilation symbols
//------------------------------------------------------------------------------
#if WINDOWS_UWP || NETFX_CORE
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
#else // <-- Including MONO
using System.Net.Sockets;
#endif

namespace Mesnac.Equip.Siemens.S7
{
   

    #region [Async Sockets UWP(W10,IoT,Phone)/Windows 8/Windows 8 Phone]
#if WINDOWS_UWP || NETFX_CORE
    class MsgSocket
    {
   
        private DataReader Reader = null;
        private DataWriter Writer = null;
        private StreamSocket TCPSocket;

        private bool _Connected;

        private int _ReadTimeout = 2000;
        private int _WriteTimeout = 2000;
        private int _ConnectTimeout = 1000;

        public static int LastError = 0;


        private void CreateSocket()
        {
   
            TCPSocket = new StreamSocket();
            TCPSocket.Control.NoDelay = true;
            _Connected = false;
        }

        public MsgSocket()
        {
   
        }

        public void Close()
        {
   
            if (Reader != null)
            {
   
                Reader.Dispose();
                Reader = null;
            }
            if (Writer != null)
            {
   
                Writer.Dispose();
                Writer = null;
            }
            if (TCPSocket != null)
            {
   
                TCPSocket.Dispose();
                TCPSocket = null;
            }
            _Connected = false;
        }

        private async Task AsConnect(string Host, string port, CancellationTokenSource cts)
        {
   
            HostName ServerHost = new HostName(Host);
            try
            {
   
                await TCPSocket.ConnectAsync(ServerHost, port).AsTask(cts.Token);
                _Connected = true;
            }
            catch (TaskCanceledException)
            {
   
                LastError = S7Consts.errTCPConnectionTimeout;
            }
            catch
            {
   
                LastError = S7Consts.errTCPConnectionFailed; // Maybe unreachable peer
            }
        }

        public int Connect(string Host, int Port)
        {
   
            LastError = 0;
            if (!Connected)
            {
   
                CreateSocket();
                CancellationTokenSource cts = new CancellationTokenSource();
                try
                {
   
                    try
                    {
   
                        cts.CancelAfter(_ConnectTimeout);
                        Task.WaitAny(Task.Run(async () => await AsConnect(Host, Port.ToString(), cts)));
                    }
                    catch
                    {
   
                        LastError = S7Consts.errTCPConnectionFailed;
                    }
                }
                finally
                {
   
                    if (cts != null)
                    {
   
                        try
                        {
   
                            cts.Cancel();
                            cts.Dispose();
                            cts = null;
                        }
                        catch {
    }
                    }

                }
                if (LastError == 0)
                {
   
                    Reader = new DataReader(TCPSocket.InputStream);
                    Reader.InputStreamOptions = InputStreamOptions.Partial;
                    Writer = new DataWriter(TCPSocket.OutputStream);
                    _Connected = true;
                }
                else
                    Close();
            }
            return LastError;
        }

        private async Task AsReadBuffer(byte[] Buffer, int Size, CancellationTokenSource cts)
        {
   
            try
            {
   
                await Reader.LoadAsync((uint)Size).AsTask(cts.Token);
                Reader.ReadBytes(Buffer);
            }
            catch
            {
   
                LastError = S7Consts.errTCPDataReceive;
            }
        }

        public int Receive(byte[] Buffer, int Start, int Size)
        {
   
            byte[] InBuffer = new byte[Size];
            CancellationTokenSource cts = new CancellationTokenSource();
            LastError = 0;
            try
            {
   
                try
                {
   
                    cts.CancelAfter(_ReadTimeout);
                    Task.WaitAny(Task.Run(async () => await AsReadBuffer(InBuffer, Size, cts)));
                }
                catch
                {
   
                    LastError = S7Consts.errTCPDataReceive;
                }
            }
            finally
            {
   
                if (cts != null)
                {
   
                    try
                    {
   
                        cts.Cancel();
                        cts.Dispose();
                        cts = null;
                    }
                    catch {
    }
                }
            }
            if (LastError == 0)
                Array.Copy(InBuffer, 0, Buffer, Start, Size);
            else
                Close();
            return LastError;
        }

        private async Task WriteBuffer(byte[] Buffer, CancellationTokenSource cts)
        {
   
            try
            {
   
                Writer.WriteBytes(Buffer);
                await Writer.StoreAsync().AsTask(cts.Token);
            }
            catch
            {
   
                LastError = S7Consts.errTCPDataSend;
            }
        }

        public int Send(byte[] Buffer, int Size)
        {
   
            byte[] OutBuffer = new byte[Size];
            CancellationTokenSource cts = new CancellationTokenSource();
            Array.Copy(Buffer, 0, OutBuffer, 0, Size);
            LastError = 0;
            try
            {
   
                try
                {
   
                    cts.CancelAfter(_WriteTimeout);
                    Task.WaitAny(Task.Run(async () => await WriteBuffer(OutBuffer, cts)));
                }
                catch
                {
   
                    LastError = S7Consts.errTCPDataSend;
                }
            }
            finally
            {
   
                if (cts != null)
                {
   
                    try
                    {
   
                        cts.Cancel();
                        cts.Dispose();
                        cts = null;
                    }
                    catch {
    }
                }
            }
            if (LastError != 0)
                Close();
            return LastError;
        }

        ~MsgSocket()
        {
   
            Close();
        }

        public bool Connected
        {
   
            get
            {
   
                return (TCPSocket != null) && _Connected;
            }
        }

        public int ReadTimeout
        {
   
            get
            {
   
                return _ReadTimeout;
            }
            set
            {
   
                _ReadTimeout = value;
            }
        }

        public int WriteTimeout
        {
   
            get
            {
   
                return _WriteTimeout;
            }
            set
            {
   
                _WriteTimeout = value;
            }
        }
        public int ConnectTimeout
        {
   
            get
            {
   
                return _ConnectTimeout;
            }
            set
            {
   
                _ConnectTimeout = value;
            }
        }
    }
#endif
    #endregion

    #region [Sync Sockets Win32/Win64 Desktop Application]
#if !WINDOWS_UWP && !NETFX_CORE
    class MsgSocket
    {
   
        private Socket TCPSocket;
        private int _ReadTimeout = 2000;
        private int _WriteTimeout = 2000;
        private int _ConnectTimeout = 1000;
        public int LastError = 0;

        public MsgSocket()
        {
   
        }

        ~MsgSocket()
        {
   
            Close();
        }

        public void Close()
        {
   
            if (TCPSocket != null)
            {
   
                TCPSocket.Dispose();
                TCPSocket = null;
            }
        }

        private void CreateSocket()
        {
   
            TCPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            TCPSocket.NoDelay = true;
        }

        private void TCPPing(string Host, int Port)
        {
   
            // To Ping the PLC an Asynchronous socket is used rather then an ICMP packet.
            // This allows the use also across Internet and Firewalls (obviously the port must be opened)           
            LastError = 0;
            Socket PingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
   
                IAsyncResult result = PingSocket.BeginConnect(Host, Port, null, null);
                bool success = result.AsyncWaitHandle.WaitOne(_ConnectTimeout, true);
                if (!success)
                {
   
                    LastError = S7Consts.errTCPConnectionFailed;
                }
            }
            catch
            {
   
                LastError = S7Consts.errTCPConnectionFailed;
            };
            PingSocket.Close();
        }

        public int Connect(string Host, int Port)
        {
   
            LastError = 0;
            if (!Connected)
            {
    
                TCPPing(Host, Port);
                if (LastError == 0)
                try
                {
   
                        CreateSocket();
                        TCPSocket.Connect(Host, Port);
                }
                catch
                {
   
                        LastError = S7Consts.errTCPConnectionFailed;
                }
            }
            return LastError;
        }

        private int WaitForData(int Size, int Timeout)
        {
   
            bool Expired = false;
            int SizeAvail;
            int Elapsed = Environment.TickCount;
            LastError = 0;
            try
            {
   
                SizeAvail = TCPSocket.Available;
                while ((SizeAvail < Size) && (!Expired))
                {
   
                    Thread.Sleep(2);
                    SizeAvail = TCPSocket.Available;
                    Expired = Environment.TickCount - Elapsed > Timeout;
                    // If timeout we clean the buffer
                    if (Expired && (SizeAvail > 0))
                    try
                    {
   
                        byte[] Flush = new byte[SizeAvail];
                        TCPSocket.Receive(Flush, 0, SizeAvail, SocketFlags.None);
                    }
                    catch {
    }
                }
            }
            catch
            {
   
                LastError = S7Consts.errTCPDataReceive;
            }
            if (Expired)
            {
   
                LastError = S7Consts.errTCPDataReceive;
            }
            return LastError;
        }

        public int Receive(byte[] Buffer, int Start, int Size)
        {
   

            int BytesRead = 0;
            LastError = WaitForData(Size, _ReadTimeout);
            if (LastError == 0)
            {
   
                try
                {
   
                    BytesRead = TCPSocket.Receive(Buffer, Start, Size, SocketFlags.None);
                }
                catch
                {
   
                    LastError = S7Consts.errTCPDataReceive;
                }
                if (BytesRead == 0) // Connection Reset by the peer
                {
   
                    LastError = S7Consts.errTCPDataReceive;
                    Close();
                }
            }
            return LastError;
        }

        public int Send(byte[] Buffer, int Size)
        {
   
            LastError = 0;
            try
            {
   
                int BytesSent = TCPSocket.Send(Buffer, Size, SocketFlags.None);
            }
            catch
            {
   
                LastError = S7Consts.errTCPDataSend;
                Close();
            }
            return LastError;
        }

        public bool Connected
        {
   
            get
            {
   
                return (TCPSocket != null) && (TCPSocket.Connected); 
            }
        }

        public int ReadTimeout
        {
   
            get
            {
   
                return _ReadTimeout;
            }
            set
            {
   
                _ReadTimeout = value;
            }
        }

        public int WriteTimeout
        {
   
            get
            {
   
                return _WriteTimeout;
            }
            set
            {
   
                _WriteTimeout = value;
            }

        }
        public int ConnectTimeout
        {
   
            get
            {
   
                return _ConnectTimeout;
            }
            set
            {
   
                _ConnectTimeout = value;
            }
        }
    }   
#endif
#endregion

    public static class S7Consts
    {
   
        #region [Exported Consts]
        // Error codes
        //------------------------------------------------------------------------------
        //                                     ERRORS                 
        //------------------------------------------------------------------------------
        public const int errTCPSocketCreation         = 0x00000001;
        public const int errTCPConnectionTimeout      = 0x00000002;
        public const int errTCPConnectionFailed       = 0x00000003;
        public const int errTCPReceiveTimeout         = 0x00000004;
        public const int errTCPDataReceive            = 0x00000005;
        public const int errTCPSendTimeout            = 0x00000006;
        public const int errTCPDataSend               = 0x00000007;
        public const int errTCPConnectionReset        = 0x00000008;
        public const int errTCPNotConnected           = 0x00000009;
        public const int errTCPUnreachableHost        = 0x00002751;

        public const int errIsoConnect                = 0x00010000; // Connection error
        public const int errIsoInvalidPDU             = 0x00030000; // Bad format
        public const int errIsoInvalidDataSize        = 0x00040000; // Bad Datasize passed to send/recv : buffer is invalid

        public const int errCliNegotiatingPDU         = 0x00100000;
        public const int errCliInvalidParams          = 0x00200000;
        public const int errCliJobPending             = 0x00300000;
        public const int errCliTooManyItems           = 0x00400000;
        public const int errCliInvalidWordLen         = 0x00500000;
        public const int errCliPartialDataWritten     = 0x00600000;
        public const int errCliSizeOverPDU            = 0x00700000;
        public const int errCliInvalidPlcAnswer       = 0x00800000;
        public const int errCliAddressOutOfRange      = 0x00900000;
        public const int errCliInvalidTransportSize   = 0x00A00000;
        public const int errCliWriteDataSizeMismatch  = 0x00B00000;
        public const int errCliItemNotAvailable       = 0x00C00000;
        public const int errCliInvalidValue           = 0x00D00000;
        public const int errCliCannotStartPLC         = 0x00E00000;
        public const int errCliAlreadyRun             = 0x00F00000;
        public const int errCliCannotStopPLC          = 0x01000000;
        public const int errCliCannotCopyRamToRom     = 0x01100000;
        public const int errCliCannotCompress         = 0x01200000;
        public const int errCliAlreadyStop            = 0x01300000;
        public const int errCliFunNotAvailable        = 0x01400000;
        public const int errCliUploadSequenceFailed   = 0x01500000;
        public const int errCliInvalidDataSizeRecvd   = 0x01600000;
        public const int errCliInvalidBlockType       = 0x01700000;
        public const int errCliInvalidBlockNumber     = 0x01800000;
        public const int errCliInvalidBlockSize       = 0x01900000;
        public const int errCliNeedPassword           = 0x01D00000;
        public const int errCliInvalidPassword        = 0x01E00000;
        public const int errCliNoPasswordToSetOrClear = 0x01F00000;
        public const int errCliJobTimeout             = 0x02000000;
        public const int errCliPartialDataRead        = 0x02100000;
        public const int errCliBufferTooSmall         = 0x02200000;
        public const int errCliFunctionRefused        = 0x02300000;
        public const int errCliDestroying             = 0x02400000;
        public const int errCliInvalidParamNumber     = 0x02500000;
        public const int errCliCannotChangeParam      = 0x02600000;
        public const int errCliFunctionNotImplemented = 0x02700000;
        //------------------------------------------------------------------------------
        //        PARAMS LIST FOR COMPATIBILITY WITH Snap7.net.cs           
        //------------------------------------------------------------------------------
        public const Int32 p_u16_LocalPort     = 1;  // Not applicable here
        public const Int32 p_u16_RemotePort    = 2;
        public const Int32 p_i32_PingTimeout   = 3;
        public const Int32 p_i32_SendTimeout   = 4;
        public const Int32 p_i32_RecvTimeout   = 5;
        public const Int32 p_i32_WorkInterval  = 6;  // Not applicable here
        public const Int32 p_u16_SrcRef        = 7;  // Not applicable here
        public const Int32 p_u16_DstRef        = 8;  // Not applicable here
        public const Int32 p_u16_SrcTSap       = 9;  // Not applicable here
        public const Int32 p_i32_PDURequest    = 10;
        public const Int32 p_i32_MaxClients    = 11; // Not applicable here
        public const Int32 p_i32_BSendTimeout  = 12; // Not applicable here
        public const Int32 p_i32_BRecvTimeout  = 13; // Not applicable here
        public const Int32 p_u32_RecoveryTime  = 14; // Not applicable here
        public const Int32 p_u32_KeepAliveTime = 15; // Not applicable here
        // Area ID
        public const byte S7AreaPE = 0x81;
        public const byte S7AreaPA = 0x82;
        public const byte S7AreaMK = 0x83;
        public const byte S7AreaDB = 0x84;
        public const byte S7AreaCT = 0x1C;
        public const byte S7AreaTM = 0x1D;
        // Word Length
        public const int S7WLBit     = 0x01;
        public const int S7WLByte    = 0x02;
        public const int S7WLChar    = 0x03;
        public const int S7WLWord    = 0x04;
        public const int S7WLInt     = 0x05;
        public const int S7WLDWord   = 0x06;
        public const int S7WLDInt    = 0x07;
        public const int S7WLReal    = 0x08;
        public const int S7WLCounter = 0x1C;
        public const int S7WLTimer   = 0x1D;
        // PLC Status
        public const int S7CpuStatusUnknown = 0x00;
        public const int S7CpuStatusRun     = 0x08;
        public const int S7CpuStatusStop    = 0x04;

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct S7Tag
        {
   
            public Int32 Area;
            public Int32 DBNumber;
            public Int32 Start;
            public Int32 Elements;
            public Int32 WordLen;
        }
        #endregion
    }

    public static class S7
    {
   
        #region [Help Functions]

        private static Int64 bias = 621355968000000000; // "decimicros" between 0001-01-01 00:00:00 and 1970-01-01 00:00:00

        private static int BCDtoByte(byte B)
        {
   
             return ((B >> 4) * 10) + (B & 0x0F);        
        }

        private static byte ByteToBCD(int Value)
        {
   
            return (byte)(((Value / 10) << 4) | (Value % 10));
        }
        
        private static byte[] CopyFrom(byte[] Buffer, int Pos, int Size)
        {
   
            byte[] Result=new byte[Size];
            Array.Copy(Buffer, Pos, Result, 0, Size);
            return Result;
        }

        public static int DataSizeByte(int WordLength)
        {
   
            switch (WordLength)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值