/// <summary> /// 生成位写入的数据报文信息,该报文可直接用于发送串口给PLC /// </summary> /// <param name="address">地址信息,每个地址存在一定的范围,需要谨慎传入数据。举例:M10,S10,X5,Y10,C10,T10</param> /// <param name="value"><c>True</c>或是<c>False</c></param> /// <returns>带报文信息的结果对象</returns> public static OperateResult <byte[]> BuildWriteBoolPacket(string address, bool value) { var analysis = FxAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } // 二次运算起始地址偏移量,根据类型的不同,地址的计算方式不同 ushort startAddress = analysis.Content2; if (analysis.Content1 == MelsecMcDataType.M) { if (startAddress >= 8000) { startAddress = (ushort)(startAddress - 8000 + 0x0F00); } else { startAddress = (ushort)(startAddress + 0x0800); } } else if (analysis.Content1 == MelsecMcDataType.S) { startAddress = (ushort)(startAddress + 0x0000); } else if (analysis.Content1 == MelsecMcDataType.X) { startAddress = (ushort)(startAddress + 0x0400); } else if (analysis.Content1 == MelsecMcDataType.Y) { startAddress = (ushort)(startAddress + 0x0500); } else if (analysis.Content1 == MelsecMcDataType.C) { startAddress += (ushort)(startAddress + 0x0E00); } else if (analysis.Content1 == MelsecMcDataType.T) { startAddress += (ushort)(startAddress + 0x0600); } else { return(new OperateResult <byte[]>(StringResources.Language.MelsecCurrentTypeNotSupportedBitOperate)); } byte[] _PLCCommand = new byte[9]; _PLCCommand[0] = 0x02; // STX _PLCCommand[1] = value ? (byte)0x37 : (byte)0x38; // Read _PLCCommand[2] = MelsecHelper.BuildBytesFromData(startAddress)[2]; // 偏移地址 _PLCCommand[3] = MelsecHelper.BuildBytesFromData(startAddress)[3]; _PLCCommand[4] = MelsecHelper.BuildBytesFromData(startAddress)[0]; _PLCCommand[5] = MelsecHelper.BuildBytesFromData(startAddress)[1]; _PLCCommand[6] = 0x03; // ETX MelsecHelper.FxCalculateCRC(_PLCCommand).CopyTo(_PLCCommand, 7); // CRC return(OperateResult.CreateSuccessResult(_PLCCommand)); }
/// <summary> /// 根据类型地址以及需要写入的数据来生成报文 /// </summary> /// <param name="address">起始地址</param> /// <param name="value">写入数据的实际值</param> /// <param name="networkNumber">网络号</param> /// <param name="networkStationNumber">网络站号</param> /// <returns>带有成功标志的指令数据</returns> public static OperateResult <byte[]> BuildWriteCommand(string address, byte[] value, byte networkNumber = 0, byte networkStationNumber = 0) { OperateResult <MelsecMcDataType, ushort> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } // 预处理指令 if (analysis.Content1.DataType == 0x01) { // 位写入 value = value.Select(m => m == 0x00 ? (byte)0x30 : (byte)0x31).ToArray( ); } else { // 字写入 byte[] buffer = new byte[value.Length * 2]; for (int i = 0; i < value.Length / 2; i++) { MelsecHelper.BuildBytesFromData(BitConverter.ToUInt16(value, i * 2)).CopyTo(buffer, 4 * i); } value = buffer; } // 默认信息----注意:高低字节交错 byte[] _PLCCommand = new byte[42 + value.Length]; _PLCCommand[0] = 0x35; // 副标题 _PLCCommand[1] = 0x30; _PLCCommand[2] = 0x30; _PLCCommand[3] = 0x30; _PLCCommand[4] = MelsecHelper.BuildBytesFromData(networkNumber)[0]; // 网络号 _PLCCommand[5] = MelsecHelper.BuildBytesFromData(networkNumber)[1]; _PLCCommand[6] = 0x46; // PLC编号 _PLCCommand[7] = 0x46; _PLCCommand[8] = 0x30; // 目标模块IO编号 _PLCCommand[9] = 0x33; _PLCCommand[10] = 0x46; _PLCCommand[11] = 0x46; _PLCCommand[12] = MelsecHelper.BuildBytesFromData(networkStationNumber)[0]; // 目标模块站号 _PLCCommand[13] = MelsecHelper.BuildBytesFromData(networkStationNumber)[1]; _PLCCommand[14] = MelsecHelper.BuildBytesFromData((ushort)(_PLCCommand.Length - 18))[0]; // 请求数据长度 _PLCCommand[15] = MelsecHelper.BuildBytesFromData((ushort)(_PLCCommand.Length - 18))[1]; _PLCCommand[16] = MelsecHelper.BuildBytesFromData((ushort)(_PLCCommand.Length - 18))[2]; _PLCCommand[17] = MelsecHelper.BuildBytesFromData((ushort)(_PLCCommand.Length - 18))[3]; _PLCCommand[18] = 0x30; // CPU监视定时器 _PLCCommand[19] = 0x30; _PLCCommand[20] = 0x31; _PLCCommand[21] = 0x30; _PLCCommand[22] = 0x31; // 批量写入的命令 _PLCCommand[23] = 0x34; _PLCCommand[24] = 0x30; _PLCCommand[25] = 0x31; _PLCCommand[26] = 0x30; // 子命令 _PLCCommand[27] = 0x30; _PLCCommand[28] = 0x30; _PLCCommand[29] = analysis.Content1.DataType == 0 ? (byte)0x30 : (byte)0x31; _PLCCommand[30] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0]; // 软元件类型 _PLCCommand[31] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1]; _PLCCommand[32] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0]; // 起始地址的地位 _PLCCommand[33] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1]; _PLCCommand[34] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2]; _PLCCommand[35] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3]; _PLCCommand[36] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4]; _PLCCommand[37] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5]; // 判断是否进行位操作 if (analysis.Content1.DataType == 1) { _PLCCommand[38] = MelsecHelper.BuildBytesFromData((ushort)value.Length)[0]; // 软元件点数 _PLCCommand[39] = MelsecHelper.BuildBytesFromData((ushort)value.Length)[1]; _PLCCommand[40] = MelsecHelper.BuildBytesFromData((ushort)value.Length)[2]; _PLCCommand[41] = MelsecHelper.BuildBytesFromData((ushort)value.Length)[3]; } else { _PLCCommand[38] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[0]; // 软元件点数 _PLCCommand[39] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[1]; _PLCCommand[40] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[2]; _PLCCommand[41] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[3]; } Array.Copy(value, 0, _PLCCommand, 42, value.Length); return(OperateResult.CreateSuccessResult(_PLCCommand)); }
/// <summary> /// 分析地址的方法,允许派生类里进行重写操作 /// </summary> /// <param name="address">地址信息</param> /// <returns>解析后的数据信息</returns> protected virtual OperateResult <MelsecMcDataType, int> McAnalysisAddress(string address) { return(MelsecHelper.McAnalysisAddress(address)); }
private byte[] ReadByCommand(byte[] command) { if (command[2] == 0x01) { // 位读取 ushort length = ByteTransform.TransUInt16(command, 8); int startIndex = (command[6] * 65536 + command[5] * 256 + command[4]); if (command[7] == MelsecMcDataType.M.DataCode) { byte[] buffer = mBuffer.GetBytes(startIndex, length); return(MelsecHelper.TransBoolArrayToByteData(buffer)); } else if (command[7] == MelsecMcDataType.X.DataCode) { byte[] buffer = xBuffer.GetBytes(startIndex, length); return(MelsecHelper.TransBoolArrayToByteData(buffer)); } else if (command[7] == MelsecMcDataType.Y.DataCode) { byte[] buffer = yBuffer.GetBytes(startIndex, length); return(MelsecHelper.TransBoolArrayToByteData(buffer)); } else { throw new Exception(StringResources.Language.NotSupportedDataType); } } else { // 字读取 ushort length = ByteTransform.TransUInt16(command, 8); int startIndex = (command[6] * 65536 + command[5] * 256 + command[4]); if (command[7] == MelsecMcDataType.M.DataCode) { bool[] buffer = mBuffer.GetBytes(startIndex, length * 16).Select(m => m != 0x00).ToArray( ); return(SoftBasic.BoolArrayToByte(buffer)); } else if (command[7] == MelsecMcDataType.X.DataCode) { bool[] buffer = xBuffer.GetBytes(startIndex, length * 16).Select(m => m != 0x00).ToArray( ); return(SoftBasic.BoolArrayToByte(buffer)); } else if (command[7] == MelsecMcDataType.Y.DataCode) { bool[] buffer = yBuffer.GetBytes(startIndex, length * 16).Select(m => m != 0x00).ToArray( ); return(SoftBasic.BoolArrayToByte(buffer)); } else if (command[7] == MelsecMcDataType.D.DataCode) { return(dBuffer.GetBytes(startIndex * 2, length * 2)); } else if (command[7] == MelsecMcDataType.W.DataCode) { return(wBuffer.GetBytes(startIndex * 2, length * 2)); } else { throw new Exception(StringResources.Language.NotSupportedDataType); } } }
/// <summary> /// 根据类型地址以及需要写入的数据来生成指令头 /// </summary> /// <param name="address">起始地址</param> /// <param name="value">数据值,对于写入位地址来说,应该传入{0x01,0x00,0x01} 通断通这样的数组</param> /// <param name="networkNumber">网络号</param> /// <param name="networkStationNumber">网络站号</param> /// <returns>解析后的指令</returns> public static OperateResult <byte[]> BuildWriteCommand(string address, byte[] value, byte networkNumber = 0, byte networkStationNumber = 0) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } int length = -1; if (analysis.Content1.DataType == 1) { // 按照位写入的操作,数据需要重新计算 length = value.Length; value = MelsecHelper.TransBoolArrayToByteData(value); } byte[] _PLCCommand = new byte[21 + value.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] = analysis.Content1.DataType; // 以点为单位还是字为单位成批读取 _PLCCommand[14] = 0x00; _PLCCommand[15] = BitConverter.GetBytes(analysis.Content2)[0]; // 起始地址的地位 _PLCCommand[16] = BitConverter.GetBytes(analysis.Content2)[1]; _PLCCommand[17] = BitConverter.GetBytes(analysis.Content2)[2]; _PLCCommand[18] = analysis.Content1.DataCode; // 指明写入的数据 // 判断是否进行位操作 if (analysis.Content1.DataType == 1) { if (length > 0) { _PLCCommand[19] = (byte)(length % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(length / 256); } else { _PLCCommand[19] = (byte)(value.Length * 2 % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(value.Length * 2 / 256); } } else { _PLCCommand[19] = (byte)(value.Length / 2 % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(value.Length / 2 / 256); } Array.Copy(value, 0, _PLCCommand, 21, value.Length); return(OperateResult.CreateSuccessResult(_PLCCommand)); }
/// <summary> /// 根据类型地址长度确认需要读取的报文 /// </summary> /// <param name="address">起始地址</param> /// <param name="length">长度</param> /// <param name="isBit">指示是否按照位成批的读出</param> /// <param name="networkNumber">网络号信息</param> /// <param name="networkStationNumber">网络站号信息</param> /// <returns>带有成功标志的指令数据</returns> public static OperateResult <byte[]> BuildReadCommand(string address, ushort length, bool isBit, byte networkNumber = 0, byte networkStationNumber = 0) { OperateResult <byte[]> coreResult = MelsecHelper.BuildAsciiReadMcCoreCommand(address, length, isBit); if (!coreResult.IsSuccess) { return(coreResult); } return(OperateResult.CreateSuccessResult(PackMcCommand(coreResult.Content, networkNumber, networkStationNumber))); OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } // 默认信息----注意:高低字节交错 byte[] _PLCCommand = new byte[42]; _PLCCommand[0] = 0x35; // 副标题 _PLCCommand[1] = 0x30; _PLCCommand[2] = 0x30; _PLCCommand[3] = 0x30; _PLCCommand[4] = MelsecHelper.BuildBytesFromData(networkNumber)[0]; // 网络号 _PLCCommand[5] = MelsecHelper.BuildBytesFromData(networkNumber)[1]; _PLCCommand[6] = 0x46; // PLC编号 _PLCCommand[7] = 0x46; _PLCCommand[8] = 0x30; // 目标模块IO编号 _PLCCommand[9] = 0x33; _PLCCommand[10] = 0x46; _PLCCommand[11] = 0x46; _PLCCommand[12] = MelsecHelper.BuildBytesFromData(networkStationNumber)[0]; // 目标模块站号 _PLCCommand[13] = MelsecHelper.BuildBytesFromData(networkStationNumber)[1]; _PLCCommand[14] = 0x30; // 请求数据长度 _PLCCommand[15] = 0x30; _PLCCommand[16] = 0x31; _PLCCommand[17] = 0x38; _PLCCommand[18] = 0x30; // CPU监视定时器 _PLCCommand[19] = 0x30; _PLCCommand[20] = 0x31; _PLCCommand[21] = 0x30; _PLCCommand[22] = 0x30; // 批量读取数据命令 _PLCCommand[23] = 0x34; _PLCCommand[24] = 0x30; _PLCCommand[25] = 0x31; _PLCCommand[26] = 0x30; // 以点为单位还是字为单位成批读取 _PLCCommand[27] = 0x30; _PLCCommand[28] = 0x30; _PLCCommand[29] = isBit ? (byte)0x31 : ( byte)0x30; _PLCCommand[30] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0]; // 软元件类型 _PLCCommand[31] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1]; _PLCCommand[32] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0]; // 起始地址的地位 _PLCCommand[33] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1]; _PLCCommand[34] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2]; _PLCCommand[35] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3]; _PLCCommand[36] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4]; _PLCCommand[37] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5]; _PLCCommand[38] = MelsecHelper.BuildBytesFromData(length)[0]; // 软元件点数 _PLCCommand[39] = MelsecHelper.BuildBytesFromData(length)[1]; _PLCCommand[40] = MelsecHelper.BuildBytesFromData(length)[2]; _PLCCommand[41] = MelsecHelper.BuildBytesFromData(length)[3]; return(OperateResult.CreateSuccessResult(_PLCCommand)); }
/// <summary> /// 根据类型地址以及需要写入的数据来生成指令头 /// </summary> /// <param name="address">起始地址</param> /// <param name="value">数据值,对于写入位地址来说,应该传入{0x01,0x00,0x01} 通断通这样的数组</param> /// <param name="networkNumber">网络号</param> /// <param name="networkStationNumber">网络站号</param> /// <returns>解析后的指令</returns> public static OperateResult <byte[]> BuildWriteCommand(string address, byte[] value, byte networkNumber = 0, byte networkStationNumber = 0) { OperateResult <MelsecMcDataType, ushort> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } int length = -1; if (analysis.Content1.DataType == 1) { // 按照位写入的操作,数据需要重新计算 int length2 = value.Length % 2 == 0 ? value.Length / 2 : value.Length / 2 + 1; byte[] buffer = new byte[length2]; for (int i = 0; i < length2; i++) { if (value[i * 2 + 0] != 0x00) { buffer[i] += 0x10; } if ((i * 2 + 1) < value.Length) { if (value[i * 2 + 1] != 0x00) { buffer[i] += 0x01; } } } length = value.Length; value = buffer; } byte[] _PLCCommand = new byte[21 + value.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] = analysis.Content1.DataType; // 以点为单位还是字为单位成批读取 _PLCCommand[14] = 0x00; _PLCCommand[15] = (byte)(analysis.Content2 % 256);; // 起始地址的地位 _PLCCommand[16] = (byte)(analysis.Content2 / 256); _PLCCommand[17] = 0x00; _PLCCommand[18] = analysis.Content1.DataCode; // 指明写入的数据 // 判断是否进行位操作 if (analysis.Content1.DataType == 1) { if (length > 0) { _PLCCommand[19] = (byte)(length % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(length / 256); } else { _PLCCommand[19] = (byte)(value.Length * 2 % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(value.Length * 2 / 256); } } else { _PLCCommand[19] = (byte)(value.Length / 2 % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(value.Length / 2 / 256); } Array.Copy(value, 0, _PLCCommand, 21, value.Length); return(OperateResult.CreateSuccessResult(_PLCCommand)); }