从原理到代码理解CRC循环冗余校验

这篇具有很好参考价值的文章主要介绍了从原理到代码理解CRC循环冗余校验。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述:本文详细介绍了CRC循环冗余计算的数学原理,算法中使用的参数说明,并以Modbus协议中的CRC-16算法为例,进行手算验证,同时提供LabVIEW和C语言的直接计算CRC-16 值的代码以及C的查表计算CRC-16代码和代码原理的说明。

一、笔者个人经历

初次接触CRC校验是因为项目需要上位机软件来记录PLC寄存器中的数据,实现PLC控制全过程中关键数据的记录和查询。上位机软件使用LV进行编写,数据的获取通过Modbus TCP实现,因为当时对Modbus和CRC都不是很熟悉,就采用了最成熟简单的办法,直接调用了第三方的Modbus工具包,项目功能也是顺利实现。之后又遇到一个项目,需要上位机作为从机,回应主控的Modbus RTU指令,这次没有选择直接使用Modbus工具包,而是使用《LabVIEW宝典》中Modbus CRC-16校验算法,根据Modbus RTU协议自主编程完成了项目要求。后来因为做嵌入式单片机,又了解使用了CRC-8和CRC-16的查表算法,也是没有详细了解过CRC循环冗余校验的原理,仅仅是可以熟练实现功能。直到后来遇到一个项目,需要用示波器捕捉并分析出未知的通信帧的通信协议,帧头,帧尾很快通过对比分析了出来,通信内容也是反复实验分析出具体数据字节和位的意义,就是校验方式分析不出,但是可以肯定数据帧是一定包含校验字节的,那时才认真开始考虑CRC循环冗余算法,试图找出数据帧的校验规则,很惭愧没有分析出来,后来是通过第三方的帮助才解决了这个问题,但是当时脑中留下了很多问号和片段式的思考及部分无序的笔记,现在重新进行了整理、思考和验证,形成此文,希望可以解答对CRC循环冗余校验算法有疑问的同学的困惑。

二、CRC循环冗余校验原理

百度CRC可以很容易的获取CRC的定义:CRC(Cyclic Redundancy Check),即循环冗余校核,是一种根据网络数据包或电脑文件等数据产生简短固定位数校核码的快速算法,主要用来检测或校核数据传输或者保存后可能出现的错误。CRC利用除法及余数的原理,实现错误侦测的功能,具有原理清晰、实现简单等优点。

首先明确CRC是一种数据校验方法,与和校验、异或校验功能相同,常用于通信的双方判断通信帧在通信过程中数据传输是否正确,如校验不通过则需要考虑舍弃此通信帧,同时需根据需要判断是否需要向发送方反馈通信异常的情况。

1、模2运算

从百度到的CRC定义中可以看到CRC是利用除法和余数的原理,这里所说的除法和余数的原理就是模2算法了,下面是模2算法的百度定义。

模2运算是一种二进制算法,CRC校验技术中的核心部分。与四则运算相同,模2运算也包括模2加法、模2减法、模2乘法、模2除法四种二进制运算。与四则运算不同的是模2运算不考虑进位和借位,模2算术是编码理论中多项式运算的基础。模2算术在其他数字领域中的应用也是很广泛的。

这里可以得出模2算法是不考虑进位和借位的,也就可以理解为每位都是独立的,不会影响其他位也不会被其他位影响,这点在后文中的计算验证部分有体现。

下面是模2运算的四则运算法则:

0+0=0;0+1=1;1+0=1;1+1=0;

0-0 =0;0-1=1;1-0=1;1-1=0;

0*0=0;0*1=0;1*0=0;1*1=1;

0/1=0; 1/1=1;

CRC算法中主要使用到的就是模2减法和模2除法。通过上述模2减法法则可以发现,模2减法实际和异或运算在结果上是完全相同的,也就不再过多描述。这里最关键的是多位二进制的除法,这是CRC校验的核心部分。模2除法具有以下性质:

(1)每一位除的结果不影响其他位,即不向上一位借位;

(2)当被除数的位数小于除数位数时,则商为0,被除数就是余数,也可以理解为被除数首位为0时,商为0。

(3)只要被除数的位数和除数一样多,且最高位为1,不管其他位是什么数,皆可商1,也可以理解为被除数首位为1,商为1,余数为被除数与除数的模2减的结果;

(4)要保证每次除完首位都为0,才能进行右移;

(5)当最后余数的位数小于除数位数时,除法停止。

通过对上述多位二进制的模2除法性质的思考,我们可以感觉到模2除与循环异或的本质是相同的,这个可以通过下文中具体的计算过程体现。

2、CRC算法参数

这里给大家推荐一个很好用的CRC计算工具:

labview crc16校验,算法,c语言,单片机,Powered by 金山文档

这个计算工具包含了很多种CRC算法,并且标示出了具体的关键参数,从我个人的使用经历上来说,需要注意的就仅仅是CRC-16 Modbus的计算结果是高字节在前,低字节在后的,这个与实际使用中通常低字节在前高字节在后不同,需要注意一下。下面我们就以CRC-16 Modbus为例对CRC算法进行说明。

labview crc16校验,算法,c语言,单片机,Powered by 金山文档
  1. 标准CRC生成多项式

每种CRC算法的标准生成多项式可能是不同的,这个需要进行注意。从上面截图的左下方我们可以得知,CRC-16 Modbus的标准生成多项式是X16+X15+X2+1,其中1可以换成X0。这样就很容易可以看出,16、15、2、0这些数字代表的是多位二进制数的数位,则标准生成多项式可写为1 1000 0000 0000 0101,对应十六进制就是0x18005,也就是对应上图右侧的 Poly:0x8005。这里的0x8005实际是标准生成多项式的简记式,因为标准生成多项式的最高位固定为1,故在简记式中就忽略了最高位1了,同时在程序编程中实际使用的也是简记式,这个在下文的程序部分有所体现。

  1. CRC初始值

初始值,这个也是根据具体哪种CRC标准来确定的,不同的CRC标准对应不同的计算初始值。还是以CRC-16 Modbus为例,计算初始值就是0xFFFF,对应上图Init:0xFFFF。计算初始值先与需要校验的数据的首字节数据进行异或,异或后结果进行模2除法运算,这个后续程序部分会体现。

  1. 正序/反序

就像串口通信需要考虑低位先传还是高位先传一样,循环冗余计算时也需要考虑从高位开始还是低位开始,即编程时需要考虑数据进行左移还是右移。需要说明的一点是,数据进行正序或者反序,最后的结果是不相同的,这个下文也会进行验证说明。上图计算工具中是通过RefIn和RefOut来进行体现的。

RefIn:true或false表示在进行计算之前,原始数据是否翻转,如原始数据:0x34 = 0011 0100,如果REFIN为true,进行翻转之后为0010 1100 = 0x2C。

RefOut:true或false表示运算完成之后,得到的CRC值是否进行翻转,如计算得到的CRC值:0x97 = 1001 0111,如果REFOUT为true,进行翻转之后为1110 1001 = 0xE9。

以CRC-16 Modbus为例,都是True,则表示反序循环冗余校验。这个结合下文程序会更好理解,下文也会进行相应的说明。

(4)CRC结果异或值

CRC结果异或值就是CRC循环冗余计算的结果与CRC结果异或值进行异或处理,结果为CRC计算的最终值,对应上图中的XorOut:0x0000。

3、手算CRC算法及验证

前面已经介绍了模2算法以及CRC算法的参数,下面就来验证一下上面的理论是否正确。还是以CRC-16 Modbus为例,对单字节0x12数据计算校验值。

首先需要确定CRC-16 Modbus算法的参数:

(1)标准生成多项式为X16+X15+X2+1,转换成二进制则为1 1000 0000 0000 0101;

(2)初始值为0xFFFF;

(3)采用反序的计算顺序;

(4)CRC结果异或值为0x0000;

然后就按照CRC-16 Modbus算法来进行计算,

0x12转为二进制为0001 0010;

与0xFFFF即1111 1111 1111 1111异或,结果为1111 1111 1110 1101;

反序为1011 0111 1111 1111;

下面进行模2除,被除数为1011 0111 1111 1111 0000 0000,除数为1 1000 0000 0000 0101,因为通信帧的基本单位是字节,所以被除数为1011 0111 1111 1111后面加8个0。

labview crc16校验,算法,c语言,单片机,Powered by 金山文档

模2除余数为1111 1100 1011 0010;(这里需要注意一下,CRC循环冗余算法中关注的是模2除的余数,而不是商)

反序为0100 1101 0011 1111,即0x4D3F;

结果再与0x0000进行异或,最终结果为0x4D3F。

利用上面介绍的CRC计算小工具进行验证,结果如下图所示。

labview crc16校验,算法,c语言,单片机,Powered by 金山文档

同理,笔者针对不同标准生成多项式进行手算实验,选择了CRC-32 对0x12进行CRC校验,手算结果与CRC计算工具结果相同。

同时针对数据的正序反序问题,选择CRC-8对0x12进行CRC校验,手算结果与CRC计算工具结果相同。

对于多字节数据的校验过程是:首先首字节与初始默认值进行异或校验,结果作为被除数进行模2除法;下一个字节与上一个字节的模2除法的结果进行异或,作为下一次模2除法的被除数;以此类推,这个在下文代码部分体现。

笔者针对多字节也进行了手算实验,选择了CRC-16 Modbus对0x12、0x34两个字节进行了CRC校验,手算结果与CRC计算工具结果相同。

三、CRC 编程实现方法

1、直接计算法

CRC算法这里还是以CRC-16 Modbus为例,其直接计算编程实现过程为:

1)设置CRC寄存器,并给其赋值0xFFFF。
2)将数据的第一个8-bit字符(将此8位高位补0为16位)与16位CRC寄存器的值进行异或,并把结果存入CRC寄存器。
3)CRC寄存器向右移(即最低位方向)一位,MSB补零,移出并检查LSB。
4)如果LSB为0,重复第三步;若LSB为1,CRC寄存器与多项式码(0xA001)相异或。此时的0xA001即为0x8005的反序。
注意:该步检查LSB应该是右移前的LSB,即第3步前的LSB。
5)重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。
6)重复第2至第5步直到所有数据全部处理完成。
7)最终CRC寄存器的内容即为CRC值。

这里对上文中提及的标准多项式和简记式的区别再进行一下说明:

在上文中手算部分可以看到实际标准多项式最高位对应被除数的那一位必定是1,与标准多项式最高位异或的结果或者说模2减的结果必定是0,因此,在步骤4)就是仅判断LSB是1还是0,进而确定是先进行异或再移位还是直接进行移位,而不参与异或运算,同时也可以理解上述步骤中仅涉及简记式进行异或或者说模2减。

读者可以结合上文中的手算部分的运算步骤来理解这里的处理步骤,关键是理解模2除和数据右移的关系,笔者这里不再进行过多说明。

LabVIEW直接计算 CRC-16 Modbus:

labview crc16校验,算法,c语言,单片机,Powered by 金山文档

程序中while循环实际就是模2除法的体现。

C语言直接计算CRC-16 Modbus:

unsigned short do_crc(unsigned char *ptr, int len)

{

unsigned char i;

unsigned int crc16 = 0xFFFF;

while(len--)

{

crc16^= *ptr++;

for (i = 0; i < 8; ++i)

{

if (crc16 &0x0001)

crc16 = (crc16 >> 0x01) ^ 0xA001;

else

crc16 = (crc16 >> 0x01);

}

}

return crc16;

}

这里有一点需要注意的是,返回的CRC16为16位数,分为两个字节,高低字节需转换(仅针对Modbus,因为modbus一般要求校验值低位在前高位在后)。

2、查表法

对于查表法,其实就是利用空间换时间,通过直接查询CRC运算结果表格来减少计算时间,这个在嵌入式单片机方面使用较多,这边还是以CRC-16 Modbus为例。

首先针对表格进行说明:

因为标准生成多项式为X16+X15+X2+1,则可以确定校验结果为2字节,因此表格分为高字节和低字节,高低位CRC数组中(即下面的 Table_CRCL[256] 和 Table_CRCH[256]中 )同下标的两个单字节数组合成一个双字节校验值。

关于下面表格中数值,是使用CRC-16,(标准生成多项式为X16+X15+X2+1;初始值0x0000;RefIn:True,RefOut:True,即反序;XorOut:0x0000)计算的0-255的CRC值。例如0x01按照上述CRC算法,结果是0xC0C1,即对应Table_CRCH[1]=0xC0和Table_CRCL[1]=0xC1。这里读者可能有疑问,为什么不是使用CRC-16 Modbus的算法?对比CRC-16 Modbus和上述算法的参数,可以看到仅仅是初始值不同,CRC-16 Modbus 初始值为0xFFFF。这里先明确,表的意义是取代模2除法的计算过程。

再回到之前的手算部分,即如下所示。

labview crc16校验,算法,c语言,单片机,Powered by 金山文档

从上式可以发现,被除数从左边起,8位及之后的7位,即1111 1111,这些数位仅参与异或且全程参与异或,或者说模2减,而异或是符合交换律的,即A^B^C=A^C^B,则1111 1111也可最后再参与异或,而0x00与任何单字节数异或均为单字节数本身,则上式被除数可以改成1011 0111 0000 0000 0000 0000 ,最后的余数低字节再与原被除数高字节异或,得到的数就是符合CRC-16 Modbus算法的最终的低字节值,也就是说原被除数高字节的值即初始值或者上一个模2除的结果的高字节的值仅影响模2除余数的低字节值,这也就是下文代码部分为什么这么写的原因。

C语言查表计算CRC-16 Modbus:

const uint8_t Table_CRCL[256] = // CRC 高位字节值表

{

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,

0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,

0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,

0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40

};

const uint8_t Table_CRCH[256] = // CRC高位位字节值表

{

0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,

0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,

0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,

0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,

0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,

0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,

0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,

0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,

0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,

0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,

0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,

0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,

0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,

0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,

0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,

0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,

0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,

0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,

0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,

0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,

0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,

0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,

0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,

0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,

0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,

0x43, 0x83, 0x41, 0x81, 0x80, 0x40

};

uint16_t CRC16(uint8_t *puchMsg, uint8_t DataLen)

{

uint8_t CRCH= 0xFF ; // 高CRC字节初始化

uint8_t CRCL = 0xFF ; // 低CRC 字节初始化

uint8_t Index ; // CRC表中的索引

while (DataLen--)

{

Index = CRCL ^ *puchMsg++ ;

CRCL = CRCH ^ CRCL[Index];

CRCH = CRCH[Index];

}

return ((uint16_t)CRCL<< 8 | CRCH); // Modbus校验值一般低字节在前,高字节在后

}

四、总结

本文选择以CRC-16 Modbus算法标准进行了详细的举例及手算验证,同时笔者也对比其他算法,如CRC-8,CRC-32进行了针对性的验证,结果均证明正确。之所以选择CRC-16 Modbus,是因为这个是平时较为常见的CRC算法,尤其是工控领域,同时也相信读者举一反三的能力,可以按照本文介绍方法掌握其他CRC算法。本文编写期间对文字,计算及代码反复考量验证,力求正确性和逻辑性,转发及引用请注明出处。

——文章来自宋雨的个人分享文章来源地址https://www.toymoban.com/news/detail-762809.html

到了这里,关于从原理到代码理解CRC循环冗余校验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JAVA获取CRC(即循环冗余校验)

    前言:网上查了很多,CRC计算时,除数长度太长无法计算,所以写此文章。希望大家喜欢!     CRC(Cyclic Redundancy Check),即循环冗余校核,是一种根据网络数据包或电脑文件等数据产生简短固定位数 校核码 的快速算法。      CRC校验本质上是选取一个合适的 除数 ,要进行校

    2024年02月06日
    浏览(29)
  • 【基础知识】CRC(循环冗余校验)直接计算和查表法

    校验是什么,个人理解就是经过一个算法,使用大量数据(几MB的数据)生成较小长度的一串信息(如16Bit),并切要做到 原数据不同时,生成的信息大概率不同(不是加密算法不考虑刻意造数据的情况) 原数据中任意一个或几个数据出现错误时,生成的信息不同(所有的原信

    2024年02月05日
    浏览(41)
  • CRC冗余校验的原理和FPGA实现思路

    CRC校验码,顾名思义是用于 校验 的。它可以用于检测数据传输过程中是否出现错误(某些位,或某几位,或者某块区域位错误),反正 可以知道数据出错了,但是不能纠错 。 CRC校验,本质上是模2除法求余。将发送信息 M 当做被除数,发送方和接收方共同约定一个除数 G

    2024年02月08日
    浏览(50)
  • 计算机网络:数据链路层之差错控制、奇偶校验码、CRC循环冗余码、海明码

    带你度过期末难关 文章目录 一、差错控制 1、冗余编码 2、编码VS编码 二、检错编码 1、奇偶校验码 2、CRC循环冗余码 三、纠错编码————海明码 海明距离 1、确定校验码位数r 2、确定校验码和数据的位置 3、求出校验码的值 4、检错并纠错 纠错的方法一: 纠错方法二: 总

    2024年02月04日
    浏览(42)
  • 题解校验码—CRC循环校验码与海明校验码

    一个编码系统的码距是 任意两个码字 的最小距离。 例如个编码系统采用三位长度的二进制编码,若该系统有四种编码分别为:000,011,100,111,此编码系统中000与111的码距为3;011与000的码距为2;011与111的码距为1,则该编码系统的码距为1。 码距计算方法:两个编码按位异

    2024年02月04日
    浏览(32)
  • CRC校验码生成逻辑的实现原理详解——结合C语言和Verilog语言代码分析

    因为前段时间用到CRC校验码,所以在网上找到了很多有关CRC校验码计算原理以及生成CRC校验码的代码实现(包括C语言和Verilog语言的实现)的文章,但关于CRC校验码代码实现的原理未能找到相关文章,于是自己结合C语言和Veirlog语言的实现代码以及CRC校验码的计算原理,对CR

    2023年04月22日
    浏览(87)
  • C#: CRC8,CRC16,CRC32 校验代码

    说明:CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似

    2024年01月18日
    浏览(31)
  • CRC校验(2):CRC32查表法详解、代码实现及CRC反转

    对于现在的CPU来说,基本上都在硬件上实现了CRC校验。但我们还是想用软件来实现一下CRC的代码,这样可以更深入地理解里面的原理。所以这一节就来详细地解释如何使用查表法从软件上来实现CRC-32的校验。另外,CRC还有一种反转的情况,实际上反转和不反转没有什么太大的

    2024年02月09日
    浏览(140)
  • CRC32校验算法原理及计算说明

    本文主要介绍如何使用CRC32校验算法计算得出FCS(Frame Check Sequence帧检验序列). 参考: 1、CRC32加密算法原理 2、CRC多项式对应代码 作用:在远距离数据通信中,为确保高效而无差错地传送数据,对数据进行校验即差错控制。 CRC原理实际上就是在一个K位二进制数据序列之后附

    2023年04月22日
    浏览(32)
  • CRC校验原理与FPGA实现(含推导过程)

      CRC校验全称为循环冗余校验(Cyclic Redundancy Check),常用于数据传输中的错误检测。   在学习CRC校验前,需要了解CRC校验中的几个基本概念: NAME:参数模型名称,比如CRC-8、CRC-16、CRC-32等 WIDTH:CRC校验位宽度 POLY:多项式的简写,用十六进制表示。例如:CRC-8的多项式

    2024年02月03日
    浏览(77)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包