CRC校验的原理及实现方法

一、CRC校验介绍

        循环冗余校验码(CRC),是一种常用的、具有检错、纠错能力的校验码,在早期的通信中运用广泛。循环冗余校验码常用于外存储器和计算机同步通信的数据校验。循环冗余校验是通过某种数学运算来建立数据位和校验位的约定关系的。

        与奇偶校验、和校验、异或校验等校验方式不同,CRC校验的计算过程相对复杂很多。

二、模2除法介绍

        CRC校验原理虽然看起来比较复杂,其实也不难理解,其根本思想就是先在要发送的帧后面附加一个数,生成一个新帧发送给接收端。当然,这个附加的数不是随意的,它要使所生成的新帧能与发送端和接收端共同选定的某个特定数整除。这里不是直接采用二进制除法,而是采用一种称之为“模2除法”。到达接收端后,再把接收到的新帧除以(同样采用“模2除法”)这个选定的除数。因为在发送端发送数据帧之前就已通过附加一个数,做了“去余”处理,所以结果应该是没有余数,结果能够被除数整除。如果有余数,则表明该帧在传输过程中出现了差错。

        这里,为了能够对CRC校验有深入了解,我们来介绍一下模2除法。与“算术除法”类似,但它既不向上位借位,也不比较除数和被除数的相同位数值的大小,只要以相同位数进行相除即可。模2减法运算实际上是按位异或运算。也就是比较后,两者对应位相同则结果为“0”,不同则结果为“1”。如下图所示,二进制的数1010101除以1001,结果得到商为1011,余数为110。

三、CRC校验原理

        上面我们对CRC校验进行了简单介绍,下面我们就来看看CRC校验是如何实现的。

       首先,为了进行CRC校验,发送端和接收端要约定一个除数,这个除数通常是以多项方式表示,这个多项式也称之为“生成多项式”。如常用的多项式x4 + x + 1,表示的除数为10011,多项式x16 + x15 + x2 + 1表示的除数为11000000000000101,下表列出了常用的除数多项式公式。

CRC算法名称多项式公式宽度多项式初始值结果异或值输入反转输出反转
CRC-4/ITUx4 + x + 14030000truetrue
CRC-5/EPCx5 + x3 + 15090900falsefalse
CRC-5/ITUx5 + x4 + x2 + 15150000truetrue
CRC-5/USBx5 + x2 + 15051F1Ftruetrue
CRC-6/ITUx6 + x + 16030000truetrue
CRC-7/MMCx7 + x3 + 17090000falsefalse
CRC-8x8 + x2 + x + 18070000falsefalse
CRC-8/ITUx8 + x2 + x + 18070055falsefalse
CRC-8/ROHCx8 + x2 + x + 1807FF00truetrue
CRC-8/MAXIMx8 + x5 + x4 + 18310000truetrue
CRC-16/IBMx16 + x15 + x2 + 116800500000000truetrue
CRC-16/MAXIMx16 + x15 + x2 + 11680050000FFFFtruetrue
CRC-16/USBx16 + x15 + x2 + 1168005FFFFFFFFtruetrue
CRC-16/MODBUSx16 + x15 + x2 + 1168005FFFF0000truetrue
CRC-16/CCITTx16 + x12 + x5 + 116102100000000truetrue
CRC-16/CCITT-FALSEx16 + x12 + x5 + 1161021FFFF0000falsefalse
CRC-16/X25x16 + x12 + x5 + 1161021FFFFFFFFtruetrue
CRC-16/XMODEMx16 + x12 + x5 + 116102100000000falsefalse
CRC-16/DNPx16 + x13 + x12 + x11 + x10 + x8 + x6 + x5 + x2 + 1163D650000FFFFtruetrue
CRC-32x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 13204C11DB7FFFFFFFFFFFFFFFFtruetrue
CRC-32/MPEG-2x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 13204C11DB7FFFFFFFF00000000falsefalse

        选定了除数之后,需要在要发送的数据后面加上k-1位“0”,k为除数的位数。然后以这个加了k-1个“0“的新数(一共是m+k-1位)以“模2除法”方式除以上面这个除数,所得到的余数就是这个数据的CRC校验码。但要注意的是,余数的位数一定要是比除数位数只能少一位,即使前面位是0,甚至是全为0(附带好整除时)也都不能省略。

        最后,再把这个校验码附加在原数据后面,构建一个新帧发送到接收端;最后在接收端再把这个新帧以“模2除法”方式除以前面选择的除数,如果没有余数,则表明该帧在传输过程中没出错,否则出现了差错。

        下面,我们通过一个例子来说明一下,CRC校验的计算过程。

       假设我们计算十六进制数0xBB的CRC校验码,我们使用的生成多项式为x4 + x + 1。则待计算的数表示为二进制位1011 1011,除数为10011。由于生成多项式的位数为5,根据上面的介绍,得知CRC校验码的位数为4(校验码的位数比生成多项式的位数少1)。因此在原始数据后面再加4个0,得到1011 1011 0000,然后把这个数以“模2除法”方式除以生成多项式,得到的余数(即CRC码)为1111,如下图所示。

        把上步计算得到的CRC校验1111替换原始帧1011 1011 0000后面的四个“0”,得到新帧1011 1011 1111。再把这个新帧发送到接收端。当以上新帧到达接收端后,接收端会把这个新帧再用上面选定的除数10011以“模2除法”方式去除,验证余数是否为0,如果为0,则证明该帧数据在传输过程中没有出现差错,否则出现了差错。

四、CRC校验的c代码实现

        CRC校验的计算过程比较复杂,一般代码实现采用查表的方法。下面的代码是CRC16校验实现的代码,对应的CRC算法为CRC-16/MODBUS,生成多项式为x16 + x15 + x2 + 1。

#include <stdio.h>

const unsigned char chCRCHTalbe[] = //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 unsigned char chCRCLTalbe[] = //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
};

unsigned short CRC16(unsigned char* pchMsg, unsigned short wDataLen)
{
	unsigned char chCRCHi = 0xFF; // 高CRC字节初始化
	unsigned char chCRCLo = 0xFF; // 低CRC字节初始化
	unsigned short wIndex; // CRC循环中的索引

	while(wDataLen--)
	{
		// 计算CRC
		wIndex = chCRCLo ^ *pchMsg++ ;
		chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];
		chCRCHi = chCRCLTalbe[wIndex] ;
	}

	return((chCRCHi << 8) | chCRCLo) ;
}

void main()
{
	unsigned char data[]={1,2,3,4,5,6};

	unsigned short result;

	result = CRC16(data,6);

	printf("%X",result);
}

 

  • 11
    点赞
  • 118
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: FPGA CRC校验原理是使用循环冗余校验算法对数据进行校验CRC校验通常用于数据传输或存储时,以防止数据在传输或存储过程中被破坏或篡改。在FPGA中,CRC校验器通常是由硬件实现的模块,可以通过FPGA的可编程逻辑进行设计。 CRC校验原理是将需要校验的数据分成一定大小的数据块,每个数据块都传送时进行校验校验数据块时,FPGA会计算数据块的CRC码,然后与数据传输或存储设备中存储的CRC码进行比较。 在FPGA中,校验数据块的过程通常由硬件实现的模块完成。该模块会输入需要校验的数据块和预定义的CRC码种子,然后按照预定义的算法进行计算。计算完成后,该模块会输出新的CRC码,然后FPGA会与存储或传输设备中的CRC码进行比较,以确定数据块是否正确。 总的来说,FPGA CRC校验是一种用于数据传输或存储过程中数据校验方法。在硬件实现中,FPGA会根据预定义的算法对数据进行计算,并与存储或传输设备中存储的CRC码进行比较,以确保数据传输或存储的可靠性。 ### 回答2: FPGA CRC校验是一种基于硬件的数据校验方法,它通过将待校验的数据流和预定的校验码值一起输入到FPGA芯片中,利用硬件电路实现CRC计算。CRC校验是一种能够检测数据传输过程中是否发生了错误的技术,它可以检测到单比特错、双比特错甚至更多比特的错。 具体来说,FPGA CRC校验实现原理是通过将输入的数据流和预定义的CRC校验码一同送入CRC电路中,经过一系列的移位、异或和反转操作得到校验结果,然后将校验值与输出的校验结果比较,如果出现差错,则表示数据包出现错误。FPGA CRC校验是一种高效、稳定的校验方法,它广泛应用于数字通信、网络传输、存储设备等领域。 总之,FPGA CRC校验是一种依靠硬件实现的数据完整性校验方式,它通过预定义的校验算法计算出数据包的校验值,并与实际校验结果进行比较,从而检测数据传输过程中是否发生了差错,保证数据在传输过程中的安全可靠。 ### 回答3: FPGA作为一种灵活可编程的集成电路,可以灵活地实现各种数字电子系统中的处理、控制、通信、计算等功能,其中CRC校验是一种应用比较广泛的数据校验协议。其原理是在传输数据的时候,通过添加一个校验码到数据后面,接收端可以通过对数据和校验码进行计算来验证数据的准确性。 在FPGA中实现CRC校验,通常采用硬件的实现方式,首先通过CRC算法计算生成CRC校验码表,然后将该表存储在FPGA中。在数据传输过程中,FPGA通过对数据和CRC校验码表进行异或运算,得到计算结果,并将该计算结果加到原始数据的末尾,然后将数据和校验码一起发送。接收端接收数据后,同样对数据和CRC校验码表进行异或计算,并将其与接收到的校验码进行比较,如果相同则表明数据传输正确,否则需要重新传输。 FPGA实现CRC校验具有高速、低功耗、可靠性强等优点,特别适合高速数据传输领域,如网络通信、存储设备、无线通信等领域。此外,FPGA还具有可编程性强、适应性广泛等优点,可以根据不同应用需求进行优化设计,提高数据的可靠性和传输速率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值