using System; using System.Collections.Generic; using System.Text; namespace XMX { public enum CRCType : int { CRC16_IBM = 0, CRC16_MAXIM, CRC16_USB, CRC16_MODBUS, CRC16_CCITT, CRC16_CCITT_FALSE, CRC16_X25, CRC16_XMODEM, CRC16_DNP, CRC32, CRC32_MPEG2, } public class DataCheck { static public CRCInfo GetCRCInfo(CRCType type) { CRCInfo param = null; switch (type) { case CRCType.CRC16_IBM: param = new CRCInfo(0x8005, 0x0000, true, true, 0x0000); break; case CRCType.CRC16_MAXIM: param = new CRCInfo(0x8005, 0x0000, true, true, 0xFFFF); break; case CRCType.CRC16_USB: param = new CRCInfo(0x8005, 0xFFFF, true, true, 0xFFFF); break; case CRCType.CRC16_MODBUS: param = new CRCInfo(0x8005, 0xFFFF, true, true, 0x0000); break; case CRCType.CRC16_CCITT: param = new CRCInfo(0x1021, 0x0000, true, true, 0x0000); break; case CRCType.CRC16_CCITT_FALSE: param = new CRCInfo(0x1021, 0xFFFF, false, false, 0x0000); break; case CRCType.CRC16_X25: param = new CRCInfo(0x1021, 0xFFFF, true, true, 0xFFFF); break; case CRCType.CRC16_XMODEM: param = new CRCInfo(0x1021, 0x0000, false, false, 0x0000); break; case CRCType.CRC16_DNP: param = new CRCInfo(0x3D65, 0x0000, true, true, 0xFFFF); break; case CRCType.CRC32: param = new CRCInfo(0x04C11DB7, 0xFFFFFFFF, true, true, 0xFFFFFFFF); break; case CRCType.CRC32_MPEG2: param = new CRCInfo(0x04C11DB7, 0xFFFFFFFF, false, false, 0x00000000); break; } return param; } static public UInt32 GetCRC(CRCType type, byte[] data) { CRCInfo param; param = GetCRCInfo(type); if (type >= CRCType.CRC16_IBM && type <= CRCType.CRC16_DNP) { return GetCRC16(param, data); } else if (type>=CRCType.CRC32 && type<=CRCType.CRC32_MPEG2) { return GetCRC32(param, data); } return 0; } static public UInt16 GetCRC16(CRCInfo param, byte[] data) { UInt16 crc = (UInt16)param.Init; UInt16 Poly = 0; UInt16 XorOut = (UInt16)param.XorOut; if (param.RefIn) { for (int i = 0; i < 16; i++) { Poly <<= 1; if ((param.Poly & (1u << i)) != 0) { Poly |= 0x01; } } } else { Poly = (UInt16)param.Poly; } foreach (byte b in data) { UInt16 bValue; if (param.RefOut) { bValue = Convert.ToUInt16(b); } else { bValue = Convert.ToUInt16((UInt16)b << 8); } crc = Convert.ToUInt16(crc ^ bValue); for (int i = 0; i < 8; i++) { if (param.RefOut) { if ((crc & 0x01) != 0) { crc >>= 1; crc ^= Poly; } else { crc >>= 1; } } else { if ((crc & 0x8000) != 0) { crc <<= 1; crc ^= Poly; } else { crc <<= 1; } } } } return Convert.ToUInt16(crc ^ XorOut); } static public UInt32 GetCRC32(CRCInfo param, byte[] data) { UInt32 crc = (UInt32)param.Init; UInt32 Poly = 0; UInt32 XorOut = (UInt32)param.XorOut; if (param.RefIn) { for (int i = 0; i < 32; i++) { Poly <<= 1; if ((param.Poly & (1u << i)) != 0) { Poly |= 0x01; } } } else { Poly = (UInt32)param.Poly; } foreach (byte b in data) { UInt32 bValue; if (param.RefOut) { bValue = Convert.ToUInt32(b); } else { bValue = Convert.ToUInt32((UInt32)b << 24); } crc = Convert.ToUInt32(crc ^ bValue); for (int i = 0; i < 8; i++) { if (param.RefOut) { if ((crc & 0x01) != 0) { crc >>= 1; crc ^= Poly; } else { crc >>= 1; } } else { if ((crc & 0x80000000) != 0) { crc <<= 1; crc ^= Poly; } else { crc <<= 1; } } } } return Convert.ToUInt32(crc ^ XorOut); } static public UInt32 GetCheckSum(byte[] data) { UInt32 sum = 0; foreach (byte b in data) { sum += b; } return sum; } static public byte GetXor(byte[] data) { byte xor = 0; foreach (byte b in data) { xor ^= b; } return xor; } } public class CRCInfo { private UInt32 _Poly; private UInt32 _Init; private UInt32 _XorOut; private bool _RefIn; private bool _RefOut; public CRCInfo() : this(0, 0, false, false, 0) { } public CRCInfo(UInt32 poly, UInt32 init, bool refIn, bool refOut, UInt32 xorOut) { _Poly = poly; _Init = init; _RefIn = refIn; _RefOut = refOut; _XorOut = xorOut; } /// /// 多项式 /// public UInt32 Poly { get { return _Poly; } set { _Poly = value; } } /// /// 初始值 /// public UInt32 Init { get { return _Init; } set { _Init = value; } } /// /// 输出CRC异或值 /// public UInt32 XorOut { get { return _XorOut; } set { _XorOut = value; } } /// /// 输入多项式反序 /// public bool RefIn { get { return _RefIn; } set { _RefIn = value; } } /// /// 输出数据反序 /// public bool RefOut { get { return _RefOut; } set { _RefOut = value; } } public override string ToString() { StringBuilder sb = new StringBuilder(); if ((Poly & 0xFFFF0000) != 0) { sb.AppendFormat("Poly: {0:X8}\r\n", Poly); sb.AppendFormat("Init: {0:X8}\r\n", Init); sb.AppendFormat("RefIn: {0}\r\n", RefIn ? "True" : "False"); sb.AppendFormat("RefOut:{0}\r\n", RefOut ? "True" : "False"); sb.AppendFormat("XorOut:{0:X8}", XorOut); } else { sb.AppendFormat("Poly: {0:X4}\r\n", Poly); sb.AppendFormat("Init: {0:X4}\r\n", Init); sb.AppendFormat("RefIn: {0}\r\n", RefIn ? "True" : "False"); sb.AppendFormat("RefOut:{0}\r\n", RefOut ? "True" : "False"); sb.AppendFormat("XorOut:{0:X4}", XorOut); } return sb.ToString(); } } }