/// <summary> /// 根据类型地址以及需要写入的数据来生成指令头 /// </summary> /// <param name="address">起始地址</param> /// <param name="value">实际的数据信息</param> /// <returns>带有成功标志的指令数据</returns> public static OperateResult <byte[]> BuildWriteWordCommand(string address, byte[] value) { var addressResult = FxCalculateWordStartAddress(address); if (!addressResult.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(addressResult)); } // 字节数据转换成ASCII格式 if (value != null) { value = MelsecHelper.BuildBytesFromData(value); } ushort startAddress = addressResult.Content; byte[] _PLCCommand = new byte[11 + value.Length]; _PLCCommand[0] = 0x02; // STX _PLCCommand[1] = 0x31; // Read _PLCCommand[2] = MelsecHelper.BuildBytesFromData(startAddress)[0]; // Offect Address _PLCCommand[3] = MelsecHelper.BuildBytesFromData(startAddress)[1]; _PLCCommand[4] = MelsecHelper.BuildBytesFromData(startAddress)[2]; _PLCCommand[5] = MelsecHelper.BuildBytesFromData(startAddress)[3]; _PLCCommand[6] = MelsecHelper.BuildBytesFromData((byte)(value.Length / 2))[0]; // Read Length _PLCCommand[7] = MelsecHelper.BuildBytesFromData((byte)(value.Length / 2))[1]; Array.Copy(value, 0, _PLCCommand, 8, value.Length); _PLCCommand[_PLCCommand.Length - 3] = 0x03; // ETX MelsecHelper.FxCalculateCRC(_PLCCommand).CopyTo(_PLCCommand, _PLCCommand.Length - 2); // CRC return(OperateResult.CreateSuccessResult(_PLCCommand)); }
/// <summary> /// 从地址,长度,是否位读取进行创建读取Ascii格式的MC的核心报文 /// </summary> /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param> /// <param name="length">读取的长度信息</param> /// <param name="isBit">是否进行了位读取操作</param> /// <param name="analysisAddress">对地址分析的委托方法</param> /// <returns>带有成功标识的报文对象</returns> public static OperateResult <byte[]> BuildAsciiReadMcCoreCommand(string address, ushort length, bool isBit, Func <string, OperateResult <MelsecMcDataType, int> > analysisAddress) { OperateResult <MelsecMcDataType, int> analysis = analysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } byte[] command = new byte[20]; command[0] = 0x30; // 批量读取数据命令 command[1] = 0x34; command[2] = 0x30; command[3] = 0x31; command[4] = 0x30; // 以点为单位还是字为单位成批读取 command[5] = 0x30; command[6] = 0x30; command[7] = isBit ? (byte)0x31 : (byte)0x30; command[8] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0]; // 软元件类型 command[9] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1]; command[10] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0]; // 起始地址的地位 command[11] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1]; command[12] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2]; command[13] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3]; command[14] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4]; command[15] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5]; command[16] = MelsecHelper.BuildBytesFromData(length)[0]; // 软元件点数 command[17] = MelsecHelper.BuildBytesFromData(length)[1]; command[18] = MelsecHelper.BuildBytesFromData(length)[2]; command[19] = MelsecHelper.BuildBytesFromData(length)[3]; return(OperateResult.CreateSuccessResult(command)); }
/// <summary> /// 根据类型地址长度确认需要读取的指令头 /// </summary> /// <param name="address">起始地址</param> /// <param name="length">长度</param> /// <returns>带有成功标志的指令数据</returns> public static OperateResult <byte[]> BuildReadWordCommand(string address, ushort length) { var addressResult = FxCalculateWordStartAddress(address); if (!addressResult.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(addressResult)); } length = (ushort)(length * 2); ushort startAddress = addressResult.Content; byte[] _PLCCommand = new byte[11]; _PLCCommand[0] = 0x02; // STX _PLCCommand[1] = 0x30; // Read _PLCCommand[2] = MelsecHelper.BuildBytesFromData(startAddress)[0]; // 偏移地址 _PLCCommand[3] = MelsecHelper.BuildBytesFromData(startAddress)[1]; _PLCCommand[4] = MelsecHelper.BuildBytesFromData(startAddress)[2]; _PLCCommand[5] = MelsecHelper.BuildBytesFromData(startAddress)[3]; _PLCCommand[6] = MelsecHelper.BuildBytesFromData((byte)length)[0]; // 读取长度 _PLCCommand[7] = MelsecHelper.BuildBytesFromData((byte)length)[1]; _PLCCommand[8] = 0x03; // ETX MelsecHelper.FxCalculateCRC(_PLCCommand).CopyTo(_PLCCommand, 9); // CRC return(OperateResult.CreateSuccessResult(_PLCCommand)); // Return }
/// <summary> /// 根据类型地址长度确认需要读取的指令头 /// </summary> /// <param name="address">起始地址</param> /// <param name="length">bool数组长度</param> /// <returns>带有成功标志的指令数据</returns> public static OperateResult <byte[], int> BuildReadBoolCommand(string address, ushort length) { var addressResult = FxCalculateBoolStartAddress(address); if (!addressResult.IsSuccess) { return(OperateResult.CreateFailedResult <byte[], int>(addressResult)); } // 计算下实际需要读取的数据长度 ushort length2 = (ushort)((addressResult.Content2 + length - 1) / 8 - (addressResult.Content2 / 8) + 1); ushort startAddress = addressResult.Content1; byte[] _PLCCommand = new byte[11]; _PLCCommand[0] = 0x02; // STX _PLCCommand[1] = 0x30; // Read _PLCCommand[2] = MelsecHelper.BuildBytesFromData(startAddress)[0]; // 偏移地址 _PLCCommand[3] = MelsecHelper.BuildBytesFromData(startAddress)[1]; _PLCCommand[4] = MelsecHelper.BuildBytesFromData(startAddress)[2]; _PLCCommand[5] = MelsecHelper.BuildBytesFromData(startAddress)[3]; _PLCCommand[6] = MelsecHelper.BuildBytesFromData((byte)length2)[0]; // 读取长度 _PLCCommand[7] = MelsecHelper.BuildBytesFromData((byte)length2)[1]; _PLCCommand[8] = 0x03; // ETX MelsecHelper.FxCalculateCRC(_PLCCommand).CopyTo(_PLCCommand, 9); // CRC return(OperateResult.CreateSuccessResult(_PLCCommand, (int)addressResult.Content3)); }
/// <summary> /// 将MC协议的核心报文打包成一个可以直接对PLC进行发送的原始报文 /// </summary> /// <param name="mcCore">MC协议的核心报文</param> /// <param name="networkNumber">网络号</param> /// <param name="networkStationNumber">网络站号</param> /// <returns>原始报文信息</returns> public static byte[] PackMcCommand(byte[] mcCore, byte networkNumber = 0, byte networkStationNumber = 0) { byte[] plcCommand = new byte[22 + mcCore.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; mcCore.CopyTo(plcCommand, 22); return(plcCommand); }
/// <summary> /// 以位为单位,创建ASCII数据写入的核心报文 /// </summary> /// <param name="addressData">三菱Mc协议的数据地址</param> /// <param name="value">原始的bool数组数据</param> /// <returns>带有成功标识的报文对象</returns> public static byte[] BuildAsciiWriteBitCoreCommand(McAddressData addressData, bool[] value) { if (value == null) { value = new bool[0]; } byte[] buffer = value.Select(m => m ? (byte)0x31 : (byte)0x30).ToArray( ); byte[] command = new byte[20 + buffer.Length]; command[0] = 0x31; // 批量写入的命令 command[1] = 0x34; command[2] = 0x30; command[3] = 0x31; command[4] = 0x30; // 子命令 command[5] = 0x30; command[6] = 0x30; command[7] = 0x31; command[8] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[0]; // 软元件类型 command[9] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[1]; command[10] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[0]; // 起始地址的地位 command[11] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[1]; command[12] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[2]; command[13] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[3]; command[14] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[4]; command[15] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[5]; command[16] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[0]; // 软元件点数 command[17] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[1]; command[18] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[2]; command[19] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[3]; buffer.CopyTo(command, 20); return(command); }
/// <summary> /// 从三菱地址,是否位读取进行创建读取Ascii格式的MC的核心报文 /// </summary> /// <param name="addressData">三菱Mc协议的数据地址</param> /// <param name="isBit">是否进行了位读取操作</param> /// <returns>带有成功标识的报文对象</returns> public static byte[] BuildAsciiReadMcCoreCommand(McAddressData addressData, bool isBit) { byte[] command = new byte[20]; command[0] = 0x30; // 批量读取数据命令 command[1] = 0x34; command[2] = 0x30; command[3] = 0x31; command[4] = 0x30; // 以点为单位还是字为单位成批读取 command[5] = 0x30; command[6] = 0x30; command[7] = isBit ? (byte)0x31 : (byte)0x30; command[8] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[0]; // 软元件类型 command[9] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[1]; command[10] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[0]; // 起始地址的地位 command[11] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[1]; command[12] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[2]; command[13] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[3]; command[14] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[4]; command[15] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[5]; command[16] = MelsecHelper.BuildBytesFromData(addressData.Length)[0]; // 软元件点数 command[17] = MelsecHelper.BuildBytesFromData(addressData.Length)[1]; command[18] = MelsecHelper.BuildBytesFromData(addressData.Length)[2]; command[19] = MelsecHelper.BuildBytesFromData(addressData.Length)[3]; return(command); }
/// <summary> /// 根据类型地址长度确认需要读取的报文 /// </summary> /// <param name="address">起始地址</param> /// <param name="length">长度</param> /// <param name="networkNumber">网络号信息</param> /// <param name="networkStationNumber">网络站号信息</param> /// <returns>带有成功标志的指令数据</returns> public static OperateResult <byte[]> BuildReadCommand(string address, ushort length, byte networkNumber = 0, byte networkStationNumber = 0) { OperateResult <MelsecMcDataType, ushort> 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] = 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]; _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> /// 以字为单位,创建ASCII数据写入的核心报文 /// </summary> /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param> /// <param name="value">实际的原始数据信息</param> /// <param name="analysisAddress">对地址分析的委托方法</param> /// <returns>带有成功标识的报文对象</returns> public static OperateResult <byte[]> BuildAsciiWriteWordCoreCommand(string address, byte[] value, Func <string, OperateResult <MelsecMcDataType, int> > analysisAddress) { OperateResult <MelsecMcDataType, int> analysis = analysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } if (value == null) { value = new byte[0]; } 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[] command = new byte[20 + value.Length]; command[0] = 0x31; // 批量写入的命令 command[1] = 0x34; command[2] = 0x30; command[3] = 0x31; command[4] = 0x30; // 子命令 command[5] = 0x30; command[6] = 0x30; command[7] = 0x30; command[8] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0]; // 软元件类型 command[9] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1]; command[10] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0]; // 起始地址的地位 command[11] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1]; command[12] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2]; command[13] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3]; command[14] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4]; command[15] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5]; command[16] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[0]; // 软元件点数 command[17] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[1]; command[18] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[2]; command[19] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[3]; value.CopyTo(command, 20); return(OperateResult.CreateSuccessResult(command)); }
/// <summary> /// 以位为单位,创建ASCII数据写入的核心报文 /// </summary> /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param> /// <param name="value">原始的bool数组数据</param> /// <param name="analysisAddress">对地址分析的委托方法</param> /// <returns>带有成功标识的报文对象</returns> public static OperateResult <byte[]> BuildAsciiWriteBitCoreCommand(string address, bool[] value, Func <string, OperateResult <MelsecMcDataType, int> > analysisAddress) { OperateResult <MelsecMcDataType, int> analysis = analysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } if (value == null) { value = new bool[0]; } byte[] buffer = value.Select(m => m ? (byte)0x31 : (byte)0x30).ToArray( ); byte[] command = new byte[20 + buffer.Length]; command[0] = 0x31; // 批量写入的命令 command[1] = 0x34; command[2] = 0x30; command[3] = 0x31; command[4] = 0x30; // 子命令 command[5] = 0x30; command[6] = 0x30; command[7] = 0x31; command[8] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0]; // 软元件类型 command[9] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1]; command[10] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0]; // 起始地址的地位 command[11] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1]; command[12] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2]; command[13] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3]; command[14] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4]; command[15] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5]; command[16] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[0]; // 软元件点数 command[17] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[1]; command[18] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[2]; command[19] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[3]; value.CopyTo(command, 20); return(OperateResult.CreateSuccessResult(command)); }
/// <summary> /// 以字为单位,创建ASCII数据写入的核心报文 /// </summary> /// <param name="addressData">三菱Mc协议的数据地址</param> /// <param name="value">实际的原始数据信息</param> /// <returns>带有成功标识的报文对象</returns> public static byte[] BuildAsciiWriteWordCoreCommand(McAddressData addressData, byte[] value) { if (value == null) { value = new byte[0]; } 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[] command = new byte[20 + value.Length]; command[0] = 0x31; // 批量写入的命令 command[1] = 0x34; command[2] = 0x30; command[3] = 0x31; command[4] = 0x30; // 子命令 command[5] = 0x30; command[6] = 0x30; command[7] = 0x30; command[8] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[0]; // 软元件类型 command[9] = Encoding.ASCII.GetBytes(addressData.McDataType.AsciiCode)[1]; command[10] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[0]; // 起始地址的地位 command[11] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[1]; command[12] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[2]; command[13] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[3]; command[14] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[4]; command[15] = MelsecHelper.BuildBytesFromAddress(addressData.AddressStart, addressData.McDataType)[5]; command[16] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[0]; // 软元件点数 command[17] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[1]; command[18] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[2]; command[19] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[3]; value.CopyTo(command, 20); return(command); }
/// <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> /// 生成位写入的数据报文信息,该报文可直接用于发送串口给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.CS) { startAddress += (ushort)(startAddress + 0x01C0); } else if (analysis.Content1 == MelsecMcDataType.CC) { startAddress += (ushort)(startAddress + 0x03C0); } else if (analysis.Content1 == MelsecMcDataType.CN) { startAddress += (ushort)(startAddress + 0x0E00); } else if (analysis.Content1 == MelsecMcDataType.TS) { startAddress += (ushort)(startAddress + 0x00C0); } else if (analysis.Content1 == MelsecMcDataType.TC) { startAddress += (ushort)(startAddress + 0x02C0); } else if (analysis.Content1 == MelsecMcDataType.TN) { 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)); }