A. 什么是CRC码
CRC是什么东西呢?其实渗毕乱我们大家都不丛档应该会对它陌生,回忆一下?你用过RAR和ZIP等压缩软件吗?它数颤们是不是常常会给你一个恼人的“CRC校验错误”信息呢?我想你应该明白了吧,CRC就是块数据的计算值,它的全称是“Cyclic Rendancy Check”,中文名是“循环冗余码”,“CRC校验”就是“循环冗余校验
B. CRC原理简介
最近刚好有时间,整理了一下关于CRC的资料,详细对比了下程序的实现过程和原理,当然,高手都是不在意的。
本文主要介绍CRC的一些基础知识,个人收获是后面关于网上标准Demo程序的一些详细解析。见下一篇https://www.jianshu.com/p/c0d93c2e89ce
声明:本文定义部分参考网上多处资料,只是为了方便做个笔记,引用网文做一些更改,如有雷同键并尘,请私信说明并修改。
一、关于CRC的介绍
CRC即循环冗余校验码(Cyclic Rendancy Check):数据通信领域中最常用的一种差错校验码,其信息字段和校验字段长度可以任意指定,但要求通信双方定义的CRC标准一致。
二、工作原理
对于工控领域,我们主要利用CRC校验来处理各种数据流的数据正确性校验。
CRC原理 :在K位信息码(目标发送数据)后再拼接R位校验码,使整个编码长度为N位,因此这种编码也叫(N,K)码。通俗的说,就是在需要发送的信息后面附加一个数(即校验码),生成一个新的发送数据发送给接收端。这个数据要求能够使生成的新数据被一个特定的数整除。这里的整除需要引入模 2除法的概念,附上网络关于模2计算的链接:
https://ke..com/item/模2运算/18556715?fr=aladdin
那么,CRC校验的具体做法就是
(1)选定一个标准除数(K位二进制数据串)
(2)在要发送的数据(m位)后面加上K-1位0,然后将这个新数(M+K-1位)以模2除法的方式除以上面这个标准除数,所得到的余数也就是该数据的CRC校验码(注:余数必须比除数少且只少一位,不够就补0)
(3)将这个校验码附在原蔽埋m位数据后面,构成新的M+K-1位数据,发送给接收端。
(4)接收端将接收到的数据除以标准除数,如果余数为0则认为数据正确。
注意: CRC校验中有两个关键点:一是要预稿禅先确定一个发送端和接收端都用来作为除数的二进制比特串(或多项式);二是把原始帧与上面选定的除进行二进制除法运算,计算出FCS。前者可以随机选择,也可按国际上通行的标准选择,但最高位和最低位必须均为“1”
实例:对于数据10110011(16#B3),以指定除数110011求它的CRC校验码,其过程如下:
关于校验码的计算(重点来了)
单纯谈CRC的模2除法其实并不困难,但实际计算中经常会遇到计算出来的结果和实际不一致的情况,这也是这几天我在看的东西。
这里需要知道几个组成部分或者说计算概念:多项式公式、多项式简记式、数据宽度、初始值、结果异或值、输入值反转、输出值反转、参数模型。
1、多项式公式
对于CRC标准除数,一般使用多项式(或二项式)公式表示,如上例中除数11011的二项式为G(X)=X4+X3+X+1,X的指数就代表了该bit位上的数据为1,(最低位为0)。这里特别注意一下位数问题,除数的位数为二项式最高次幂+1(4+1=5),这个很重要。
2、多项式简记式
通过对CRC的基本了解我们知道,多项式的首尾必定为1,而这个1的位置在下一步计算一定为0,所以就把前面这个1给省略掉了,出现了一个叫简记式的东西,如上例中除数11011的简记式为1011,很多看过CRC高级语言源码的人会知道,对于CRC_16标准下G(X)=X16+X15+X2+1(16#18005)的poly值实际上是8005,这里使用的就是简记式。后面会对这个用法做一个说明。
3、数据宽度
数据宽度指的就是CRC校验码的长度(二进制位数),知道了CRC的运算概念和多项式,就可以理解这个概念了,CRC长度始终要比除数位数少1,与简记式长度是一致的。
以上三个数据就是我们经常能够用到的基本数据
4、初始值与结果异或值
在一些标准中,规定了初始值,则数据在进行上述二项式运算之前,需要先将要计算的数据与初始值的最低字节进行异或,然后再与多项式进行计算。
而在结果异或值不为零的情况下,则需要将计算得到的CRC结果值再与结果异或值进行一次异或计算,得到的最终值才是我们需要的CRC校验码。
这里可以看出,初始值与结果值的位数要求与数据宽度一致。
5、输入值反转与输出值反转
输入值反转的意思是在计算之前先将二项式反转,然后再用得到的新值和数据进行计算。如对于G(X)=X16+X15+X2+1(16#18005),其正向值为1 1000 0000 0000 0101,反转值则为1010 0000 0000 0001 1
输出值反转则是将最终得到的CRC结果反转。
通常,输入值反转后的结果值也会是反转的,所以这两个选项一般是同向的,我们只有在在线CRC计算器中会看到自由选择正反转的情况存在。
那么,这里引用CSDN博主 bobde163 的一段总结:
CRC16、CRC32等多字节的校验值的计算有几点需要清楚(只针对一次一个字节的算法):
1) 初始值不为0的情况下,该如何计算:
输入数据需要反转:先将要计算的数据与初始值的最低字节进行异或,再与反转后的多项式进行计算。
输入数据不需要反转:先将要计算的数据左移到与初始值对齐的位置(如CRC16算法,则左移8位,低位填充0;如CRC32算法,则左移24位,低位填充0)与初始值进行异或,再与正常的多项式进行计算。
2) 结果异或值不为0的情况:第一步算得到的CRC值再与结果异或值进行异或操作得到最终的校验值:
输出数据反转:如果输入数据是反转的模式,则结果也是反转的
输出数据不反转:如果输入数据是不反转的模式,则结果也是不反转的
3)初始值的选择是可自己定义,很多不同的厂家使用的初始值是不一样,不一样的初始值得到的结果也是不一样的。
---------------------
原文:https://blog.csdn.net/bobde163/article/details/78760213
不同的二项式、初始值、结果异或值、反转原则都会造成最终的结果不一致,这就是为什么明明是正确的计算方式,有时候算出来的结果却总是不正确。
那么,如何去判断应该采用哪些原则呢?这里谈到最后一个概念:
6、参数模型
虽然CRC可以任意定义二项式、数据长度等,但没有一个统一的标准的话,就会让整个计算变得非常的麻烦。但实际上,不同的厂家经常采用不同的标准算法,这里列出了一些国际常用的模型表:
以上为关于CRC的笔记,下一篇讲一讲高级语言实现思路
C. crc是什么意思
CRC意思是循环冗余码校验。
校验原理:(M-R)/G=Q+0/G
说明:以接收到的校验码除以约定的除数,若余数为0,则可认为接收到的数据是正确的。
例:有效信息1101,生成多项式样1011
循环校验码解:
有效信息1101(k=4),即M(x)=x3+x2+x0,生成多项式1011(r+1=4,即r=3);
即G(x)=x3+x1+x0,M(x)·x3=x6+x5+x3,即1101000(对1101左移三位);
M(x)·x3/G(x)=1101000/1011=1111+001/1011即1010的CRC是:1101001。
CRC码集选择的原则:
若设码字长度为N,信息字段为K位,校验字段为R位(N=K+R),则对于CRC码集中的任一码字,存在且仅存在一个R次多项式g(x),使得
V(x)=A(x)g(x)=xRm(x)+r(x);
其中:m(x)为K次信息多项式,r(x)为R-1次校验多项式,
g(x)称为生成多项式:
g(x)=g0+g1x+g2x2+。。。+g(R-1)x(R-1)+gRxR
发送方通过指定的g(x)产生CRC码字,接收方则通过该g(x)来验证收到的CRC码字。
D. crc是什么意思
CRC(Cyclic Rendancy Check),即循环冗余校核,是一种根据网络数据包或电脑文件等数据产生简短固定位数校核码的快速算法,主要用来检测或校核数据传输或者保存后可能出现的错误。CRC利用除法及余数的原理,实现错误侦测的功能,具有原理清晰、实现简单等优点。
CRC也就是循环冗余校验码,是计算机网络通信领域常用的校验码。循环冗余校验码包括一系列移位、相除等数据编码规则,其算法原理、算法程序的设计与分析,都可以通过相应的软件编码进行解决。
循环冗余校验码是利用软件进行校验的算法,因此其检验速度很快,校验的误码率也较低,整个计算机网络通信的信息传输速度很高。CRC差错纠正控制法能够有效减少通信线路的误码率,得到的通信数据传旦友输信息更准确。
在数据的传输过程中由于空间电磁环境复杂等原因,可能会产生误码,即某几位数据0变为1,或1变为0,导致接收端得到错误的数据。为了降低误码率,通常对数据进行特定编码,在收发端进行额外的验证,使接收端能发现某些错误;
进而实现纠错功能,常用的编码方法有CRC-32校验码、CRC-16校验码、汉明码、奇偶校验法等。其中32位循环冗余校验简称CRC-32校验在性能和资源消耗两方面都有较大的优势,因而,在无线电通信、旁正SATA硬盘数据传输等系统中,CRC-32校验是运迟悔最常用的检错手段之一。
E. 简化版的crc校验,求翻译成易语言源码
.版本 2
.子程序 crc, 整数型
.参数 InData, 文本型
.参数 length, 整数型, 可空, 此参数可以不要,改为局部变量
.局部变量 num1, 整数型
.局部变量衫森 i, 整数型
.局部变量 bin, 字节集
.局部变量 j_length, 整数型
bin = 到顷塌山字节集 (InData)
j_length = 取字节集长度 (bin)
.计次循环首 (j_length, i)
num1 = num1 + bin [i]
.计次循雀中环尾 ()
返回 (num1 % 50 + 48)
F. CRC指的是什么
CRC:循环冗余校验(Cyclic Rendancy Check, CRC)。
CRC是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。
CRC简介:
在数据传输过程中,无论传输系统的设计再怎么完美,差错总会存在,这种差错可能会导致在链路上传输的一个或者多个帧被破坏顷银(出现比特差错,0变为1,或者1变为0),从而接受方接收到错误的数据。
为尽量提高接受方收到数据的正确率,在接收方接收数据之前需要对数据进行差错检测,当且仅当检测的结果为正确时接收方才真正收下数据。检测的方式有多种,常见的有奇偶校验、因特网校验和循环冗余校验等。
(6)crc的源码是什么扩展阅读:
CRC应用场合:
CRC校验实用程序库 在数据存储和数据通讯领域,为了保证数据的正确,就不得不采用检错的手段。在诸多检错手段中,CRC是最着名的一种。
CRC的全称是循环冗余校验,其特点是:检错能力强,开销小,易于用编码器及检测电路实现。从其检错能力来看,它所不能发现的错误的几率仅为0.0047%以下。从性能森乎卖上和开销上考虑,均远远优于奇偶校验及算术和校验等方式。
因而,在数据存储和数据通讯此逗领域,CRC无处不在:着名的通讯协议X.25的FCS(帧检错序列)采用的是CRC-CCITT,WinRAR、NERO、ARJ、LHA等压缩工具软件采用的是CRC32,磁盘驱动器的读写采用了CRC16,通用的图像存储格式GIF、TIFF等也都用CRC作为检错手段。下面介绍硬件生成与计算CRC的过程。
参考资料:网络---CRC
G. CRC码是什么
循环冗余校验码(CRC)
CRC校验采用多项式编码方法。被处理的数据块可以看作是一个n阶的二进制多项式,由
。如一个8位二进制数10110101可以表示为:
。多项式乘除法运算过程与普通代数多项式的乘除法相同。多项式的加减法运算以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校验码生成多项式g(x)=
。采用16位CRC校验,可以保证在
bit码元中只含有一位未被检测出的错误
。在IBM的同步数据链路控制规程SDLC的帧校验序列FCS中,使用CRC-16,其生成多项式g(x)=
;而在CCITT推荐的高级数据链路控制规程HDLC的帧校验序列FCS中,使用CCITT-16,其生成多项式g(x)=
。CRC-32的生成多项式g(x)=
。CRC-32出错的概率比CRC-16低
倍
。由于CRC-32的可靠性,把CRC-32用于重要数据传输十分合适,所以在通信、计算机等领域运用十分广泛。在一些UART通信控制芯片(如MC6582、Intel8273和Z80-SIO)内,都采用了CRC校验码进行差错控制;以太网卡芯片、MPEG解码芯片中,也采用CRC-32进行差错控制。
H. CRC码的编码和解码程序是什么
我有一个别人变得CRC程序,其中有好几种CRC的编码方法,也许会有用
using System;
namespace Communication.IO.Tools
{
/// <summary>
/// Tool to calculate and add CRC codes to a string
///
/// ***************************************************************************
/// Copyright (c) 2003 Thoraxcentrum, Erasmus MC, The Netherlands.
///
/// Written by Marcel de Wijs with help from a lot of others,
/则谨// especially Stefan Nelwan
///
/闭迟// This code is for free. I ported it from several different sources to C#.
///
/// For comments: [email protected]
/// ***************************************************************************
/// </summary>
public class CRCTool
{
// 'order' [1..32] is the CRC polynom order, counted without the leading '1' bit
// 'polynom' is the CRC polynom without leading '1' bit
//孙态基 'direct' [0,1] specifies the kind of algorithm: 1=direct, no augmented zero bits
// 'crcinit' is the initial CRC value belonging to that algorithm
// 'crcxor' is the final XOR value
// 'refin' [0,1] specifies if a data byte is reflected before processing (UART) or not
// 'refout' [0,1] specifies if the CRC will be reflected before XOR
// Data character string
// For CRC-CCITT : order = 16, direct=1, poly=0x1021, CRCinit = 0xFFFF, crcxor=0; refin =0, refout=0
// For CRC16: order = 16, direct=1, poly=0x8005, CRCinit = 0x0, crcxor=0x0; refin =1, refout=1
// For CRC32: order = 32, direct=1, poly=0x4c11db7, CRCinit = 0xFFFFFFFF, crcxor=0xFFFFFFFF; refin =1, refout=1
// Default : CRC-CCITT
private int order = 16;
private ulong polynom = 0x1021;
private int direct = 1;
private ulong crcinit = 0xFFFF;
private ulong crcxor = 0x0;
private int refin = 0;
private int refout = 0;
private ulong crcmask;
private ulong crchighbit;
private ulong crcinit_direct;
private ulong crcinit_nondirect;
private ulong [] crctab = new ulong[256];
// Enumeration used in the init function to specify which CRC algorithm to use
public enum CRCCode{CRC_CCITT, CRC16, CRC32};
public CRCTool()
{
//
// TODO: Add constructor logic here
//
}
public void Init(CRCCode CodingType)
{
switch( CodingType )
{
case CRCCode.CRC_CCITT:
order = 16; direct=1; polynom=0x1021; crcinit = 0xFFFF; crcxor=0; refin =0; refout=0;
break;
case CRCCode.CRC16:
order = 16; direct=1; polynom=0x8005; crcinit = 0x0; crcxor=0x0; refin =1; refout=1;
break;
case CRCCode.CRC32:
order = 32; direct=1; polynom=0x4c11db7; crcinit = 0xFFFFFFFF; crcxor=0xFFFFFFFF; refin =1; refout=1;
break;
}
// Initialize all variables for seeding and builing based upon the given coding type
// at first, compute constant bit masks for whole CRC and CRC high bit
crcmask = ((((ulong)1<<(order-1))-1)<<1)|1;
crchighbit = (ulong)1<<(order-1);
// generate lookup table
generate_crc_table();
ulong bit, crc;
int i;
if ( direct == 0 )
{
crcinit_nondirect = crcinit;
crc = crcinit;
for (i=0; i<order; i++)
{
bit = crc & crchighbit;
crc<<= 1;
if ( bit != 0 )
{
crc^= polynom;
}
}
crc&= crcmask;
crcinit_direct = crc;
}
else
{
crcinit_direct = crcinit;
crc = crcinit;
for (i=0; i<order; i++)
{
bit = crc & 1;
if (bit != 0)
{
crc^= polynom;
}
crc >>= 1;
if (bit != 0)
{
crc|= crchighbit;
}
}
crcinit_nondirect = crc;
}
}
/// <summary>
/// 4 ways to calculate the crc checksum. If you have to do a lot of encoding
/// you should use the table functions. Since they use precalculated values, which
/// saves some calculating.
/// </summary>.
public ulong crctablefast (byte[] p)
{
// fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip.
// only usable with polynom orders of 8, 16, 24 or 32.
ulong crc = crcinit_direct;
if ( refin != 0 )
{
crc = reflect(crc, order);
}
if ( refin == 0 )
{
for ( int i = 0; i < p.Length; i++ )
{
crc = (crc << 8) ^ crctab[ ((crc >> (order-8)) & 0xff) ^ p[i]];
}
}
else
{
for ( int i = 0; i < p.Length; i++ )
{
crc = (crc >> 8) ^ crctab[ (crc & 0xff) ^ p[i]];
}
}
if ( (refout^refin) != 0 )
{
crc = reflect(crc, order);
}
crc^= crcxor;
crc&= crcmask;
return(crc);
}
public ulong crctable (byte[] p)
{
// normal lookup table algorithm with augmented zero bytes.
// only usable with polynom orders of 8, 16, 24 or 32.
ulong crc = crcinit_nondirect;
if ( refin != 0 )
{
crc = reflect(crc, order);
}
if ( refin == 0 )
{
for ( int i = 0; i < p.Length; i++ )
{
crc = ((crc << 8) | p[i]) ^ crctab[ (crc >> (order-8)) & 0xff ];
}
}
else
{
for ( int i = 0; i < p.Length; i++ )
{
crc = (ulong)(( (int)(crc >> 8) | (p[i] << (order-8))) ^ (int)crctab[ crc & 0xff ]);
}
}
if ( refin == 0 )
{
for ( int i = 0; i < order/8; i++ )
{
crc = (crc << 8) ^ crctab[ (crc >> (order-8)) & 0xff];
}
}
else
{
for ( int i = 0; i < order/8; i++ )
{
crc = (crc >> 8) ^ crctab[crc & 0xff];
}
}
if ( (refout^refin) != 0 )
{
crc = reflect(crc, order);
}
crc^= crcxor;
crc&= crcmask;
return(crc);
}
public ulong crcbitbybit(byte[] p)
{
// bit by bit algorithm with augmented zero bytes.
// does not use lookup table, suited for polynom orders between 1...32.
int i;
ulong j, c, bit;
ulong crc = crcinit_nondirect;
for (i=0; i<p.Length; i++)
{
c = (ulong)p[i];
if ( refin != 0 )
{
c = reflect(c, 8);
}
for (j=0x80; j != 0; j>>=1)
{
bit = crc & crchighbit;
crc<<= 1;
if ( (c & j) != 0)
{
crc|= 1;
}
if ( bit != 0 )
{
crc^= polynom;
}
}
}
for ( i=0; (int)i < order; i++)
{
bit = crc & crchighbit;
crc<<= 1;
if ( bit != 0 ) crc^= polynom;
}
if ( refout != 0 )
{
crc=reflect(crc, order);
}
crc^= crcxor;
crc&= crcmask;
return(crc);
}
public ulong crcbitbybitfast(byte[] p)
{
// fast bit by bit algorithm without augmented zero bytes.
// does not use lookup table, suited for polynom orders between 1...32.
int i;
ulong j, c, bit;
ulong crc = crcinit_direct;
for (i = 0; i < p.Length; i++)
{
c = (ulong)p[i];
if ( refin != 0)
{
c = reflect(c, 8);
}
for ( j = 0x80; j > 0; j >>= 1 )
{
bit = crc & crchighbit;
crc <<= 1;
if ( (c & j) > 0 ) bit^= crchighbit;
if ( bit > 0 ) crc^= polynom;
}
}
if ( refout > 0)
{
crc=reflect( crc, order );
}
crc^= crcxor;
crc&= crcmask;
return(crc);
}
/// <summary>
/// CalcCRCITT is an algorithm found on the web for calculating the CRCITT checksum
/// It is included to demonstrate that although it looks different it is the same
/// routine as the crcbitbybit* functions. But it is optimized and preconfigured for CRCITT.
/// </summary>
public ushort CalcCRCITT(byte[] p)
{
uint uiCRCITTSum = 0xFFFF;
uint uiByteValue;
for (int iBufferIndex = 0; iBufferIndex < p.Length; iBufferIndex++)
{
uiByteValue = ( (uint) p[iBufferIndex] << 8);
for ( int iBitIndex = 0; iBitIndex < 8; iBitIndex++ )
{
if ( ( (uiCRCITTSum^uiByteValue) & 0x8000) != 0 )
{
uiCRCITTSum = (uiCRCITTSum <<1 ) ^ 0x1021;
}
else
{
uiCRCITTSum <<= 1;
}
uiByteValue <<=1;
}
}
return (ushort)uiCRCITTSum;
}
#region subroutines
private ulong reflect (ulong crc, int bitnum)
{
// reflects the lower 'bitnum' bits of 'crc'
ulong i, j=1, crcout = 0;
for ( i = (ulong)1 <<(bitnum-1); i != 0; i>>=1)
{
if ( ( crc & i ) != 0 )
{
crcout |= j;
}
j<<= 1;
}
return (crcout);
}
private void generate_crc_table()
{
// make CRC lookup table used by table algorithms
int i, j;
ulong bit, crc;
for (i=0; i<256; i++)
{
crc=(ulong)i;
if (refin != 0) // 'refin' [0,1] specifies if a data byte is reflected before processing (UART) or not
{
crc=reflect(crc, 8);
}
crc<<= order-8;
for (j=0; j<8; j++)
{
bit = crc & crchighbit;
crc<<= 1;
if ( bit !=0 ) crc^= polynom;
}
if (refin != 0)
{
crc = reflect(crc, order);
}
crc&= crcmask;
crctab[i]= crc;
}
}
#endregion
}
}
I. CRC校验是什么
CRC校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能。
可以对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。
CRC校验中有两个关键点,一是预先确定一个发送送端和接收端都用来作为除数的二进制比特码没串(或多项式),可以迟核纳随机选择,也可以使用国际标准。
但是最高位和最低位必须为1;二是把原始帧与上面计算出的除数进行模2除法运算,计氏纯算出CRC码。
J. 求一个CRC校验C++源代码。题目:发送数据为1101011011,生成的多项式为P(X)=X4+X+1(X4为X的4次方),
下面的代码输入为原数据和多项式对就饥薯的二进制码,输出为产生的校验码。
如原数据是1101011011,多项式是X^4+X+1(即10011)。产生的校验码为1110。
输入110101101110011
输出1110
#include<iostream>
#include<cstring>
#include<iomanip>
usingnamespacestd;
#defineWORDSIZE255
intgetNum(chara[],intn);
voidshowNum(intr,intn);
intmain(intargc,char*argv[])
{
cout<<"pleaseinputXandP:"<<endl;
intx,p,lenA,lenP;
chara[WORDSIZE];
memset(a,'