public static class ModbusHelper { // 生成写单个线圈(功能码05)的Modbus指令 public static string GenerateWriteSingleCoilCommand(byte deviceAddress, ushort coilAddress, bool value) { byte[] command = new byte[6]; command[0] = deviceAddress; command[1] = 0x05; // 写单个线圈功能码 command[2] = (byte)(coilAddress >> 8); command[3] = (byte)coilAddress; command[4] = value ? (byte)0xFF : (byte)0x00; command[5] = 0x00; // 计算CRC校验 ushort crc = CalculateCRC(command, 6); byte[] crcBytes = BitConverter.GetBytes(crc); // 组合完整命令(包含CRC校验) byte[] fullCommand = new byte[8]; Array.Copy(command, fullCommand, 6); fullCommand[6] = crcBytes[0]; // CRC低字节在前 fullCommand[7] = crcBytes[1]; // CRC高字节在后 // 转换为十六进制字符串 return BitConverter.ToString(fullCommand).Replace("-", ""); } // 验证Modbus响应是否有效 public static bool ValidateResponse(string command, string response) { if (string.IsNullOrEmpty(response) || response.Length < 8) return false; // 解析响应字符串为字节数组 byte[] responseBytes = StringToByteArray(response); // 从原始命令中提取设备地址 byte deviceAddress = StringToByteArray(command.Substring(0, 2))[0]; // 验证设备地址 if (responseBytes[0] != deviceAddress) return false; // 验证功能码(响应中的功能码应与请求相同,若有异常则功能码最高位为1) byte requestFunctionCode = StringToByteArray(command.Substring(2, 2))[0]; byte responseFunctionCode = responseBytes[1]; // 检查是否为异常响应 if ((responseFunctionCode & 0x80) != 0) { byte errorCode = responseBytes[2]; Console.WriteLine($"Modbus异常响应 - 功能码: {requestFunctionCode}, 错误码: {errorCode}"); return false; } // 验证功能码是否匹配 if (responseFunctionCode != requestFunctionCode) return false; // 验证CRC校验 ushort receivedCrc = (ushort)((responseBytes[responseBytes.Length - 2] << 8) | responseBytes[responseBytes.Length - 1]); ushort calculatedCrc = CalculateCRC(responseBytes, responseBytes.Length - 2); return receivedCrc == calculatedCrc; } // 计算Modbus RTU CRC校验 private static ushort CalculateCRC(byte[] data, int length) { ushort crc = 0xFFFF; for (int i = 0; i < length; i++) { crc ^= data[i]; for (int j = 0; j < 8; j++) { if ((crc & 0x0001) != 0) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; } // 将十六进制字符串转换为字节数组 private static byte[] StringToByteArray(string hex) { int length = hex.Length; byte[] bytes = new byte[length / 2]; for (int i = 0; i < length; i += 2) { bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); } return bytes; } }