C# 计算CRC16

我们在做数据传输时,经常会计算一段数据的CRC16。就是传入一段字节数组,得出2个字节的CRC16校验值。

我在这里提供一个计算函数:

//计算CRC16
private byte[] CRC16_C(byte[] data)
{
    byte CRC16Lo;
    byte CRC16Hi;           //CRC寄存器 
    byte CL; byte CH;       //多项式码 ccitt的多项式是x16+x12+x5+1,多项式码是0x1021,但由于ccitt是默认先传LSB而不是MSB,故这里应该将多项式码按bit反转得到0x8408
    byte SaveHi; byte SaveLo;
    byte[] tmpData;
    int Flag;
    CRC16Lo = 0xFF;
    CRC16Hi = 0xFF;
    CL = 0x08;
    CH = 0x84;
    tmpData = data;
    for (int i = 0; i < tmpData.Length; i++)
    {
        CRC16Lo = (byte)(CRC16Lo ^ tmpData[i]); //每一个数据与CRC寄存器进行异或 
        for (Flag = 0; Flag <= 7; Flag++)
        {
            SaveHi = CRC16Hi;
            SaveLo = CRC16Lo;
            CRC16Hi = (byte)(CRC16Hi >> 1);      //高位右移一位 
            CRC16Lo = (byte)(CRC16Lo >> 1);      //低位右移一位 
            if ((SaveHi & 0x01) == 0x01) //如果高位字节最后一位为1 
            {
                CRC16Lo = (byte)(CRC16Lo | 0x80);   //则低位字节右移后前面补1 
            }             //否则自动补0 
            if ((SaveLo & 0x01) == 0x01) //如果LSB为1,则与多项式码进行异或 
            {
                CRC16Hi = (byte)(CRC16Hi ^ CH);
                CRC16Lo = (byte)(CRC16Lo ^ CL);
            }
        }
    }
    byte[] ReturnData = new byte[2];
    ReturnData[0] = CRC16Hi;       //CRC高位 
    ReturnData[1] = CRC16Lo;       //CRC低位 
    return ReturnData;
}


值得注意的是这里的多项式码。对于不同的标准有不同的CRC16计算多项式,本例中采用的是CCITT的计算多项式。不同的多项式有唯一对应的多项式码。有兴趣可以自行search CRC多项式与多项式码的关系。

但是本例中由于CCITT默认是先传LSB的,故多项式码要做一次LSB与MSB的反转。

有心者在实际试验中可以验证。

你可能感兴趣的:(C# 计算CRC16)