C# CRC16 CCITT XModem
核心方法,如果要返回两个字节,则把最后改为 return BitConverter.GetBytes(crc)
private ushort Crc16Ccitt(byte[] bytes) { ushort poly = 0x1021; ushort[] table = new ushort[256]; ushort initialValue = 0x0; ushort temp, a; ushort crc = initialValue; for (int i = 0; i < table.Length; ++i) { temp = 0; a = (ushort)(i << 8); for (int j = 0; j < 8; ++j) { if (((temp ^ a) & 0x8000) != 0) temp = (ushort)((temp << 1) ^ poly); else temp <<= 1; a <<= 1; } table[i] = temp; } for (int i = 0; i < bytes.Length; ++i) { crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]); } return crc; }
提取为类,把查询表提前初始化,避免每次调用都进行计算。
/// <summary> /// CRC16 CCITT XModem计算校验值 /// </summary> public static class CRC16 { /// <summary> /// 多项式 /// </summary> const ushort Polynominal = 0x1021; /// <summary> /// 查询表 /// </summary> static ushort[] table = new ushort[256]; /// <summary> /// 静态构造函数,初始化查询表 /// </summary> static CRC16() { ushort temp, a; for (int i = 0; i < table.Length; ++i) { temp = 0; a = (ushort)(i << 8); for (int j = 0; j < 8; ++j) { if (((temp ^ a) & 0x8000) != 0) temp = (ushort)((temp << 1) ^ Polynominal); else temp <<= 1; a <<= 1; } table[i] = temp; } } /// <summary> /// 计算校验值 /// </summary> /// <param name="data"></param> /// <returns></returns> public static byte[] CheckSum(List<byte> data) { ushort crc = 0x0; for (int i = 0; i < data.Count; ++i) { crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & data[i]))]); } return BitConverter.GetBytes(crc); } /// <summary> /// 计算部分区域的校验值 /// </summary> /// <param name="data"></param> /// <param name="startIndex"></param> /// <param name="count"></param> /// <returns></returns> public static byte[] CheckSumRange(List<byte> data, int startIndex, int count) { return CheckSum(data.GetRange(startIndex, count)); } }
参考资料: