CRC16校验研究与实现

       最近工作需要,使用了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/IBM16+x15+x2+1 800500000000truetrue
CRC-16/MAXIM16+x15+x2+1 80050000FFFFtruetrue
CRC-16/USB16+x15+x2+1 8005FFFFFFFFtruetrue
CRC-16/MODBUS16+x15+x2+1 8005FFFF0000truetrue
CRC-16/CCITT16+x12+x5+1 102100000000truetrue
CRC-16/CCITT-FALSE16+x12+x5+1 1021FFFF0000falsefalse
CRC-16/X2516+x12+x5+1 1021FFFFFFFFtruetrue
CRC-16/XMODEM16+x12+x5+1 102100000000falsefalse
CRC-16/DNP16+x13+x12+x11+x10+x8+x6+x5+x2+1 3D650000FFFFtruetrue

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GavinKing2010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值