计算法简单实现crc校验
CRC校验算法详解及代码实现

CRC校验算法详解及代码实现CRC校验算法的原理是利用生成多项式来计算数据的校验值。
在发送端,将数据和生成多项式进行计算得到一个校验值,然后将这个校验值附加到发送的数据后面一起传输。
在接收端,接收到数据后再次进行计算,并与接收到的校验值进行比较,如果相同则说明数据传输过程中没有错误,否则说明数据传输过程中出现错误。
下面是CRC校验算法的具体步骤:1.选择一个生成多项式,通常用一个二进制数表示。
生成多项式的位数称为CRC位数,常见的有CRC-8,CRC-16,CRC-32等。
2.将生成多项式的最高位与数据的最高位对齐,然后进行异或运算。
异或运算的结果作为下一次异或运算的输入,直到将所有数据都计算完毕。
3.将计算得到的结果作为校验值附加到数据后面一起传输。
下面是一个简单的CRC校验算法的代码实现:```pythondef crc(data, generator):crc_value = 0generator_length = len(generator)for bit in data:crc_value ^= bitif crc_value & 0x1:crc_value = (crc_value >> 1) ^ int(generator, 2)else:crc_value = crc_value >> 1return crc_value#测试数据data = [1, 0, 1, 1]generator = "1011"#进行CRC校验residue = crc(data, generator)print(residue)```在上面的代码中,`data`表示要进行校验的数据,以列表的形式表示,每个元素是一个二进制位。
`generator`表示生成多项式,以字符串的形式表示,每个字符是一个二进制位。
程序输出的结果为校验值。
总结:本文详细介绍了CRC校验算法的原理和步骤,并给出了一个简单的代码实现。
CRC原理及计算示例

CRC原理及计算⽰例
推荐博⽂:
1、CRC原理:
2、CRC校验码的计算⽰例:
除数是随机数或按标准选定,CRC的关键是如何求出余数(CRC校验码)。
假设选择的CRC⽣成多项式为G(x)=x^4+x^3+1 要求计算出⼆进制的序列10110011的CRC校验码。
(1)、
将多项式转为⼆进制数,由G(x)=x^4+x^3+1得知,⼀共5位(总位数=最⾼位的幂次+1,即4+1=5)根据多项式的含义(多项式只列出⼆进制值为1的位,也就是这个⼆进制的第4位、第3位、第0位的⼆进制均为1,其它位均为0,所有⼆进制的⽐特串(除数)为11001
(2)、
A.原数帧:10110011
B.除数:11001 (5位数)
C.新数帧:在原数据帧后⾯补上(除数总位数-1个)0 ----> 10110011 0000
D.CRC校验码:C/B的余数,余数的位数只能⽐B少⼀位不够在左边补0,------> 10110011 0000/11001 = 100(这⾥只有三位,所以需要在100左边补0为 0100)
E.新发送帧:在A后⾯加上D(10110011 0100), 接收端收到E,使⽤E/B看是否有余数,如果没有余数则表明该帧在传输过程中没有出错,否则出了差错 -----> 10110011 0100/11001 =10101000余数为0。
C语言实现CRC校验(多种方法)

}
上面的程序根据运算分析而来,很容易理解。为了节约内存空间,我们对程序作进一步的简化。分析可知,当二进制序列中上一位计算的余数第15bit位为1时,即( 上一位计算的余数 & 0x8000) != 0,计算本位时,上一位余数 * 2后可对0x11021作求余运算,然后再加上本位计算所得余数。这个很好理解,也就是说,打个比方,把它看作简单的除法,计算上一位时的余数乘以2后,如果比较大可以当被除数,就再去除除数求余。有一点和普通除法不同的是,因为多项式除法中采用不带借位的减法运算,所以0x10000也可以被0x11021除,余数并非为0x10000,而是0x1021。这个自己动手算一下就知道了。余数之和也是不带进位的加法运算,即异或。最后还强调一点,因为二进制序列是左移16位后参与运算的,所以,一直算到序列的最后一位也是可以被除的,这点大家要明白。下面给出简化后的C语言实现。
2、按位计算CRC
采用CRC-CCITT多项式,多项式为0x11021,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) + ……
CRC校验码的原理

CRC校验码的原理CRC(Cyclic Redundancy Check)是一种常用的校验码,用于检测数据传输中的错误。
CRC校验码的原理是通过对数据进行计算,生成一个校验码,并将其附加到原始数据中一起传输。
接收方在收到数据后,通过重新计算校验码,并将其与接收到的校验码进行比较,以判断数据是否发生了错误。
1.选择一个固定长度的除数,通常称为生成多项式。
2.将生成多项式左移一个比特位,然后与数据的首个比特位进行“异或”操作。
结果称为“临时商”。
3.将数据向左移动一个比特位,并将上一步计算得到的临时商与下一个比特位进行“异或”操作,生成新的临时商。
4.重复上述过程,直到处理完数据的所有比特位。
5.将计算得到的临时商添加到原始数据的末尾作为校验码。
接收方收到数据后也按照相同的生成多项式重新进行CRC计算,然后将计算得到的临时商与接收到的校验码进行比较。
如果两者相等,说明数据没有发生错误;如果不相等,说明数据发生了错误。
在这种情况下,接收方可以要求发送方重新发送数据。
1.高效性:CRC校验码通常能够检测出大多数单比特和多比特的错误,很少漏掉错误。
2.易于实现:CRC校验码的计算过程可以通过硬件电路或软件算法来实现,非常简单直观。
3.不可逆性:CRC校验码不能完全确定数据中的错误位置和错误数量,而仅能检测错误。
4.灵活性:可以根据需要选择不同的生成多项式,以适应不同的数据传输环境。
需要注意的是,CRC校验码并不能检测所有的错误,特别是在数据传输距离较长、传输介质质量较差或噪声较多的情况下,仍然可能发生传输错误。
因此,在实际应用中,需要根据具体情况选择合适的校验码和纠错方法来保证数据传输的可靠性。
crc16校验码的计算方法

crc16校验码的计算方法CRC16校验码是一种常用的校验码算法,主要用于数据传输的错误检测。
它通过对待校验的数据进行计算,生成一个16位的校验码,然后将校验码附加在数据后面进行传输。
接收方在接收到数据后,同样使用CRC16算法对数据进行计算,并将计算得到的校验码与接收到的校验码进行比较,如果两者一致,说明数据传输没有错误。
CRC16校验码的计算方法可以分为以下几个步骤:1. 初始化CRC寄存器:将CRC寄存器的值初始化为一个固定的值,通常为0xFFFF。
2. 逐位计算:从数据的最高位开始,依次对每一位进行计算。
首先,将CRC寄存器的最高位与当前数据位进行异或操作,然后将CRC 寄存器的值左移一位。
3. 检查最高位:如果左移后CRC寄存器的最高位为1,则将CRC 寄存器的值与一个预设的固定值(通常为0x8005)进行异或操作。
4. 继续计算:重复步骤2和步骤3,直到对数据的每一位都进行了计算。
5. 结果取反:将CRC寄存器的值取反,得到最终的CRC16校验码。
下面以一个简单的例子来说明CRC16校验码的计算过程。
假设我们要计算数据0x0123的CRC16校验码。
1. 初始化CRC寄存器为0xFFFF。
2. 逐位计算:首先将CRC寄存器的最高位(0xFFFF的最高位为1)与数据的最高位(0x0的最高位为0)进行异或操作,得到1。
然后将CRC寄存器左移一位,得到0xFFFE。
3. 检查最高位:左移后CRC寄存器的最高位为1,将CRC寄存器的值与0x8005进行异或操作,得到0x7FFB。
4. 继续计算:重复步骤2和步骤3,对数据的每一位都进行计算。
最终得到CRC寄存器的值为0x7FFB。
5. 结果取反:将CRC寄存器的值取反,得到最终的CRC16校验码为0x8004。
通过以上计算,我们得到了数据0x0123的CRC16校验码为0x8004。
在实际应用中,发送方将数据和校验码一起发送给接收方,接收方在接收到数据后进行校验,如果计算得到的校验码与接收到的校验码一致,说明数据传输没有错误;如果不一致,则说明数据传输存在错误。
CRC_校验码的计算方法

CRC 校验码的计算方法CRC从原理到实现===============作者:Spark Huang(hcpp@)日期: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元素伽罗瓦域)多项式算术为数学基础的,听起来很恐怖,但实际上它的主要特点和运算规则是很好理解的。
C语言实现CRC校验

C语言实现CRC校验1.按位计算法:按位计算是一种基本的CRC校验方法。
实现步骤如下:1)定义一个用于存储CRC校验结果的变量(通常是一个无符号整数)并初始化为零。
2)将待校验的数据按位划分。
3)逐位处理每个划分的数据,以异或运算(^)与之前计算得到的CRC结果进行计算,直到处理完所有数据。
4)最终得到的CRC校验结果即为校验码。
示例代码如下:```c#include <stdio.h>unsigned int calculateCRC(unsigned char *data, int size)unsigned int crc = 0;for (int i = 0; i < size; i++)crc ^= data[i] << 8;for (int bit = 0; bit < 8; bit++)if ((crc & 0x8000) != 0)crc = (crc << 1) ^ 0x1021;} elsecrc <<= 1;}}}return crc;int maiunsigned char data[] = {0x01, 0x02, 0x03, 0x04, 0x05};int size = sizeof(data) / sizeof(data[0]);unsigned int crc = calculateCRC(data, size);printf("CRC: 0x%04X\n", crc);return 0;```上述代码中,`calculateCRC`函数用于计算CRC校验结果,接受一个指向待校验数据的指针和数据长度作为参数。
`main`函数通过调用`calculateCRC`函数计算CRC校验结果,并使用`printf`函数打印结果。
2.查表法:查表法是另一种常用的CRC校验算法,通过建立一个查找表来提高计算效率。
CRC校验的概念及具体实现

CRC校验的概念及具体实现概念CRC(Cyclic redundancy check),循环冗余校验CRC校验是⽤于检测⼀帧数据发送是否正确,只有确认对错的作⽤,并没有纠错的能⼒。
还有⼀点就是CRC校验通过了,并不代表这个数据肯定就是正确的,只能说尽可能减少出错的概率,当然CRC错了那么这个数据肯定是不正确的。
⽽这个概率是跟CRC的位数相关,也跟选择的多项式有关,⼤致可以理解为CRC8,就是1/(28),CRC16则是1/(216)以此类推。
对于检验⼀帧数据是否正确有很多算法,CRC只是其中的⼀种,SUM的形式也可以的,只是算法不同对于校验结果的效果也是不⼀样的,最好的效果是,每⼀位的变化都可以引起最终checksum的值发⽣较⼤的改变。
引⼊除法计算是⼀种很好的⽅法,每⼀位发⽣改变对于最后的余数都会引起较⼤的变化。
多项式(Polynomical)多项式即CRC除法的除数,⽽且多项式是总于⾼于CRCN中N的⼀位,这样可以保证余数的位数与N相同。
同时多项式也有好坏之分,区别就是在于出错的概率,⾄于哪种多项式好⼀些,这个⼀般来说是数学家的事情,我们⼯程上拿过来⽤就好,⽽且⼀般的协议中也已经规定了这个CRC的多项式。
其实多项式只是⼀种表现⽅式,当然也可以直接⽤16进制表⽰以CRC-CCITT为例x16+x12+x5+1也可以表⽰为0x1021计算例⼦引⽤别⼈⽂档中的例⼦来说明CRC机制,如下是⼀个CRC4计算的例⼦1100001010 = Quotient (nobody cares about the quotient)_______________10011 ) 11010110110000 = Augmented message (1101011011 + 0000)=Poly 10011,,.,,....-----,,.,,....10011,.,,....10011,.,,....-----,.,,....00001.,,....00000.,,....-----.,,....00010,,....00000,,....-----,,....00101,....00000,....-----,....01011....00000....-----....10110...10011...-----...01010..00000..-----..10100.10011.-----.0111000000-----1110 = Remainder = THE CHECKSUM先将要计算的后⽅填充相应位数的0(CRC4,4位),再对POLY进⾏求余操作,这个余数就是我们要的checksum这个操作就是⼀个除法操作,只是在减的时候⽤XOR来代替减法,这样就不要考虑进位借位的问题,⽽且XOR来代替减法也不会使CRC的效果变差,因为每⼀位的改变还是会引起checksum较⼤的变化。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算法简单实现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
xorwfCRC16_High,w movwf&nb
sp;CRCByte callCRC_Byte incfFSR decfv_Count;需计算的字节数movfCRC_High,w xorwfCRC16_Low,w movwfCRC16_High movfCRC_Low,w movwfCRC16_Low movfv_Count,w;计算结束? btfssSTATUS,Z gotoCRC_Data10 return ; ------------------------------------------------------------- ;CRCdat eend ; ------------------------------------------------------------- 说明:CRC的计算原理如下(一个字节的简单例子) 110110000000000000000000 -一个字节数据,左移16b d01000000100001 -CRC-CCITT多项式,17b -------------------------- 10100000001000010 -中间余数 d01000000100001 ------------------------- 10100000110001100 d
01000000100001 ----------------------- 10100011010110100 d01000000100001 --------------------- 10101101001010100 d0ppppppppppppppppp -------------------------- ... aaaaaaaaaaaaaaaa -结果A(A1,A0) 由此与一字节的情况比较,将两个字节分开计算如下:先算高字节: dddddddd000000000000000000000000 -D1,0,0,0 pppppppppppppppp -P ----------------------------------- ... aaaaaaaaaaaaaaaa -高字节部分余数PHA三个8位的列中只低两个字节的最后结果是余数,而数据所在的高&nbs
p;8位列最后都被消去了,因其中的运算均为异或,不产生进位或借位,故每一位数据只影响本列的结果,即d并不直接影响结果。
再将前例变化一下重列如下:11011000 -------------------------- 10001000000100001//P d01000000100001//P 0000000000000//0 d01000000100001//P 0000000000000//0 d01000000100001//P 0000000000000//0 d01000000100001//P ------------------- 0100101001110101 现在的问题就是如何根据d来对P移位异或了,从上面的例子看,也可以理解为每步移位,但
根据d决定中间余数是否与P异或。
从前面原来的例子可以看出,决定的条件是中间余数的最高位为0,因为P的最高位一定为1,即当中间余数与d相应位异或的最高位为1时,中间余数移位就要和P异或,否则只需移位即可。
其方法如下例(上例的变形,注意其中空格的移动表现了d的影响如何被排除在结果之外): d--------a-------- 10000000000000000 -HSB=1 0000000000000000 -a =1 0001000000100001 -不含最高位的 1 ----------------- 10001000000100001 0010000001000010 0001000000100001 ----------------- 00011000001100011 -HSB=0 0110000011000110 ----------------- 10110000011000110 -HSB=1 1100000110001100 0001000000100001 ----------------- 11101000110101101 -HSB=0 1010001101011010 ----------------- 01010001101011010 -HSB=1 &nb
sp;0100011010110100 0001000000100001 ----------------- 00101011010010101 -HSB=0 1010110100101010 ----------------- 01010110100101010 -HSB=1 0101101001010100 0001000000100001 ----------------- 0100101001110101 -CRC 结合这些,前面的程序就好理解了。