crc循环冗余检验


 1. CRC校验原理  

       CRC循环冗余检验是一种通用的错误检测技术,常用于网络通信、数据存储等领域。它通过生成一个校验码来检测数据传输过程中的错误。

      CRC校验的原理是在发送数据时,在数据末尾加上一定位数的校验码,接收方在接受数据时,计算数据与校验码的CRC值与发送方计算的CRC值进行比较。如果两个CRC值不一致,就说明接收到的数据存在差错,需要重发。

       通常,CRC校验使用除法运算来计算CRC值,生成多项式的不同组合和长度将会产生不同的CRC校验码。因此,选择正确的生成多项式是非常重要的,可以有效提高数据传输的可靠性。

     除此之外,还可以通过采取多重校验、差错纠正等方法来进一步提高数据传输的正确性。crc选择的除法是一种特殊的除法模二运算。

2. 模2除法

       也称为二进制异或运算(XOR),是一种逐位比较两个二进制数对应位的值的运算。在二进制异或运算中,当两个数的某一位相同时,结果为0,否则结果为1。例如,对于二进制数1011和1100进行异或运算,它们的对应位不同时,结果为1;对应位相同时,结果为0。因此,它们的异或结果为0111。

        

常见的三种CRC 标准

       余数初始值”就是在计算CRC值的开始,给CRC寄存器一个初始值。“结果异或值”是在其余计算完成后将CRC寄存器的值在与这个值进行一下异或操作作为最后的校验值。

 CRC算法实例

要传输的数据为:1101011011

除数设为:10011

在计算前先将原始数据后面填上4个0:11010110110000,之所以要补0,后面再做解释。


       从这个例子可以看出,采用了模2的加减法后,不需要考虑借位的问题,所以除法变简单了。最后得到的余数就是CRC 校验字。为了进行CRC运算,也就是这种特殊的除法运算,必须要指定个被除数,在CRC算法中,这个被除数有一个专有名称叫做“生成多项式”。生成多项式的选取是个很有难度的问题,如果选的不好,那么检出错误的概率就会低很多。

       有一点要注意,生成多项式经常会说到多项式的位宽(Width,简记为W),这个位宽不是多项式对应的二进制数的位数,而是位数减1。比如CRC8中用到的位宽为8的生成多项式,其实对应得二进制数有九位:100110001。另外一点,多项式表示和二进制表示都很繁琐,交流起来不方便,因此,文献中多用16进制简写法来表示,因为生成多项式的最高位肯定为1,最高位的位置由位宽可知,故在简记式中,将最高的1统一去掉了,如CRC32的生成多项式简记为04C11DB7实际上表示的是104C11DB7。当然,这样简记除了方便外,在编程计算时也有它的用处。位宽为4(W=4),按照CRC算法的要求,计算前要在原始数据后填上W个0,也就是4个0。

代码实现

/*******************************************************************************
  * @函数名称	UpdateCRC16
  * @函数说明   更新输入数据的CRC校验
  * @输入参数   crcIn
                byte
  * @输出参数   无
  * @返回参数   CRC校验值
*******************************************************************************/
uint16_t UpdateCRC16(uint16_t crcIn, uint8_t byte)
{
    uint32_t crc = crcIn;
    uint32_t in = byte|0x100;
    do
    {
        crc <<= 1;
        in <<= 1;
        if (in&0x100)
            ++crc;
        if (crc&0x10000)
            crc ^= 0x1021;
    }
    while (!(in&0x10000));
    return crc&0xffffu;
}

/*******************************************************************************
  * @函数名称	UpdateCRC16
  * @函数说明   更新输入数据的CRC校验
  * @输入参数   data :数据
                size :长度
  * @输出参数   无
  * @返回参数   CRC校验值
*******************************************************************************/
uint16_t Cal_CRC16(const uint8_t* data, uint32_t size)
{
    uint32_t crc = 0;
    const uint8_t* dataEnd = data+size;
	
    while (data<dataEnd)
	{
		crc = UpdateCRC16(crc,*data++);
	}

    crc = UpdateCRC16(crc,0);
    crc = UpdateCRC16(crc,0);
    return crc&0xffffu;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值