最近工作需要,使用了CRC16校验。经过网上学习,发现有很多种CRC16校验算法。经过多处资料总结,形成一种通用的CRC16校验方法。
CRC计算原理就不再叙述(网上很多)。现在介绍CRC校验的几个关键参数:
POLY:生成项的简写,以16进制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生成项是0x104C11DB7。
INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。
REFIN:待测数据的每个字节是否按位反转,True或False。
REFOUT:在计算后之后,异或输出之前,整个数据是否按位反转,True或False。
XOROUT:计算结果与此参数异或后得到最终的CRC值。
下面给出CRC16校验的实现代码(C#):
public static byte reverse8(byte c)
{
c = (byte)((c & 0x55) << 1 | (c & 0xAA) >> 1);
c = (byte)((c & 0x33) << 2 | (c & 0xCC) >> 2);
c = (byte)((c & 0x0F) << 4 | (c & 0xF0) >> 4);
return c;
}
public static ushort reverse16(ushort x)
{
x = (ushort)(((x & 0xaaaa) >> 1) | ((x & 0x5555) << 1));
x = (ushort)(((x & 0xcccc) >> 2) | ((x & 0x3333) << 2));
x = (ushort)(((x & 0xf0f0) >> 4) | ((x & 0x0f0f) << 4));
x = (ushort)(((x & 0xff00) >> 8) | ((x & 0x00ff) << 8));
return x;
}
/// <summary>
/// CRC16 校验计算(有输入输出值反转)
/// </summary>
/// <param name="Cmd">输入buffer</param>
/// <param name="CRCini">CRC初值</param>
/// <param name="Poly">多项式</param>
/// <param name="OXans">结果异或值</param>
/// <param name="inDatagainst">输入值反转使能</param>
/// <param name="outDatagainst">输出值反转使能</param>
/// <param name="IsHighBefore">高位在前</param>
/// <param name="nstart">计算起始引索</param>
/// <param name="nend">计算结束引索</param>
/// <returns></returns>
public static byte[] GetCRC16ByPoly(byte[] Cmd, ushort CRCini, ushort Poly, ushort OXans, bool inDatagainst, bool outDatagainst, bool IsHighBefore, int nstart, int nend = 0)
{
ushort CRC = 0;// CRCini;
ushort CRCValue = CRCini;// 0xFFFF;
byte test = 0;
if (nend == 0) nend = Cmd.Length;
for (int i = nstart; i <= nend; i++)
{
if (inDatagainst)
test = reverse8(Cmd[i]);
else
test = Cmd[i];
CRC = (ushort)(test << 8);
for (int j = 0; j < 8; j++)
{
if ((short)(CRCValue ^ CRC) < 0)
{
CRCValue = (ushort)((CRCValue << 1) ^ Poly);
}
else
{
CRCValue = (ushort)(CRCValue <<= 1);
}
CRC <<= 1;
}
}
if (outDatagainst)
CRCValue = reverse16(CRCValue);
CRCValue = (ushort)(CRCValue ^ OXans);
byte[] Check = BitConverter.GetBytes(CRCValue);
if (IsHighBefore == true)
{
return new byte[2] { Check[1], Check[0] };
}
else
{
return Check;
}
}
附录:一些标准的CRC16算法对应的相关参数设置:
CRC算法名称 | 多项式公式 | 多项式 | 初始值 | 结果异或值 | 输入值反转 | 输出值反转 | |
---|---|---|---|---|---|---|---|
CRC-16/IBM | 16+x15+x2+1 | 8005 | 0000 | 0000 | true | true | |
CRC-16/MAXIM | 16+x15+x2+1 | 8005 | 0000 | FFFF | true | true | |
CRC-16/USB | 16+x15+x2+1 | 8005 | FFFF | FFFF | true | true | |
CRC-16/MODBUS | 16+x15+x2+1 | 8005 | FFFF | 0000 | true | true | |
CRC-16/CCITT | 16+x12+x5+1 | 1021 | 0000 | 0000 | true | true | |
CRC-16/CCITT-FALSE | 16+x12+x5+1 | 1021 | FFFF | 0000 | false | false | |
CRC-16/X25 | 16+x12+x5+1 | 1021 | FFFF | FFFF | true | true | |
CRC-16/XMODEM | 16+x12+x5+1 | 1021 | 0000 | 0000 | false | false | |
CRC-16/DNP | 16+x13+x12+x11+x10+x8+x6+x5+x2+1 | 3D65 | 0000 | FFFF | true | true |