namespace SSPCTester.Devices.Protocol; public static class ModbusRtuProtocol { public static ushort ComputeCrc(ReadOnlySpan data) { ushort crc = 0xFFFF; foreach (byte value in data) { crc ^= value; for (int i = 0; i < 8; i++) crc = (ushort)((crc & 1) != 0 ? (crc >> 1) ^ 0xA001 : crc >> 1); } return crc; } public static byte[] BuildRequest(byte slave, byte function, ushort address, ushort valueOrCount) { var frame = new byte[8]; frame[0] = slave; frame[1] = function; frame[2] = (byte)(address >> 8); frame[3] = (byte)address; frame[4] = (byte)(valueOrCount >> 8); frame[5] = (byte)valueOrCount; ushort crc = ComputeCrc(frame.AsSpan(0, 6)); frame[6] = (byte)crc; frame[7] = (byte)(crc >> 8); return frame; } public static void ValidateCrc(ReadOnlySpan frame) { if (frame.Length < 5) throw new InvalidDataException("Modbus 响应长度不足。"); ushort expected = ComputeCrc(frame[..^2]); ushort actual = (ushort)(frame[^2] | frame[^1] << 8); if (expected != actual) throw new InvalidDataException($"Modbus CRC 错误,期望 {expected:X4},实际 {actual:X4}。"); } } public static class ModbusValueConverter { public static double ConvertRaw(ushort rawBits, bool signed, string formula, double range) { double raw = signed ? unchecked((short)rawBits) : rawBits; return formula switch { "A" => raw / 10000.0 * range, "B" => raw / range, _ => throw new InvalidDataException($"不支持换算公式 {formula}") }; } }