CRC校验算法及C#程序实现

CRC校验算法及C#程序实现
CRC校验算法及C#程序实现

CRC校验算法及C#程序实现

CRC校验可以运用于传输数据过程中的验证,发送端发送有效数据时,先根据有效数据和生成多项式(比如CCITT标准的多项式是X16+X12+X5+1)计算出CRC校验码,把CRC 校验码加到有效数据后面一起发送;当接收数据时,取出前面有效数据部分,用同样生成多项式计算出CRC校验码,然后取出接收数据后面CRC校验码部分,对比两个校验码是否相同。如果相同,认为接收到的数据与发送的数据是一致的,传输正确;如果不同,认为传输数据出错。

CRC(循环冗余校验)算法主要是一个计算除法的过程。算法有两个输入值,第一个是输入的信号,这通常是一个很长的数据,作为被除数。第二个是一个与具体的CRC算法相关的多项式,称为生成多项式,用作除数。基本的计算过程是,两者作模2除法(本质上是对应位做异或运算),余数就是CRC校验码的结果。

I、基本算法(人工笔算):

以CRC16-CCITT为例进行说明,它的生成多项式是X16+X12+X5+1,CRC校验码为16位,生成多项式17位。假如数据流为4字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0];

数据流左移16位,相当于扩大256×256倍,再除以生成多项式0x11021,做不借位的除法运算(相当于按位异或),所得的余数就是CRC校验码。

发送时的数据流为6字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0]、CRC[1]、CRC[0];II、计算机算法1(比特型算法):

1)将扩大后的数据流(6字节)高16位(BYTE[3]、BYTE[2])放入一个长度为16的寄存器;

2)如果寄存器的首位为1,将寄存器左移1位(寄存器的最低位从下一个字节获得),再与生成多项式的简记式异或;

否则仅将寄存器左移1位(寄存器的最低位从下一个字节获得);

3)重复第2步,直到数据流(6字节)全部移入寄存器;

4)寄存器中的值则为CRC校验码CRC[1]、CRC[0]。

III、计算机算法2(字节型算法):

字节型算法的一般描述为:本字节的CRC码,等于上一字节CRC码的低8位左移8位,与上一字节CRC右移8位同本字节异或后所得的CRC码异或。

字节型算法如下:

1)CRC寄存器组初始化为全"0"(0x0000)。(注意:CRC寄存器组初始化全为1时,最后CRC 应取反。)

2)CRC寄存器组向左移8位,并保存到CRC寄存器组。

3)原CRC寄存器组高8位(右移8位)与数据字节进行异或运算,得出一个指向值表的索引。

4)索引所指的表值与CRC寄存器组做异或运算。

5)数据指针加1,如果数据没有全部处理完,则重复步骤2)。

6)得出CRC。

简单例子

下面用一个简单的例子来说明CRC算法的计算过程。输入信号是101111,生成多项式是1001(对应数学表达式为X3+1)。被除数后面需要补充3个0。即101111000对1001做模2除法运算,得到一个3位的余数010,这个就是CRC校验码。在上例中,余数为010。将余数附加到输入信号后面,即发送数据为101111010,取接收端接收到的数据的前六位对1001做模2除法运算,看看得到的CRC校验码是不是等于接收数据的后三位。如果是,传输正

确,如果不是,传输错误。

4 C#程序代码

这是采用比特型算法编写的程序。

以下CRCVerifyLHY类中的GetCRC方法就是用来计算CRC校验码的,在Main函数中byte 数组用来存放要传输的数据(注意:前面两个字节都初始为0,用来存放CRC校验码结果,真正要传输的数据从第三个字节开始)。这里简单地只传输一个字节的数据,如下面的157,可以先人工用笔算出一个CRC校验码,然后看程序的输出是否和人工算的一致,经本人验证,此算法程序应该是正确的。

using System;

using System.Collections.Generic;

using System.Text;

namespace CRCVerify

{

class CRCVerifyLHY

{

//dataStream数组中的dataStream[0]和dataStream[1]为CRC校验码的初始值,即0x0000。其他的数组元素即为要传输的信息码,cRC_16为生成多项式的简记式

//以CRC16-CCITT为例进行说明,CRC校验码为16位,生成多项式17位,其简记式实际是0x11021,

//但是生成多项式的最高位固定为1,故在简记式中忽略最高位1了,CRC16-CCITT的简记式就可以写为0x1021

public static ushort GetCRC(byte[] dataStream, ushort cRC_16)

{

ushort cRC_temp = Convert.ToUInt16((dataStream[dataStream.Length - 1] << 8) + dataStream[dataStream.Length - 2]);

int totalBit = (dataStream.Length - 2) * 8;

for (int i = totalBit - 1; i >= 0; i--)

{

ushort a = Convert.ToUInt16(i / 8);

ushort b = Convert.ToUInt16(i % 8);

ushort nextBit = Convert.ToUInt16((dataStream[a] >> b) & 0x01);

if (cRC_temp >= 32768)

{

cRC_temp = Convert.ToUInt16(((cRC_temp - 32768) << 1) + nextBit);

cRC_temp = Convert.ToUInt16(cRC_temp ^ cRC_16);

}

else

{

cRC_temp = Convert.ToUInt16((cRC_temp << 1) + nextBit);

}

}

return cRC_temp;

}

}

class Program

{

static void Main(string[] args)

{

byte[] array = new byte[] { 0, 0, 157 };

ushort cRC_Result = CRCV erifyLHY.GetCRC(array, 0x1021); Console.WriteLine(cRC_Result);

Console.ReadKey();

}

}

}

建议使用以下:

using System;

namespace USTC

{

///

/// 消息CRC校验算法

///

public class CRC

{

//private int key = 0x11021H;

public CRC()

{

}

public static int GetKey(byte[] data)

{

int count = data.Length;

byte[] buf = new byte[data.Length + 2];

data.CopyTo(buf, 0);

int ptr = 0;

int i = 0;

int crc = 0;

byte crc1, crc2, crc3;

crc1 = buf[ptr++];

crc2 = buf[ptr++];

buf[count] = 0;

buf[count + 1] = 0;

while (--count >= 0)

{

crc3 = buf[ptr++];

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

{

if (((crc1 & 0x80) >> 7) == 1)//判断crc1高位是否为1

{

crc1 = (byte)(crc1 << 1); //移出高位

if (((crc2 & 0x80) >> 7) == 1)//判断crc2高位是否为1

{

crc1 = (byte)(crc1 | 0x01);//crc1低位由0变1

}

crc2 = (byte)(crc2 << 1);//crc2移出高位

if (((crc3 & 0x80) >> 7) == 1) //判断crc3高位是否为1

{

crc2 = (byte)(crc2 | 0x01); //crc2低位由0变1

}

crc3 = (byte)(crc3 << 1);//crc3移出高位

crc1 = (byte)(crc1 ^ 0x10);

crc2 = (byte)(crc2 ^ 0x21);

}

else

{

crc1 = (byte)(crc1 << 1); //移出高位

if (((crc2 & 0x80) >> 7) == 1)//判断crc2高位是否为1

{

crc1 = (byte)(crc1 | 0x01);//crc1低位由0变1

}

crc2 = (byte)(crc2 << 1);//crc2移出高位

if (((crc3 & 0x80) >> 7) == 1) //判断crc3高位是否为1

{

crc2 = (byte)(crc2 | 0x01); //crc2低位由0变1

}

crc3 = (byte)(crc3 << 1);//crc3移出高位

}

}

}

crc = (int)((crc1 << 8) + crc2);

return crc;

}

}

}

CRC校验解读

三种常用的CRC16校验算法的C51程序的优化2009-10-10 09:34:17| 分类:技术知识| 标签:|字号大 CRC校验又称为循环冗余校验,是数据通讯中常用的一种校验算法。它可以有效的判别出数据在传输过程中是否发生了错误,从而保障了传输的数据可靠性。 CRC校验有多种方式,如:CRC8、CRC16、CRC32等等。在实际使用中,我们经常使用CRC16校验。CRC16校验也有多种,如:1005多项式、1021多项式(CRC-ITU)等。在这里我们不讨论CRC算法是怎样产生的,而是重点落在几种算法的C51程序的优化上。 计算CRC校验时,最常用的计算方式有三种:查表、计算、查表+计算。一般来说,查表法最快,但是需要较大的空间存放表格;计算法最慢,但是代码最简洁、占用空间最小;而在既要求速度,空间又比较紧张时常用查表+计算法。 下面我们分别就这三种方法进行讨论和比较。这里以使用广泛的51单片机为例,分别用查表、计算、查表+计算三种方法计算1021多项式(CRC-ITU)校验。原始程序都是在网上或杂志上经常能见到的,相信大家也比较熟悉了,甚至就是正在使用或已经使用过的程序。 编译平台采用Keil C51 7.0,使用小内存模式,编译器默认的优化方式。 常用的查表法程序如下,这是网上经常能够看到的程序范例。因为篇幅关系,省略了大部分表格的内容。 code unsigned int Crc1021Table[256] = { 0x0000, 0x1021, 0x2042, 0x3063,... 0x1ef0 }; unsigned int crc0(unsigned char *pData, unsigned char nLength) { unsigned int CRC16 = 0;

计算法简单实现crc校验

计算法简单实现crc校验 计算法简单实现crc校验 前一段时间做协议转换器的时间用到CRC-16校验,查了不少资料发现都不理想。查表法要建表太麻烦,而计算法觉得那些例子太罗嗦。最后只好自己写了,最后发现原来挺简单嘛:)两个子程序搞定。这里用的多项式为:CRC-16=X16+X12+X5+X0=2 +2 +2+2 =0x11021 因最高位一定为“1”,故略去计算只采用0x1021即可 CRC_Byte:计算单字节的CRC值 CRC_Data:计算一帧数据的CRC值 CRC_HighCRC_Low:存放单字节CRC值 CRC16_HighCRC16_Low:存放帧数据CRC值; ------------------------------------------------------------- ;Functi on:CRConebyte ;Input:CRCByte ;Output:CRC_HighCRC_Low ; ------------------------------------------------------------- CRC_Byte: clrfCRC_Low clrfCRC_High movlw09H movwfv_Loop1 movfCRCByte,w movwfCRC_High CRC: decfszv_Loop1;8次循环,每一位相应计算 gotoCRC10 gotoCRCend CRC10 bcfSTATUS,C rlfCRC_Low rlfCRC_High btfssSTATUS,C   ;gotoCRC;为0不需计算movlw10H;若多项式改变,这里作相应变化xorwfCRC_High,f movlw21H;若多项式改变,这里作相应变化 xorwfCRC_Low,f gotoCRC CRCend: nop nop return ; ------------------------------------------------------------- ;CRCone byteend ; ------------------------------------------------------------- ; ------------------------------------------------------------- ;Functi on:CRCdate ;Input:BufStart(A,B,C)(一帧数据的起始地址)v_Count(要做CRC的字节数);Output:CRC16_HighCRC16_Low(结果); ------------------------------------------------------------- CRC_Data: clrfCRC16_High clrfCRC16_Low CRC_Data10 movfINDF,w

crc校验码计算例题

crc校验码计算例题 1、若信息码字为11100011,生成多项式G(X)=X5+X4+X+1,则计算出的CRC 校验码为?x的最高次幂5则信息码(被除数)补五个0为:1110001100000 除数为110011 ------------10110110 --------------------- 110011/1110001100000 -------110011 ------------------ ---------101111 ---------110011 ------------------ ----------111000 ----------110011 ------------------ ------------101100 ------------110011 ------------------------ -------------111110 -------------110011 ------------------------- ---------------11010 2、信息码为101110101,生成多项式X4+X2+1,求冗余位??? 算法同上被除数补四个0 为:1011101010000 除数为:10101 答案:1100 7E 00 05 60 31 32 33 计算CRC16结果应该是:5B3E 方法如下: CRC-16码由两个字节构成,在开始时CRC寄存器的每一位都预置为1,然后把CRC寄存器与8-bit的数据进行异或(异或:二进制运算相同为0,不同为1;0^0=0;0^1=1;1^0=1;1^1=0),之后对CRC寄存器从

CRC算法及Verilog实现

CRC算法原理及其Verilog实现 1CRC简介 CRC校验是一种在数据通信系统和其它串行传输系统中广泛使用的错误检测手段。通用的CRC标准有CRC-8、CRC-16、CRC-32、CRC-CCIT,其中在网络通信系统中应用最广泛的是CRC-32标准。本文将以CRC-32为例,说明CRC编码的实现方式以及如何用verilog语言对CRC编码进行描述。 2二.模2运算 在说明CRC编码方式之前,首先介绍一下模2运算法则,在CRC运算过程中会使用到模2除法运算。模2运算是一种二进制运算法则,与四则运算相同,模2运算也包括模2加、模2减、模2乘、模2除四种运算。模2运算用“+”表示加法运算,用“-”、“×”或“.”、“/”分别表示减法、乘法和除法运算。与普通四则运算法则不同的是,模2加法是不带进位的二进制加法运算,模2减法是不带借位的二进制减法运算。同时,模2乘法在累加中间结果时采用的是模2加法运算;模2除法求商过程中余数减除数采用的是模2减法运算。因此,两个二进制数进行模2加减法运算时,相当于两个二进制数进行按位异或运算,每一位的结果只与两个数的当前位有关。模2除法在确定商时,与普通二进制除法也略有区别。普通二进制除法中,当余数小于除数时,当前位的商为0,当余数大于等于除数时,当前位的商为1。模2除法在确定当前位的商时,只关心余数的首位,首位为1则商为1,首位为0则商为0。 1.模2加法的定义: 0+0=0,0+1=1,1+0=1,1+1=0。 举例如下: 1010+0110=1100。 2.模2减法的定义:

0-0=0,0-1=1,1-0=1,1-1=0。 举例如下: 1010-0110=1100。 3.模2乘法的定义: 0×0=0,0×1=0,1×0=0,1×1=1。 举例如下: 1011×101=100111 列竖式计算: 1011 × 101 —————— 1011 0000 1011 —————— 100111 其中横线之间的累加过程,采用的是2进制加法,不进位。 4.模2除法: 0/1=0,1/1=1。 举例如下: 1011/101=10,余数为100。 列竖式计算: 10 ———— 101 )1011 101 ———— 001 101

CRC校验算法学习

CRC校验算法学习(这个算法看了很多遍了,都是囫囵吞枣,这次将资料拷贝到这里,好好学习一下) (2008-2-23 23:18)CRC校验采用多项式编码方法。 被处理的数据块可以看作是一个二进制多项式,例如,10110101可以看作是2^7+2^5+2^4+2^2+2^0,多项式乘除法运算过程与普通代数多项式的乘除法相同。多项式的加减法运算以2为模,加减时不进,错位,和逻辑异或运算一致。 采用CRC校验时,发送方和接收方用同一个生成多项式g(x),并且g(x)的首位和最后一位的系数必须为1。CRC的处理方法是:发送方以g(x)去除t(x),得到余数作为CRC 校验码。校验时,以计算的校正结果是否为0为据,判断数据帧是否出错。 CRC校验可以100%地检测出所有奇数个随机错误和长度小于等于k(k为g(x)的阶数)的突发错误。所以CRC的生成多项式的阶数越高,那么误判的概率就越小。 CCITT建议:2048 kbit/s的PCM基群设备采用CRC-4方案,使用的CRC校验采用16位CRC校验。在IBM的同步数据链路控制规程SDLC的帧校验序列FCS中,使用CRC-16。g(x)的位数越高,检错能力就越强。由于CRC-32的可靠性,把CRC-32用于重要数据传输十分合适,所以在通信、计算机等领域运用十分广泛。在一些UART通信控制芯片(如MC6582、Intel8273和Z80-SIO)内,都采用了CRC校验码进行差错控制;以太网卡芯片、MPEG解码芯片中,也采用CRC-32进行差错控制。>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>> (转自https://www.360docs.net/doc/2414441098.html,/forum/viewthread.php?tid=5470&sid=3rrqV omR) CRC校验码的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去。在接收端,则根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。 在数据存储和数据通讯领域,CRC无处不在:著名的通讯协议X.25的FCS(帧检错序列)采用的是CRC. CCITT,ARJ、LHA等压缩工具软件采用的是CRC32,磁盘驱动器的读写采用了CRC16,通用的图像存储格式GIF、TIFF等也都用CRC作为检错手段。 CRC的本质是模-2除法的余数,采用的除数不同,CRC的类型也就不一样。通常,CRC 的除数用生成多项式来表示。最常用的CRC码的生成多项式有CRC16,CRC32. 以CRC16为例,16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(既乘以2^16)后,再除以一个多项式,最后所得到的余数既是CRC码,如下式所示,其中K(X)表示n位的二进制序列数,G(X)为多项式,Q(X)为整数,R(X)是余数(既CRC码)。K(X)>>16=G(x)Q(x)+R(x) 求CRC码所采用模2加减运算法则,既是不带进位和借位的按位加减,这种加减运算实际上就是逻辑上的异或运算,加法和减法等价,乘法和除法运算与普通代数式的乘除法运算是一样,符合同样的规律。生成CRC码的多项式如下,其中CRC-16和CRC-CCITT产生16位的CRC码,而CRC-32则产生的是32位的CRC码 接收方将接收到的二进制序列数(包括信息码和CRC码)除以多项式,如果余数为0,则说明传输中无错误发生,否则说明传输有误,关于其原理这里不再多述。用软件计算CRC 码时,接收方可以将接收到的信息码求CRC码,比较结果和接收到的CRC码是否相同。 CCITT推荐的高级数据链路控制规程HDLC的帧校验序列FCS中,使用CCITT-16即CRC16,其生成多项式为G(x)=x16+x12+x5+1, CRC-32的生成多项式为G(x)=x32+x26+x23+x22+x16+x11+x10+x16+x8+x7+x5+x4+x2+x+1 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

CRC校验PLC算法

CRC校验函数 cBuffer:计算CRC校验码的数组。 iBufLen:该数组的长度。 unsigned int CRC_Verify(unsigned char *cBuffer, unsigned int iBufLen) { unsigned int i, j; //#define wPolynom 0xA001 unsigned int wCrc = 0xffff; unsigned int wPolynom = 0xA001; /*---------------------------------------------------------------------------------*/ for (i = 0; i < iBufLen; i++) { wCrc ^= cBuffer[i]; for (j = 0; j < 8; j++) { if (wCrc &0x0001) { wCrc = (wCrc >> 1) ^ wPolynom; } else { wCrc = wCrc >> 1; } } } return wCrc; } 如何用PLC写上述的CRC校验函数,笔者整理了一个CRC校验计算的子程序。 CRC-16码由两个字节构成,在开始时CRC寄存器的每一位都预置为1(0xffff),然后把CRC寄存器与8-bit的数据进行异或,之后对CRC寄存器从高到低进行移位,在最高位(MSB)的位置补零,而最低位(LSB),移位后已经被移出CRC寄存器)如果为1,则把寄存器与预定义的多项式码(16#A001)进行异或,否则如果LSB为零,则无需进行异或。重复上述的由高至低的移位8次,第一个8-bit数据处理完毕,用此时CRC寄存器的值与下一个8-bit 数据异或并进行如前一个数据似的8次移位。所有的字符处理完成后CRC寄存器内的值即为最终的CRC值。 下面为CRC的计算过程: 1.设置CRC寄存器,并给其赋值FFFF(hex)。 2.将数据的第一个8-bit字符与16位CRC寄存器的低8位进行异或,并把结果存入CRC寄存器。 3.CRC寄存器向右移一位,MSB补零,移出并检查LSB。 4.如果LSB为0,重复第三步;若LSB为1,CRC寄存器与多项式码相异或。 5.重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。 6.重复第2至第5步直到所有数据全部处理完成。 7.最终CRC寄存器的内容即为CRC值。 输入参数: 待校验数据区指针,第一个字节为数据长度

CRC_校验码的计算方法

CRC 校验码的计算方法 CRC从原理到实现=============== 作者:Spark Huang(hcpp@https://www.360docs.net/doc/2414441098.html,) 日期:2004/12/8 摘要:CRC(Cyclic Redundancy Check)被广泛用于数据通信过程中的差错检测,具有很强的检错能力。本文详细介绍了CRC的基本原理,并且按照解释通行的查表算法的由来的思路介绍了各种具体的实现方法。 1.差错检测 数据通信中,接收端需要检测在传输过程中是否发生差错,常用的技术有奇偶校验(Parity Check),校验和(Checksum)和CRC(Cyclic Redundancy Check)。它们都是发送端对消息按照某种算法计算出校验码,然后将校验码和消息一起发送到接收端。接收端对接收到的消息按照相同算法得出校验码,再与接收到的校验码比较,以判断接收到消息是否正确。 奇偶校验只需要1位校验码,其计算方法也很简单。以奇检验为例,发送端只需要对所有消息位进行异或运算,得出的值如果是0,则校验码为1,否则为0。接收端可以对消息进行相同计算,然后比较校验码。也可以对消息连同校验码一起计算,若值是0则有差错,否则校验通过。 通常说奇偶校验可以检测出1位差错,实际上它可以检测出任何奇数位差错。 校验和的思想也很简单,将传输的消息当成8位(或16/32位)整数的序列,将这些整数加起来而得出校验码,该校验码也叫校验和。校验和被用在IP协议中,按照16位整数运算,而且其MSB(Most Significant Bit)的进位被加到结果中。 显然,奇偶校验和校验和都有明显的不足。奇偶校验不能检测出偶数位差错。对于校验和,如果整数序列中有两个整数出错,一个增加了一定的值,另一个减小了相同的值,这种差错就检测不出来。 2.CRC算法的基本原理------------------- CRC算法的是以GF(2)(2元素伽罗瓦域)多项式算术为数学基础的,听起来很恐怖,但实际上它 的主要特点和运算规则是很好理解的。 GF(2)多项式中只有一个变量x,其系数也只有0和1,如: 1*x^7 + 0*x^6 + 1*x^5 + 0*x^4 + 0*x^3 + 1*x^2 +1*x^1 + 1*x^0

CCITT CRC-16计算原理与实现

CCITT CRC-16计算原理与实现 CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除数据通信外,CRC在其它很多领域也是大有用武之地的。例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑。 差错控制理论是在代数理论基础上建立起来的。这里我们着眼于介绍CRC的算法与实现,对原理只能捎带说明一下。若需要进一步了解线性码、分组码、循环码、纠错编码等方面的原理,可以阅读有关资料。 利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的r位监督码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。这个规则,在差错控制理论中称为“生成多项式”。 1 代数学的一般性算法 在代数编码理论中,将一个码组表示为一个多项式,码组中各码元当作多项式的系数。例如 1100101 表示为 1·x6+1·x5+0·x4+0·x3+1·x2+0·x+1,即 x6+x5+x2+1。 设编码前的原始信息多项式为P(x),P(x)的最高幂次加1等于k;生成多项式为G(x),G(x)的最高幂次等于r;CRC多项式为R(x);编码后的带CRC的信息多项式为T(x)。 发送方编码方法:将P(x)乘以xr(即对应的二进制码序列左移r位),再除以 G(x),所得余式即为R(x)。用公式表示为 T(x)=xrP(x)+R(x) 接收方解码方法:将T(x)除以G(x),如果余数为0,则说明传输中无错误发生,否则说明传输有误。 举例来说,设信息码为1100,生成多项式为1011,即P(x)=x3+x2,G(x)=x3+x+1,计算CRC的过程为 xrP(x) x3(x3+x2) x6+x5 x -------

CRC16校验算法实现

CRC16校验算法实现(转) 循环冗余码校验英文名称为Cyclical Redundancy Check,简称CRC。它是利用除法及余数的原理来作错误侦测(Error Detecting)的。实际应用时,发送装置计算出CRC值并随数据一同发送给接收装置,接收装置对收到的数据重新计算CRC并与收到的CRC相比较,若两个CRC值不同,则说明数据通讯出现错误。 根据应用环境与习惯的不同,CRC又可分为以下几种标准: ①CRC-12码; ②CRC-16码; ③CRC-CCITT码; ④CRC-32码。 CRC-12码通常用来传送6-bit字符串。CRC-16及CRC-CCITT码则用是来传送8-bit字符,其中CRC-16为美国采用,而CRC-CCITT为欧洲国家所采用。CRC-32码大都被采用在一种称为Point-to-Point的同步传输中。 下面着重是CRC-16检验码的生成过程。 CRC-16码由两个字节构成,在开始时CRC寄存器的每一位都预置为1,然后把CRC寄存器与8-bit的数据进行异或,之后对CRC寄存器从高到低进行移位,在最高位(MSB)的位置补零,而最低位(LSB,移位后已经被移出CRC寄存器)如果为1,则把寄存器与预定义的多项式码进行异或,否则如果 LSB为零,则无需进行异或。重复上述的由高至低的移位8次,第一个8-bit数据处理完毕,用此时CRC寄存器的值与下一个8-bit数据异或并进行如前一个数据似的8次移位。所有的字符处理完成后CRC寄存器内的值即为最终的CRC值。 下面为CRC16的计算过程,其中生成多项式为:X16+X15+X2+1: 1.设置CRC寄存器,并给其赋值FFFF(hex)。 2.将数据的第一个8-bit字符与16位CRC寄存器的低8位进行异或,并把结果存入CRC 寄存器。 3.CRC寄存器向右移一位,MSB补零,移出并检查LSB。 4.如果LSB为0,重复第三步;若LSB为1,CRC寄存器与生成多项式码相异或。 5.重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。 6.重复第2至第5步直到所有数据全部处理完成。 7.最终CRC寄存器的内容即为CRC值。 校验码实现 编写CRC校验程序有两种办法:一种为计算法,一种为查表法。下面是查表法的C语言实现:校验码算法程序实现样例(C语言):

CRC校验实用程序库(一)

CRC校验实用程序库(一) 在数据存储和数据通讯领域,为了保证数据的正确,就不得不采用检错的手段。在诸多检错手段中,CRC是最著名的一种。CRC的全称是循环冗余校验,其特点是:检错能力极强,开销小,易于用编码器及检测电路实现。从其检错能力来看,它所不能发现的错误的几率仅为0.0047%以下。从性能上和开销上考虑,均远远优于奇偶校验及算术和校验等方式。因而,在数据存储和数据通讯领域,CRC无处不在:著名的通讯协议X.25的FCS(帧检错序列)采用的是CRC-CCITT,ARJ、LHA等压缩工具软件采用的是CRC32,磁盘驱动器的读写采用了CRC16,通用的图像存储格式GIF、TIFF等也都用CRC作为检错手段。 CRC的本质是模-2除法的余数,采用的除数不同,CRC的类型也就不一样。通常,CRC的除数用生成多项式来表示。最常用的CRC码的生成多项式如表1所示。 @@10A08800.GIF;表1.最常用的CRC码及生成多项式@@ 由于CRC在通讯和数据处理软件中经常采用,笔者在实际工作中对其算法进行了研究和比较,总结并编写了一个具有最高效率的CRC通用程序库。该程序采用查表法计算CRC,在速度上优于一般的直接模仿硬件的算法,可以应用于通讯和数据压缩程序。 通常的CRC算法在计算一个数据段的CRC值时,其CRC值是由求解每个数值的CRC值的和对CRC寄存器的值反复更新而得到的。这样,求解CRC的速度较慢。通过对CRC算法的研究,我们发现:一个8位数据

加到16位累加器中去,只有累加器的高8位或低8位与数据相作用,其结果仅有256种可能的组合值。因而,我们可以用查表法来代替反复的运算,这也同样适用于CRC32的计算。本文所提供的程序库中,函数crchware是一般的16位CRC的算法;mk-crctbl用以在内存中建立一个CRC数值表;crcupdate用以查表并更新CRC累加器的值;crcrevhware和crcrevupdate是反序算法的两个函数;BuildCRCTable、CalculateBlockCRC32和UpdateCharac terCRC32用于CRC32的计算。 /*CRC.C——CRC程序库*/ #defineCRCCCITT0x1021 #defineCCITT-REV0x8408 #defineCRC160x8005 #defineCRC16-REV0xA001 #defineCRC32-POLYNOMIAL0xEDB88320L /*以上为CRC除数的定义*/ #defineNIL0 #definecrcupdate(d,a,t)*(a)=(*(a)>8)^(d)]; #definecrcupdate16(d,a,t)*(a)=(*(a)>>8^(t)(*(a)^(d))&0x00ff]) /*以上两个宏可以代替函数crcupdate和crcrevupdate*/ #include #include

CRC8校验分析(修正版)

CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。(网上流行的这一篇文章,前后两种算法得出来的CRC校验码并不一样,经过多次比对,发现查表法算出来的是正确的.一般性算法却不对,最后总结出来的是每一字节的被除数要反过来读取,算完后余数[即CRC码]也要反过来读取才对,不知何故,如果你懂,请发博文告诉大家.) CRC校验可以简单地描述为:例如我们要发送一些数据(信息字段),为了避免一些干扰以及在接收端的对读取的数据进行判断是否接受的是真实的数据,这时我们就要加上校验数据(即CRC校验码),来判断接收的数据是否正确。在发送端,根据要传送的k位二进制码序列,以一定的规则(CRC校验有不同的规则。这个规则,在差错控制理论中称为“生成多项式”。)产生一个校验用的r位校验码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共 k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则(即与发送时生成CRC校验码相同的规则)进行检验,校验采用计算机的模二除法,即除数和被除数(即生成多项式)做异或运算,进行异或运算时除数和被除数最高位对齐,进行按位异或运算,若最终的数据能被除尽,则传输正确;否则,传输错误。 CRC8即最终生成的CRC校验码为1字节,其生成多项式,生成多项式为g(x)=x8+x5+x4+1,相当于g(x)=1·x8+0·x7+0·x6+1·x5+1·x4+0·x3+0·x2+0·x1+1·x0,即对应的二进制数为100110001。 CRC8校验算法: 1.CRC8校验的一般性算法: 例如:信息字段代码为: 0X01 0X02 ————对应m(x)=x8+x (00000001) (00000010) 反过来读取,即为10000000 01000000 生成多项式为:g(x)=x8+x5+x4+1 ————对应g(x)的二进制代码为:100110001 现在我们将要对2字节数据0x0102生成CRC8校验码,并最终将生成的1字节CRC校验码跟在0x0102的后面,即0x01 02 ##,(##即8为CRC码),最终生成的3字节数据就是经CRC8校验生成的数据。 先计算x8m(x)=x16+x9,对应的2进制数为:10000000 01000000 00000000 。可以看到这样运算所得到的结果其实就是将信息字段代码的数左移8位。因为最终要将生成的8位CRC8校验码附在信息字段的后面,所以要将信息字段的数左移8位。最后用x8m(x)得到的二进制数对生成多项式g(x)进行模二运算,最终的余数(其二进制数的位数一定比生成多项式g(x)的位数小)就是所要的CRC8校验码。

CRC校验的算法实现

CRC校验的算法实现 一、CRC简介 CRC基于多项式的编码技术。在多项式编码中,将信息位串看成阶次为从X^k-1到X^0的信息多项式M(x)的系数序列,在计算CRC码时,发送方和接收方必须采用同一个生成多项式G(x),G(x)的阶次应该低于M(x),且最高和最低阶的系数为1。 根据发送端要传送的k位二进制码序列,可以以一定的规则产生一个r位检验码(就是CRC码),附在信息后面,构成一个新的二进制码序列数共(k+r)位,为传送多项式T(x),最后将其发送出去。产生CRC码的方法是: 以16位CRC码产生规则为例:先将要发送的二进制序列数左移16位(即乘以2的16 次方后)后,再除以生成多项式(这里采用的是模2运算法则,即多项式除法中采用不带借位的减法运算,运算等同于异或运算。),最后所得到的余数就是CRC码。任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。例如:代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。 二、检验原理 因为接收端接收到的传送多项式T(x)一定能被生成多项式G(x)模2整除,所以可用来判断传输过程是否出现错码。接收端有两种处理方式:1、计算k位序列的CRC码,与接收到的CRC比较,一致则接收正确。2、计算整个k+r 位的CRC码,若为0,则接收正确。 三、算法实现 这里采用 CRC-CCITT 多项式G(X) = X16 + X12 + X5 + 1,多项式为0x11021,因为第一位固定位1可省略,故C语言编程时,参与计算的为0x1021。 当按位计算CRC时,例如计算二进制序列为1001 1010 1010 1111时,将二进制序列数左移16位,即为1001 1010 1010 1111 (0000 0000 0000 0000),实际上该二进制序列可拆 分为1000 0000 0000 0000 (0000 0000 0000 0000) + 000 0000 0000 0000 (0000 0000 0000 0000) + 00 0000 0000 0000 (0000 0000 0000 0000) + 1 0000 0000 0000 (0000 0000 0000 0000) + …… 共16个二进制分序列。 算法步骤为: (1)对第一个二进制分序列求余数,竖式除法即为0x10000 ^ 0x11021运算,后面的0位保留; (2)接着对第二个二进制分序列求余数,将第一步运算的余数*2 后再和第二个二进制分序列一起对0x11021 求余,这一步理解应该没什么问题。如果该分序列为0,无需计算。(3)对其余的二进制序列求余与上面两步相同。 (4)计算到最后一位时即为整个二进制序列的余数,即为CRC校验码。 四、源代码 unsigned char test[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xf f}; unsigned char len = 16; void main( void ) {

crc8校验查表法实现方法

/* CRC-8 for Dallas iButton products From Maxim/Dallas AP Note 27 "Understanding and Using Cyclic Redundancy Checks with Dallas Semiconductor iButton Products" The Ap note describes the CRC-8 algorithm used in the iButton products. Their implementation involves a 256 byte CRC table. This algorithm is implemented here. In addition two other algorithms are shown. One uses nibble arrays and the other uses boolean arithmetic. 18JAN03 - T. Scott Dattalo */ /* crc array from the Maxim ApNote */ unsigned char crc_array[256] = { 0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41, 0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc, 0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62, 0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, 0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff, 0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5, 0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07, 0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58, 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a, 0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6, 0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24, 0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b, 0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9, 0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f, 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,

CRC校验算法

CRC(Cyclic Redundancy Check)循环冗余校验是常用的数据校验方法,讲CRC 算法的文章很多,之所以还要写这篇,是想换一个方法介绍CRC算法,希望能让大家更容易理解CRC算法。 先说说什么是数据校验。数据在传输过程(比如通过网线在两台计算机间传文件)中,由于传输信道的原因,可能会有误码现象(比如说发送数字5但接收方收到的却是6),如何发现误码呢?方法是发送额外的数据让接收方校验是否正确,这就是数据校验。最容易想到的校验方法是和校验,就是将传送的数据(按字节方式)加起来计算出数据的总和,并将总和传给接收方,接收方收到数据后也计算总和,并与收到的总和比较看是否相同。如果传输中出现误码,那么总和一般不会相同,从而知道有误码产生,可以让发送方再发送一遍数据。 CRC校验也是添加额外数据做为校验码,这就是CRC校验码,那么CRC校验码是如何得到的呢? 非常简单,CRC校验码就是将数据除以某个固定的数(比如ANSI-CRC16中,这个数是0x18005),所得到的余数就是CRC校验码。 那这里就有一个问题,我们传送的是一串字节数据,而不是一个数据,怎么将一串数字变成一个数据呢?这也很简单,比如说2个字节B1,B2,那么对应的数就是(B1<<8)+B2;如果是3个字节B1,B2,B3,那么对应的数就是((B1<<16)+(B2<<8)+B3),比如数字是0x01,0x02,0x03,那么对应的数字就是0x10203;依次类推。如果字节数很多,那么对应的数就非常非常大,不过幸好CRC只需要得到余数,而不需要得到商。 从上面介绍的原理我们可以大致知道CRC校验的准确率,在CRC8中出现了误码但没发现的概率是1/256,CRC16的概率是1/65536,而CRC32的概率则是1/2^32,那已经是非常小了,所以一般在数据不多的情况下用CRC16校验就可以了,而在整个文件的校验中一般用CRC32校验。 这里还有个问题,如果被除数比除数小,那么余数就是被除数本身,比如说只要传一个字节,那么它的CRC就是它自己,为避免这种情况,在做除法之前先将它移位,使它大于除数,那么移多少位呢?这就与所选的固定除数有关了,左移位数比除数的位数少1,下面是常用标准中的除数: CRC8:多项式是X8+X5+X4+1,对应的数字是0x131,左移8位 CRC12:多项式是X12+X11+X3+X2+1,对应的数字是0x180D,左移12位 CCITT CRC16:多项式是X16+X12+X5+1,对应的数字是0x11021,左移16位 ANSI CRC16:多项式是X16+X15+X2+1,对应的数字是0x18005,左移16位 CRC32:多项式是 X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1,对应数字是 0x104C11DB7,左移32 因此,在得到字节串对应的数字后,再将数字左移M位(比如ANSI-CRC16是左移16位),就得到了被除数。 好了,现在被除数和除数都有了,那么就要开始做除法求CRC 校验码了。CRC除法的计算过程与我们笔算除法类似,首先是被除数与除数高位对齐后,被除数减去除数,得到了差,除数再与差的最高位对齐,进行减法,然

CRC校验算法-程序例子

变量定义 rtrig1:R_TRIG; execute: BOOL; command:ARRAY[0..255] OF BYTE; number: BYTE; command_temp: ARRAY [0..255] OF WORD; CRCHi: WORD; CRCLo: WORD; CRC_temp: WORD:=16#FFFF; i:INT; j:INT; k:INT; result: ARRAY [0..255] OF BYTE; CRC: WORD; 程序(绿色字体为CRC校验代码)rtrig1(CLK:=execute); IF rtrig1.Q THEN CASE command[1] OF 01,02,03,04,05,06: number:=6; 15,16: number:=7+command[6]; END_CASE; FOR i:=0 TO number BY 1 DO command_temp[i]:=BYTE_TO_WORD(command[i]); END_FOR; FOR j:=0 TO number BY 1 DO CRCHi:=CRC_temp AND 16#FF00; CRCLo:=CRC_temp AND 16#00FF; CRC_temp:=CRCHi OR (CRCLo XOR command_temp[j]); FOR k:= 0 TO 7 BY 1 DO IF CRC_temp.0 = 1 THEN CRC_temp:=SHR(CRC_temp,1); CRC_temp:=CRC_temp XOR 16#A001; ELSE CRC_temp:=SHR(CRC_temp,1); END_IF; END_FOR; END_FOR; CRC:=(CRCLo*16#0100) OR (CRCHi/16#0100); ELSE

CRC16校验方法

CRC校验算法 CRC校验算法 CRC(Cyclic Redundancy Check)循环冗余校验是常用的数据校验方法,讲CRC算法的文章很多,之所以还要写这篇,是想换一个方法介绍CRC算法,希望能让大家更容易理解CRC算法。 先说说什么是数据校验。数据在传输过程(比如通过网线在两台计算机间传文件)中,由于传输信道的原因,可能会有误码现象(比如说发送数字5但接收方收到的却是6),如何发现误码呢?方法是发送额外的数据让接收方校验是否正确,这就是数据校验。最容易想到的校验方法是和校验,就是将传送的数据(按字节方式)加起来计算出数据的总和,并将总和传给接收方,接收方收到数据后也计算总和,并与收到的总和比较看是否相同。如果传输中出现误码,那么总和一般不会相同,从而知道有误码产生,可以让发送方再发送一遍数据。 CRC校验也是添加额外数据做为校验码,这就是CRC校验码,那么CRC校验码是如何得到的呢?非常简单,CRC校验码就是将数据除以某个固定的数(比如ANSI-CRC16中,这个数是0x18005),所得到的余数就是CRC校验码。 那这里就有一个问题,我们传送的是一串字节数据,而不是一个数据,怎么将一串数字变成一个数据呢?这也很简单,比如说2个字节B1,B2,那么对应的数就是(B1<<8)+B2;如果是3个字节B1,B2,B3,那么对应的数就是((B1<<16)+(B2<<8)+B3),比如数字是0x01,0x02,0x03,那么对应的数字就是0x10203;依次类推。如果字节数很多,那么对应的数就非常非常大,不过幸好CRC只需要得到余数,而不需要得到商。 从上面介绍的原理我们可以大致知道CRC校验的准确率,在CRC8中出现了误码但没发现的概率是1/256,CRC16的概率是1/65536,而CRC32的概率则是1/2^32,那已经是非常小了,所以一般在数据不多的情况下用CRC16校验就可以了,而在整个文件的校验中一般用CRC32校验。 这里还有个问题,如果被除数比除数小,那么余数就是被除数本身,比如说只要传一个字节,那么它的CRC就是它自己,为避免这种情况,在做除法之前先将它移位,使它大于除数,那么移多少位呢?这就与所选的固定除数有关了,左移位数比除数的位数少1,下面是常用标准中的除数:CRC8:多项式是X8+X5+X4+1,对应的数字是0x131,左移8位 CRC12:多项式是X12+X11+X3+X2+1,对应的数字是0x180D,左移12位 CCITT CRC16:多项式是X16+X12+X5+1,对应的数字是0x11021,左移16位 ANSI CRC16:多项式是X16+X15+X2+1,对应的数字是0x18005,左移16位 CRC32:多项式是X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1,对应数字是0x104C11DB7,左移32位。

CRC校验算法

1.生成多项式。 16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(既乘以 )后,再除以一个多项式,最后所得到的余数既是CRC码。任意一个由二进制位串组成的代码都可以和一个系数仅为…0?和…1?取值的多项式一一对应。例如:代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。 标准CRC生成多项式如下表: 名称生成多项式简记式* 标准引用 CRC-4 x4+x+1 3 ITU G.704 CRC-8 x8+x5+x4+1 0x31 CRC-8 x8+x2+x1+1 0x07 CRC-8 x8+x6+x4+x3+x2+x1 0x5E CRC-12 x12+x11+x3+x+1 80F CRC-16 x16+x15+x2+1 8005 IBM SDLC CRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS CRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS CRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP //叶子:这里不知道问什么省略了,有些迷惑哦。要是生成多项式要是都省了,那还怎么校验?我猜想可能是中间的全为一吧。 生成多项式的最高位固定的1,故在简记式中忽略最高位1了,如0x1021实际是0x11021。 I、基本算法(人工笔算): 以CRC16-CCITT为例进行说明,CRC校验码为16位,生成多项式17位。假如数据流为4字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0]; 数据流左移16位,相当于扩大256×256倍,再除以生成多项式0x11021,做不借位的除法运算(相当于按位异或),所得的余数就是CRC校验码。 发送时的数据流为6字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0]、CRC[1]、CRC[0];II、计算机算法1(比特型算法): 1)将扩大后的数据流(6字节)高16位(BYTE[3]、BYTE[2])放入一个长度为16的寄存器; 2)如果寄存器的首位为1,将寄存器左移1位(寄存器的最低位从下一个字节获得),再与生成多项式的简记式异或; 否则仅将寄存器左移1位(寄存器的最低位从下一个字节获得); 3)重复第2步,直到数据流(6字节)全部移入寄存器; 4)寄存器中的值则为CRC校验码CRC[1]、CRC[0]。 III、计算机算法2(字节型算法):256^n表示256的n次方 把按字节排列的数据流表示成数学多项式,设数据流为BYTE[n]BYTE[n-1]BYTE[n-2]、、、BYTE[1]BYTE[0],表示成数学表达式为BYTE[n]×256^n+BYTE[n-1]×256^(n-1) +...+BYTE[1]*256+BYTE[0],在这里+表示为异或运算。设生成多项式为G17(17bit),

相关主题
相关文档
最新文档