Пример #1
0
        /// <summary>
        /// 根据类型地址以及需要写入的数据来生成指令头
        /// </summary>
        /// <param name="type"></param>
        /// <param name="address"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        protected byte[] GetWriteCommand(MelsecDataType type, ushort address, byte[] data)
        {
            byte[] _PLCCommand = new byte[21 + data.Length];

            //默认信息----注意:高低字节交错
            _PLCCommand[0] = 0x50;                                    //副标题
            _PLCCommand[1] = 0x00;
            _PLCCommand[2] = NetworkNumber;                           //网络号
            _PLCCommand[3] = 0xFF;                                    //PLC编号
            _PLCCommand[4] = 0xFF;                                    //目标模块IO编号
            _PLCCommand[5] = 0x03;
            _PLCCommand[6] = NetworkStationNumber;                    //目标模块站号

            _PLCCommand[7]  = (byte)((_PLCCommand.Length - 9) % 256); //请求数据长度
            _PLCCommand[8]  = (byte)((_PLCCommand.Length - 9) / 256);;
            _PLCCommand[9]  = 0x0A;                                   //CPU监视定时器
            _PLCCommand[10] = 0x00;
            _PLCCommand[11] = 0x01;                                   //批量读取数据命令
            _PLCCommand[12] = 0x14;
            _PLCCommand[13] = type.DataType;                          //一点为单位成批读取
            _PLCCommand[14] = 0x00;
            _PLCCommand[15] = (byte)(address % 256);;                 //起始地址的地位
            _PLCCommand[16] = (byte)(address / 256);
            _PLCCommand[17] = 0x00;
            _PLCCommand[18] = type.DataCode;//指明写入的数据

            if (type.DataType == 1)
            {
                _PLCCommand[19] = (byte)(data.Length * 2 % 256);//软元件长度的地位
                _PLCCommand[20] = (byte)(data.Length * 2 / 256);
            }
            else
            {
                _PLCCommand[19] = (byte)(data.Length / 2 % 256);//软元件长度的地位
                _PLCCommand[20] = (byte)(data.Length / 2 / 256);
            }

            Array.Copy(data, 0, _PLCCommand, 21, data.Length);
            return(_PLCCommand);
        }
Пример #2
0
 /// <summary>
 /// 向PLC写入数据,针对D和W的方式,数据格式为有符号的short数组
 /// </summary>
 /// <param name="type">写入的数据类型</param>
 /// <param name="address">初始地址</param>
 /// <param name="data">有符号的short数组</param>
 /// <returns>结果</returns>
 public OperateResult WriteIntoPLC(MelsecDataType type, ushort address, short[] data)
 {
     byte[] temp = GetBytesFromArray(data, false);
     return(WriteIntoPLC(type, address, temp));
 }
Пример #3
0
 /// <summary>
 /// 使用Unicode编码向PLC写入字符串数据,针对W,D的方式,数据为字符串
 /// </summary>
 /// <param name="type">写入的数据类型</param>
 /// <param name="address">初始地址</param>
 /// <param name="data">字符串数据信息</param>
 /// <returns>结果</returns>
 public OperateResult WriteUnicodeStringIntoPLC(MelsecDataType type, ushort address, string data)
 {
     byte[] temp = Encoding.Unicode.GetBytes(data);
     return(WriteIntoPLC(type, address, temp));
 }
Пример #4
0
 /// <summary>
 /// 向PLC写入ASCII编码字符串数据,针对W,D的方式,数据为字符串
 /// </summary>
 /// <param name="type">写入的数据类型</param>
 /// <param name="address">初始地址</param>
 /// <param name="data">字符串数据信息</param>
 /// <returns>结果</returns>
 public OperateResult WriteAsciiStringIntoPLC(MelsecDataType type, ushort address, string data)
 {
     byte[] temp = Encoding.ASCII.GetBytes(data);
     temp = SingularTurnEven(temp);
     return(WriteIntoPLC(type, address, temp));
 }
Пример #5
0
        /// <summary>
        /// 从三菱PLC中读取想要的数据,返回读取结果
        /// </summary>
        /// <param name="type">想要读取的数据类型</param>
        /// <param name="address">读取数据的起始地址</param>
        /// <param name="length">读取的数据长度,字最大值960,位最大值7168</param>
        /// <returns>带数据头的字节数组</returns>
        public OperateResult <byte[]> ReadFromPLC(MelsecDataType type, ushort address, ushort length)
        {
            OperateResult <byte[]> result = new OperateResult <byte[]>();

            //获取指令
            byte[] _PLCCommand = GetReadCommand(type, address, length);


            Socket     socket  = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            HslTimeOut timeout = new HslTimeOut()
            {
                WorkSocket = socket
            };

            try
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolCheckConnect), timeout);
                socket.Connect(new IPEndPoint(PLCIpAddress, GetPort()));
                timeout.IsSuccessful = true;
            }
            catch
            {
                ChangePort();
                result.Message = StringResources.ConnectedFailed;;
                socket.Close();
                return(result);
            }
            byte[] DataHead = null;
            try
            {
                socket.Send(_PLCCommand);
                //先接收满9个数据
                int NeedReceived = 9;
                DataHead     = NetSupport.ReadBytesFromSocket(socket, NeedReceived);
                NeedReceived = BitConverter.ToUInt16(DataHead, 7);
                DataHead     = NetSupport.ReadBytesFromSocket(socket, NeedReceived);
                //获取读取代码
                result.ErrorCode = BitConverter.ToUInt16(DataHead, 0);
                result.Content   = new byte[DataHead.Length - 2];
                Array.Copy(DataHead, 2, result.Content, 0, DataHead.Length - 2);
                if (type.DataType == 1)
                {
                    result.Content = ReceiveBytesTranslate(result.Content);
                }
                result.IsSuccess = true;
            }
            catch (Exception ex)
            {
                result.Message = StringResources.SocketIOException + ex.Message;
                socket.Close();
                return(result);
            }
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            socket = null;
            if (result.ErrorCode > 0)
            {
                result.IsSuccess = false;
            }
            return(result);
        }
Пример #6
0
        /// <summary>
        /// 解析数据地址
        /// </summary>
        /// <param name="address">数据地址</param>
        /// <param name="type">类型</param>
        /// <param name="startAddress">其实地址</param>
        /// <param name="result">结果数据对象</param>
        /// <returns></returns>
        private bool AnalysisAddress(string address, out MelsecDataType type, out ushort startAddress, OperateResult result)
        {
            try
            {
                switch (address[0])
                {
                case 'M':
                case 'm':
                {
                    type = MelsecDataType.M;
                    break;
                }

                case 'X':
                case 'x':
                {
                    type = MelsecDataType.X;
                    break;
                }

                case 'Y':
                case 'y':
                {
                    type = MelsecDataType.Y;
                    break;
                }

                case 'D':
                case 'd':
                {
                    type = MelsecDataType.D;
                    break;
                }

                case 'W':
                case 'w':
                {
                    type = MelsecDataType.W;
                    break;
                }

                case 'L':
                case 'l':
                {
                    type = MelsecDataType.L;
                    break;
                }

                default: throw new Exception("输入的类型不支持,请重新输入");
                }
                startAddress = Convert.ToUInt16(address.Substring(1));
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
                type           = null;
                startAddress   = 0;
                return(false);
            }
            return(true);
        }