C语言实现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校验程序-c语言
uint acc=0,i,j=0;
while(len--)
{
acc=acc^(*s++<<8);
for(i=0;i++<8;)
从机程序:
#define_PPDATAR_H
#include <reg51.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
/*握手信号宏定义*/
#define CALL 0x24//主机呼叫
#define OK 0x00//从机准备好
{
uchar i = 0;
uchar tmp;
/*发送呼叫信号CALL并接收应答信息,如果没有接收到从机准备好的信号,则重新发送呼叫帧*/
while(tmp!=OK)
{
/*发送呼叫信号CALL */
TI = 0;
SBUF = CALL;
while(!TI);
TI = 0;
/*接收从机应答*/
RI = 0;
void si()
{
unsigned int M;
a=x%10;
M=x/10;
b=M%10;
M=M/10;
c=M%10;
d=M/10;//a取出第四位,b取出第三位,c取出第二位,d取出第一位
}
//***********************显示**********************//
void display()
#define MAXLEN 64//缓冲区最大长度
uchar buf[MAXLEN];
c语言crc校验函数
c语言crc校验函数C语言中的CRC校验函数通常用于计算数据的循环冗余校验码,以便验证数据的完整性和准确性。
CRC校验算法通常用于通信协议、存储系统和数据传输中。
下面我将从多个角度介绍C语言中CRC校验函数的相关内容。
首先,CRC校验函数的实现通常需要一个预先定义的CRC多项式和初始值。
常见的CRC多项式包括CRC-8、CRC-16、CRC-32等,每种CRC多项式都有对应的生成多项式。
在实际编程中,可以通过查表或直接计算的方式来实现CRC校验函数。
其次,CRC校验函数的实现通常包括初始化CRC寄存器、按位处理数据、最终异或处理等步骤。
在C语言中,可以使用位运算和循环结构来实现这些步骤。
需要注意的是,不同的CRC多项式和初始值会影响CRC校验函数的实现细节。
另外,C语言中有许多开源的CRC校验函数库,如zlib、libcrc等,这些库提供了通用的CRC校验函数实现,可以直接在项目中引用和调用。
使用这些库可以简化CRC校验函数的实现过程,提高开发效率。
此外,对于特定的应用场景,可能需要根据实际需求定制CRC 校验函数。
这包括选择合适的CRC多项式、优化计算性能、处理数据端对齐等方面。
定制CRC校验函数需要充分理解CRC算法的原理和实现细节,并进行充分的测试验证。
总之,C语言中的CRC校验函数是一个重要且常见的功能,实现CRC校验函数需要充分理解CRC算法的原理和实现细节,选择合适的CRC多项式和初始值,并根据实际需求进行定制化的实现。
通过合理的设计和实现,可以保证数据的完整性和准确性,提高系统的稳定性和可靠性。
CRC算法原理及C语言实现
CRC算法原理及C语言实现CRC(Cyclic Redundancy Check)循环冗余校验算法是一种常用的错误检测算法,广泛应用于数据通信、存储等领域。
它通过对发送的数据进行多项式计算,得到一个校验值,然后将这个校验值附加到数据末尾,接收方再进行校验,通过比较接收到的校验值和重新计算的校验值来判断数据是否出现错误。
本文将介绍CRC算法的原理以及如何使用C语言实现。
一、CRC算法原理1.多项式表示CRC算法使用一个多项式来进行计算,这个多项式称为校验多项式(Generator Polynomial)。
在CRC算法中,校验多项式是一个二进制数,其中最高位为1,低位为0。
例如,CRC-32算法的校验多项式是0x04C11DB72.计算过程(1)初始化:将校验值设为一个固定的初始值,通常为全为0的二进制数。
(2)数据处理:逐位处理输入的数据,包括附加校验值的数据。
(3)除法运算:对每一位数据按位异或,然后进行除法运算,取余数。
(4)更新校验值:将余数与下一位数据进行异或运算,再将结果作为新的校验值。
(5)重复上述步骤,直到处理完所有的数据。
3.校验结果CRC算法的校验结果即为最后得到的校验值。
在进行校验时,接收方使用相同的校验多项式,对接收到的数据进行相同的操作,得到的校验值与发送方发送的校验值进行比较,如果相同,则说明数据未发生错误,否则则说明数据出现了错误。
二、C语言实现CRC算法下面是一个简单的C语言实现CRC算法的例子,以CRC-32算法为例:```c#include <stdio.h>//初始化校验值unsigned int crc32_inireturn 0xFFFFFFFF;//计算CRC值unsigned int i, j;for (i = 0; i < length; i++)crc = crc ^ data[i];for (j = 0; j < 8; j++)if ((crc & 1) != 0)crc = (crc >> 1) ^ CRC32_POLYNOMIAL;} elsecrc = crc >> 1;}}}return crc;int maiunsigned char data[] = "Hello, World!";unsigned int crc = crc32_init(;printf("CRC-32 value: %08X\n", crc ^ 0xFFFFFFFF);return 0;```以上就是CRC算法的原理及使用C语言实现的内容。
C语言实现CRC校验
C语言实现CRC校验C语言中实现CRC校验可以采用多种方法,包括手动计算和使用现成的库函数等。
本文将介绍两种常用的方法:表格法和位操作法。
1.表格法:表格法利用一个查找表来加速CRC计算,具体实现步骤如下:1. 定义一个常量数组table,用于存储所有可能的CRC值。
2.遍历待校验的数据,计算每一个字节的CRC值,并使用该值作为下一个字节的查找表偏移量。
3.根据查找表找到下一个字节对应的CRC值,并更新当前CRC值。
4.重复上述步骤直到遍历完所有字节。
5.返回最终的CRC值。
下面是一个用于计算CRC-16的示例代码:```c#include <stdio.h>//查找表unsigned short crc_table[256];//初始化查找表void init_crc_tablunsigned short crc;int i, j;for(i = 0; i < 256; i++)crc = i;for(j = 0; j < 8; j++)if(crc & 0x0001)crc = (crc >> 1) ^ 0xA001;elsecrc >>= 1;}crc_table[i] = crc;}//计算CRC-16值unsigned short crc16(unsigned char *buf, int len) unsigned short crc = 0xFFFF;for(int i = 0; i < len; i++)crc = (crc >> 8) ^ crc_table[(crc ^ buf[i]) & 0xFF]; }return crc;int maiinit_crc_table(;unsigned char data[] = {0x01, 0x02, 0x03, 0x04, 0x05};int len = sizeof(data) / sizeof(unsigned char);unsigned short crc = crc16(data, len);printf("CRC-16: %04X\n", crc);return 0;```2.位操作法:位操作法直接利用位操作运算来计算CRC值,具体实现步骤如下:1.初始化CRC值为一个特定的初始值。
CRC校验方法用C语言实现源代码
CRC校验方法用C语言实现源代码CRC校验方法,用C语言实现源代码CRC(Cyclic Redundancy Check)校验应用较为广泛,以前为了处理简单,在程序中大多数采用LRC(Longitudinal Redundancy Check)校验,LRC校验很好理解,编程实现简单。
用了一天时间研究了CRC的C语言实现,理解和掌握了基本原理和C语言编程。
结合自己的理解简单写下来。
1、CRC简介CRC检验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个检验码r位(就是CRC码),附在信息后面,构成一个新的二进制码序列数共(k+r)位,最后发送出去。
接收端根据同样的规则校验,以确定传送中是否出错。
接收端有两种处理方式:1、计算k位序列的CRC码,与接收到的CRC 比较,一致则接收正确。
2、计算整个k+r位的CRC码,若为0,则接收正确。
CRC码有多种检验位数,8位、16位、32位等,原理相同。
16位的CRC码产生的规则是先将要发送的二进制序列数左移16位,除以一个多项式,最后所得到的余数就是CRC码。
求CRC码所采用的是模2运算法则,即多项式除法中采用不带借位的减法运算,运算等同于异或运算。
这一点要仔细理解,是编程的基础。
CRC-16: (美国二进制同步系统中采用) G(X) = X16 + X15 + X2 + 1 CRC-CCITT: (欧洲CCITT推荐) G(X) = X16 + X12 + X5 + 1 CRC-32: G(X) = X32 + X26 + X23 + X22 + X16 +X12 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + 1 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 000起对0x11021求余,这一步理解应该没什么问题。
c语言crc校验例程a001
C语言CRC校验例程1. 介绍CRC(Cyclic Redundancy Check)是一种广泛用于数据传输的校验方法,通过对数据进行多项式运算得到校验值,以验证数据的完整性和准确性。
在通信和存储系统中,CRC校验常用于检测数据传输过程中的错误,防止数据的损坏或篡改。
本文将介绍C语言中的CRC校验例程,以帮助读者了解和使用CRC校验算法。
2. CRC校验算法原理CRC校验算法是基于多项式运算的一种校验方法。
它通过对数据的每个字节进行位运算,并不断更新一个寄存器的值,最终得到校验值。
具体步骤如下:- 初始化寄存器为一个预设的值。
- 按照预定的运算规则,对数据的每个字节进行位运算,并更新寄存器的值。
- 对最终的寄存器值进行进一步处理,得到最终的校验值。
3. CRC校验算法实现C语言中可以通过以下方式实现CRC校验算法:1) 选择合适的CRC多项式和初始值。
不同的应用场景可能需要选择不同的CRC多项式和初始值,因此在实现CRC校验算法时,需要根据具体的需求来选择合适的参数。
2) 实现位运算函数。
使用C语言的位运算操作(如按位与、按位异或等),对数据进行逐位操作,以实现CRC校验算法的运算过程。
需要注意的是,位运算需要根据具体的CRC多项式来确定运算规则。
3) 实现CRC校验函数。
将CRC校验算法的运算过程封装成一个函数,以便在需要时调用。
该函数需要接受数据和数据长度作为输入,并返回计算得到的CRC校验值。
4. 示例代码下面是一个简单的C语言CRC校验例程,用于计算数据的CRC校验值:```c#include <stdio.h>/* CRC多项式 */#define CRC_POLYNOMIAL 0xEDBxxx/* 初始化寄存器值 */#define CRC_INITIAL 0xFFFFFFFF/* CRC校验函数 */unsigned int crc32(const unsigned char *data, int len) {unsigned int crc = CRC_INITIAL;int i, j;for (i = 0; i < len; i++) {crc = crc ^ data[i];for (j = 0; j < 8; j++) {if (crc 0x1) {crc = (crc >> 1) ^ CRC_POLYNOMIAL;} else {crc = crc >> 1;}}}return crc ^ CRC_INITIAL;}int m本人n() {unsigned char data[] = {0x01, 0x02, 0x03, 0x04, 0x05}; unsigned int crc = crc32(data, sizeof(data));printf("CRC32: 0xX\n", crc);return 0;}```5. 总结本文介绍了C语言中CRC校验例程的实现方法,通过选择合适的CRC多项式和初始值,以及使用位运算函数,实现了一个CRC校验算法的示例代码。
c语言crc校验程序查表法
c语言crc校验程序查表法
(原创版)
目录
1.CRC 校验原理
2.C 语言 CRC 校验程序实现
3.查表法在 CRC 校验中的应用
4.实例:使用查表法实现 CRC 校验
正文
一、CRC 校验原理
CRC(Cyclic Redundancy Check,循环冗余校验)是一种基于二进制多项式的数据校验技术。
它通过在数据末尾附加一些校验位,然后接收方在接收到数据后,通过相同的计算方法,对数据进行校验,以判断数据在传输过程中是否发生了改变或损坏。
CRC 校验的主要优点是能够检测出大部分数据传输错误,且计算简单,易于实现。
二、C 语言 CRC 校验程序实现
C 语言中实现 CRC 校验的主要步骤如下:
1.首先,根据需要生成一个二进制多项式。
这个多项式可以是固定的,也可以是随机生成的。
2.将待校验的数据用二进制表示,并在数据末尾添加一些校验位,使得整个数据长度可以被二进制多项式整除。
3.使用二进制多项式去除数据,得到一个余数。
这个余数就是 CRC 校验的结果。
4.在接收端,使用相同的方法计算 CRC 校验结果,然后将其与发送端得到的结果进行比较。
如果二者相同,则认为数据传输正确;如果不同,
则认为数据发生了改变或损坏。
三、查表法在 CRC 校验中的应用
查表法是一种常用的 CRC 校验算法。
它通过预先计算一组 CRC 值,并将其存储在表格中。
在需要进行 CRC 校验时,只需要查找对应的 CRC 值即可。
这种方法的优点是计算速度快,节省存储空间。
CRC常见算法的C语言实现
CRC常见算法的C语言实现CRC(Cyclic Redundancy Check)是一种常见的数据校验算法,用于检测或校正以循环方式传输的数据中的错误。
CRC算法在通信、存储、校验等领域得到广泛应用。
以下是CRC常见算法的C语言实现示例。
1.CRC-8校验算法:```// CRC-8 polynomial: x^8+x^2+x+1 (0x07)unsigned char crc8(const unsigned char *data, unsigned int length)unsigned char crc = 0;for (unsigned int i = 0; i < length; i++)crc ^= data[i];for (unsigned int j = 0; j < 8; j++)if (crc & 0x80)crc = (crc << 1) ^ 0x07;elsecrc <<= 1;}}return crc;```2.CRC-16校验算法:```// CRC-16 polynomial: x^16+x^15+x^2+1 (0x8005)unsigned short crc16(const unsigned char *data, unsigned int length)unsigned short crc = 0;for (unsigned int i = 0; i < length; i++)crc ^= (unsigned short)data[i] << 8;for (unsigned int j = 0; j < 8; j++)if (crc & 0x8000)crc = (crc << 1) ^ 0x8005;elsecrc <<= 1;}}return crc;```3.CRC-32校验算法:```// CRC-32 polynomial: 0x04c11db7unsigned int crc32(const unsigned char *data, unsigned int length)unsigned int crc = 0xFFFFFFFF;for (unsigned int i = 0; i < length; i++)crc ^= data[i];for (unsigned int j = 0; j < 8; j++)if (crc & 1)elsecrc >>= 1;}}return ~crc;```以上是常见的CRC校验算法的C语言实现示例。
C语言实现CRC校验(多种方法)
C语言实现CRC校验(多种方法)CRC(Cyclic Redundancy Check)校验应用较为广泛,以前为了处理简单,在程序中大多数采用LRC(Longitudinal Redundancy Check)校验,LRC校验很好理解,编程实现简单。
用了一天时间研究了CRC 的C语言实现,理解和掌握了基本原理和C语言编程。
结合自己的理解简单写下来。
1、CRC简介CRC检验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个检验码r位(就是CRC码),附在信息后面,构成一个新的二进制码序列数共(k+r)位,最后发送出去。
接收端根据同样的规则校验,以确定传送中是否出错。
接收端有两种处理方式:1、计算k位序列的CRC码,与接收到的CRC比较,一致则接收正确。
2、计算整个k+r位的CRC码,若为0,则接收正确。
CRC码有多种检验位数,8位、16位、32位等,原理相同。
16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(即乘以2的16次方后),除以一个多项式,最后所得到的余数就是CRC 码。
求CRC码所采用的是模2运算法则,即多项式除法中采用不带借位的减法运算,运算等同于异或运算。
这一点要仔细理解,是编程的基础。
CRC-16: (美国二进制同步系统中采用) G(X) = X16 + X15 + X2 + 1CRC-CCITT: (由欧洲CCITT推荐) G(X) = X16 + X12 + X5 + 1CRC-32: G(X) = X32 + X26 + X23 + X22 + X16 +X12 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + 12、按位计算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) + ……现在开始分析运算:<1>对第一个二进制分序列求余数,竖式除法即为0x10000 ^ 0x11021运算,后面的0位保留;<2>接着对第二个二进制分序列求余数,将第一步运算的余数*2后再和第二个二进制分序列一起对0x11021求余,这一步理解应该没什么问题。
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检验的所有常用算法(C代码)
CRC检验的所有常⽤算法(C代码)本⽂的代码从以下⽹址修改⽽来:《CRC16常见⼏个标准的算法及C语⾔实现》代码在VS2008上验证过。
⼀共有6个⽂件。
crc_common.h/****************************Info*********************************************** Name: InvertUint8* Note: 把字节颠倒过来,如0x12变成0x480x12: 0001 00100x48: 0100 1000*****************************************************************************/void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf);void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf);void InvertUint32(unsigned int *dBuf,unsigned int *srcBuf);crc_common.cpp// 参考⾃; https:///leumber/article/details/54311811?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160274684119724813264633%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%2 /****************************Info*********************************************** Name: InvertUint8* Note: 把字节颠倒过来,如0x12变成0x480x12: 0001 00100x48: 0100 1000*****************************************************************************/void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf){int i;unsigned char tmp[4]={0};for(i=0;i< 8;i++){if(srcBuf[0]& (1 << i))tmp[0]|=1<<(7-i);}dBuf[0] = tmp[0];}void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf){int i;unsigned short tmp[4]={0};for(i=0;i< 16;i++){if(srcBuf[0]& (1 << i))tmp[0]|=1<<(15 - i);}dBuf[0] = tmp[0];}void InvertUint32(unsigned int *dBuf,unsigned int *srcBuf){int i;unsigned int tmp[4]={0};for(i=0;i< 32;i++){if(srcBuf[0]& (1 << i))tmp[0]|=1<<(31 - i);}dBuf[0] = tmp[0];}crc_16.h/****************************Info*********************************************** Name: CRC-16/CCITT x16+x12+x5+1* Width: 16* Poly: 0x1021* Init: 0x0000* Refin: True* Refout: True* Xorout: 0x0000* Alias: CRC-CCITT,CRC-16/CCITT-TRUE,CRC-16/KERMIT*****************************************************************************/unsigned short CRC16_CCITT(unsigned char *data, unsigned int datalen);/****************************Info*********************************************** Name: CRC-16/CCITT-FALSE x16+x12+x5+1* Width: 16* Poly: 0x1021* Init: 0xFFFF* Refin: False* Refout: False* Xorout: 0x0000* Note:*****************************************************************************/unsigned short CRC16_CCITT_FALSE(unsigned char *data, unsigned int datalen);/****************************Info*********************************************** Name: CRC-16/XMODEM x16+x12+x5+1* Width: 16* Poly: 0x1021* Init: 0x0000* Refin: False* Refout: False* Xorout: 0x0000*****************************************************************************/ unsigned short CRC16_XMODEM(unsigned char *data, unsigned int datalen); /****************************Info*********************************************** Name: CRC-16/X25 x16+x12+x5+1* Width: 16* Poly: 0x1021* Init: 0xFFFF* Refin: True* Refout: True* Xorout: 0XFFFF* Note:*****************************************************************************/ unsigned short CRC16_X25(unsigned char *data, unsigned int datalen);/****************************Info*********************************************** Name: CRC-16/MODBUS x16+x15+x2+1* Width: 16* Poly: 0x8005* Init: 0xFFFF* Refin: True* Refout: True* Xorout: 0x0000* Note:*****************************************************************************/ unsigned short CRC16_MODBUS(unsigned char *data, unsigned int datalen); /****************************Info*********************************************** Name: CRC-16/IBM x16+x15+x2+1* Width: 16* Poly: 0x8005* Init: 0x0000* Refin: True* Refout: True* Xorout: 0x0000* Alias: CRC-16,CRC-16/ARC,CRC-16/LHA*****************************************************************************/ unsigned short CRC16_IBM(unsigned char *data, unsigned int datalen);/****************************Info*********************************************** Name: CRC-16/MAXIM x16+x15+x2+1* Width: 16* Poly: 0x8005* Init: 0x0000* Refin: True* Refout: True* Xorout: 0xFFFF* Note:*****************************************************************************/ unsigned short CRC16_MAXIM(unsigned char *data, unsigned int datalen);/****************************Info*********************************************** Name: CRC-16/USB x16+x15+x2+1* Width: 16* Poly: 0x8005* Init: 0xFFFF* Refin: True* Refout: True* Xorout: 0xFFFF* Note:*****************************************************************************/ unsigned short CRC16_USB(unsigned char *data, unsigned int datalen);/****************************Info*********************************************** Name: CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1* Width: 16* Poly: 0x3D65* Init: 0x0000* Refin: True* Refout: True* Xorout: 0xFFFF* Use: M-Bus,ect.*****************************************************************************/ unsigned short CRC16_DNP(unsigned char *data, unsigned int datalen);crc_16.cpp#include <stdio.h>#include "crc_common.h"/****************************Info*********************************************** Name: CRC-16/CCITT x16+x12+x5+1* Width: 16* Poly: 0x1021* Init: 0x0000* Refin: True* Refout: True* Xorout: 0x0000* Alias: CRC-CCITT,CRC-16/CCITT-TRUE,CRC-16/KERMIT*****************************************************************************/#if 0unsigned short CRC16_CCITT(unsigned char *data, unsigned int datalen){unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x1021;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin);}#else//这⾥为了效率,我们不需要将所有Refin和refout为true的输⼊输出数据移位转换//只需要将poly⼆项式转换后,运算时将左移变为右移unsigned short CRC16_CCITT(unsigned char *data, unsigned int datalen){unsigned short wCRCin = 0x0000;unsigned char wChar = 0;InvertUint16(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = wCRCin >> 1;}}return (wCRCin);}#endif/****************************Info*********************************************** Name: CRC-16/CCITT-FALSE x16+x12+x5+1* Width: 16* Poly: 0x1021* Init: 0xFFFF* Refin: False* Refout: False* Xorout: 0x0000* Note:*****************************************************************************/unsigned short CRC16_CCITT_FALSE(unsigned char *data, unsigned int datalen) {unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x1021;while (datalen--){wCRCin ^= *(data++) << 8;for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}return (wCRCin);}/****************************Info*********************************************** Name: CRC-16/XMODEM x16+x12+x5+1* Width: 16* Poly: 0x1021* Init: 0x0000* Refin: False* Refout: False* Xorout: 0x0000* Alias: CRC-16/ZMODEM,CRC-16/ACORN*****************************************************************************/unsigned short CRC16_XMODEM(unsigned char *data, unsigned int datalen){unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x1021;while (datalen--){wCRCin ^= (*(data++) << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}return (wCRCin);}/****************************Info*********************************************** Name: CRC-16/X25 x16+x12+x5+1* Width: 16* Poly: 0x1021* Init: 0xFFFF* Refin: True* Refout: True* Xorout: 0XFFFF* Note:*****************************************************************************/#if 0unsigned short CRC16_X25(unsigned char *data, unsigned int datalen){unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x1021;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin^0xFFFF);}#elseunsigned short CRC16_X25(unsigned char *data, unsigned int datalen){unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x1021;InvertUint16(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = wCRCin >> 1;}return (wCRCin^0xFFFF);}#endif/****************************Info*********************************************** Name: CRC-16/MODBUS x16+x15+x2+1* Width: 16* Poly: 0x8005* Init: 0xFFFF* Refin: True* Refout: True* Xorout: 0x0000* Note:*****************************************************************************/#if 0unsigned short CRC16_MODBUS(unsigned char *data, unsigned int datalen) {unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x8005;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin);}#elseunsigned short CRC16_MODBUS(unsigned char *data, unsigned int datalen) {unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x8005;InvertUint16(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = wCRCin >> 1;}}return (wCRCin);}#endif/****************************Info*********************************************** Name: CRC-16/IBM x16+x15+x2+1* Width: 16* Poly: 0x8005* Init: 0x0000* Refin: True* Refout: True* Xorout: 0x0000* Alias: CRC-16,CRC-16/ARC,CRC-16/LHA*****************************************************************************/#if 0unsigned short CRC16_IBM(unsigned char *data, unsigned int datalen){unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x8005;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin);}#elseunsigned short CRC16_IBM(unsigned char *data, unsigned int datalen){unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x8005;InvertUint16(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = wCRCin >> 1;}}return (wCRCin);}#endif/****************************Info*********************************************** Name: CRC-16/MAXIM x16+x15+x2+1* Width: 16* Poly: 0x8005* Init: 0x0000* Refin: True* Refout: True* Xorout: 0xFFFF* Note:*****************************************************************************/unsigned short CRC16_MAXIM(unsigned char *data, unsigned int datalen) {unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x8005;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin^0xFFFF);}#elseunsigned short CRC16_MAXIM(unsigned char *data, unsigned int datalen) {unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x8005;InvertUint16(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = wCRCin >> 1;}}return (wCRCin^0xFFFF);}#endif/****************************Info*********************************************** Name: CRC-16/USB x16+x15+x2+1* Width: 16* Poly: 0x8005* Init: 0xFFFF* Refin: True* Refout: True* Xorout: 0xFFFF* Note:*****************************************************************************/#if 0unsigned short CRC16_USB(unsigned char *data, unsigned int datalen) {unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x8005;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin^0xFFFF);}#elseunsigned short CRC16_USB(unsigned char *data, unsigned int datalen) {unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x8005;InvertUint16(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = wCRCin >> 1;}}return (wCRCin^0xFFFF);}#endif/****************************Info*********************************************** Name: CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1 * Width: 16* Poly: 0x3D65* Init: 0x0000* Refin: True* Refout: True* Xorout: 0xFFFF* Use: M-Bus,ect.*****************************************************************************/#if 0unsigned short CRC16_DNP(unsigned char *data, unsigned int datalen) {unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x3D65;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin^0xFFFF) ;}#elseunsigned short CRC16_DNP(unsigned char *data, unsigned int datalen){unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x3D65;InvertUint16(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = (wCRCin >> 1);}}return (wCRCin^0xFFFF);}#endifcrc_32.h/****************************Info*********************************************** Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1* Width: 32* Poly: 0x4C11DB7* Init: 0xFFFFFFF* Refin: True* Refout: True* Xorout: 0xFFFFFFF* Alias: CRC_32/ADCCP* Use: WinRAR,ect.*****************************************************************************/unsigned int CRC32(unsigned char *data, unsigned int datalen);/****************************Info*********************************************** Name: CRC-32/MPEG-2 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 * Width: 32* Poly: 0x4C11DB7* Init: 0xFFFFFFF* Refin: False* Refout: False* Xorout: 0x0000000* Note:*****************************************************************************/unsigned int CRC32_MPEG(unsigned char *data, unsigned int datalen);crc_32.cpp#include "crc_common.h"/****************************Info*********************************************** Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1* Width: 32* Poly: 0x4C11DB7* Init: 0xFFFFFFF* Refin: True* Refout: True* Xorout: 0xFFFFFFF* Alias: CRC_32/ADCCP* Use: WinRAR,ect.*****************************************************************************/#if 0unsigned int CRC32(unsigned char *data, unsigned int datalen){unsigned int wCRCin = 0xFFFFFFFF;unsigned int wCPoly = 0x04C11DB7;unsigned int wChar = 0;while (datalen--){wChar = *(data++);InvertUint8((unsigned char *)&wChar,(unsigned char *)&wChar);wCRCin ^= (wChar << 24);for(int i = 0;i < 8;i++){if(wCRCin & 0x80000000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint32(&wCRCin,&wCRCin);return (wCRCin ^ 0xFFFFFFFF) ;}#elseunsigned int CRC32(unsigned char *data, unsigned int datalen){unsigned int wCRCin = 0xFFFFFFFF;unsigned int wCPoly = 0x04C11DB7;InvertUint32(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = wCRCin >> 1;}}return (wCRCin ^ 0xFFFFFFFF) ;}#endif/****************************Info*********************************************** Name: CRC-32/MPEG-2 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 * Width: 32* Refin: False* Refout: False* Xorout: 0x0000000* Note:*****************************************************************************/ unsigned int CRC32_MPEG(unsigned char *data, unsigned int datalen) {unsigned int wCRCin = 0xFFFFFFFF;unsigned int wCPoly = 0x04C11DB7;unsigned int wChar = 0;while (datalen--){wChar = *(data++);wCRCin ^= (wChar << 24);for(int i = 0;i < 8;i++){if(wCRCin & 0x80000000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}return (wCRCin) ;}crc_4_5_6_7_8.h/****************************Info********************************************** * Name: CRC-4/ITU x4+x+1* Width: 4* Poly: 0x03* Init: 0x00* Refin: True* Refout: True* Xorout: 0x00* Note:*****************************************************************************/ unsigned char CRC4_ITU(unsigned char *data, unsigned int datalen); /****************************Info********************************************** * Name: CRC-5/EPC x5+x3+1* Width: 5* Poly: 0x09* Init: 0x09* Refin: False* Refout: False* Xorout: 0x00* Note:*****************************************************************************/ unsigned char CRC5_EPC(unsigned char *data, unsigned int datalen); /****************************Info********************************************** * Name: CRC-5/USB x5+x2+1* Width: 5* Poly: 0x05* Init: 0x1F* Refin: True* Refout: True* Xorout: 0x1F* Note:*****************************************************************************/ unsigned char CRC5_USB(unsigned char *data, unsigned int datalen); /****************************Info********************************************** * Name: CRC-5/ITU x5+x4+x2+1* Width: 5* Poly: 0x15* Init: 0x00* Refin: True* Refout: True* Xorout: 0x00* Note:*****************************************************************************/ unsigned char CRC5_ITU(unsigned char *data, unsigned int datalen); /****************************Info********************************************** * Name: CRC-6/ITU x6+x+1* Width: 6* Poly: 0x03* Init: 0x00* Refin: True* Refout: True* Xorout: 0x00* Note:*****************************************************************************/ unsigned char CRC6_ITU(unsigned char *data, unsigned int datalen); /****************************Info********************************************** * Name: CRC-7/MMC x7+x3+1* Width: 7* Poly: 0x09* Init: 0x00* Refin: False* Refout: False* Xorout: 0x00* Use: MultiMediaCard,SD,ect.*****************************************************************************/ unsigned char CRC7_MMC(unsigned char *data, unsigned int datalen); /****************************Info********************************************** * Name: CRC-8 x8+x2+x+1* Width: 8* Poly: 0x07* Init: 0x00* Refin: False* Refout: False* Xorout: 0x00* Note:*****************************************************************************/ unsigned char CRC8(unsigned char *data, unsigned int datalen);/****************************Info********************************************** * Name: CRC-8/ITU x8+x2+x+1* Width: 8* Poly: 0x07* Init: 0x00* Refin: False* Refout: False* Xorout: 0x55*****************************************************************************/ unsigned char CRC8_ITU(unsigned char *data, unsigned int datalen);/****************************Info*********************************************** Name: CRC-8/ROHC x8+x2+x+1* Width: 8* Poly: 0x07* Init: 0xFF* Refin: True* Refout: True* Xorout: 0x00* Note:*****************************************************************************/ unsigned char CRC8_ROHC(unsigned char *data, unsigned int datalen); /****************************Info*********************************************** Name: CRC-8/MAXIM x8+x5+x4+1* Width: 8* Poly: 0x31* Init: 0x00* Refin: True* Refout: True* Xorout: 0x00* Alias: DOW-CRC,CRC-8/IBUTTON* Use: Maxim(Dallas)'s some devices,e.g. DS18B20*****************************************************************************/ unsigned char CRC8_MAXIM(unsigned char *data, unsigned int datalen); crc_4_5_6_7_8.cpp#include "crc_common.h"/****************************Info*********************************************** Name: CRC-4/ITU x4+x+1* Width: 4* Poly: 0x03* Init: 0x00* Refin: True* Refout: True* Xorout: 0x00* Note:*****************************************************************************/ unsigned char CRC4_ITU(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x03;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly << 4);elsewCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin);}/****************************Info*********************************************** Name: CRC-5/EPC x5+x3+1* Width: 5* Poly: 0x09* Init: 0x09* Refin: False* Refout: False* Xorout: 0x00* Note:*****************************************************************************/ unsigned char CRC5_EPC(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x09<<3;unsigned char wCPoly = 0x09<<3;while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly);elsewCRCin = wCRCin << 1;}}return (wCRCin >> 3);}/****************************Info*********************************************** Name: CRC-5/USB x5+x2+1* Width: 5* Poly: 0x05* Init: 0x1F* Refin: True* Refout: True* Xorout: 0x1F* Note:*****************************************************************************/#if 0unsigned char CRC5_USB(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x1F<<3;unsigned char wCPoly = 0x05;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly << 3);wCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin^0x1F);}#elseunsigned char CRC5_USB(unsigned char *data, unsigned int datalen) {unsigned char wCRCin = 0x1F;unsigned char wCPoly = 0x05;InvertUint8(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ (wCPoly >> 3);elsewCRCin = wCRCin >> 1;}}return (wCRCin^0x1F);}#endif/****************************Info********************************************** * Name: CRC-5/ITU x5+x4+x2+1* Width: 5* Poly: 0x15* Init: 0x00* Refin: True* Refout: True* Xorout: 0x00* Note:*****************************************************************************/#if 0unsigned char CRC5_ITU(unsigned char *data, unsigned int datalen) {unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x15;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly << 3);elsewCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin);}#elseunsigned char CRC5_ITU(unsigned char *data, unsigned int datalen) {unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x15;InvertUint8(&wCPoly,&wCPoly);while (datalen--){wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ (wCPoly >> 3);elsewCRCin = wCRCin >> 1;}}return (wCRCin);}#endif/****************************Info********************************************** * Name: CRC-6/ITU x6+x+1* Width: 6* Poly: 0x03* Init: 0x00* Refin: True* Refout: True* Xorout: 0x00* Note:*****************************************************************************/ unsigned char CRC6_ITU(unsigned char *data, unsigned int datalen) {unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x03;unsigned char wChar = 0;while (datalen--){wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly << 2);elsewCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin);}/****************************Info********************************************** * Name: CRC-7/MMC x7+x3+1* Width: 7* Poly: 0x09* Init: 0x00* Refin: False* Refout: False* Xorout: 0x00* Use: MultiMediaCard,SD,ect.。
CRC校验算法的分析及C语言实现
CRC校验算法的分析及C语言实现CRC(循环冗余校验)是一种常见的校验算法,用于检测和纠正数据传输中的错误。
CRC校验算法通过生成多项式对发送的数据进行计算,并将校验结果附加到数据中进行传输。
接收方可以使用相同的多项式进行计算,并将结果与接收到的数据进行比较,以检查是否存在传输错误。
1.选择一个生成多项式,通常用一个16位或32位的二进制数表示。
2.将原始数据与补充的0进行异或操作,并左移一个单位。
3.重复上述步骤,直到向左移位的次数等于生成多项式的位数。
4.将得到的余数作为校验位,将其附加到原始数据后面。
5.接收方使用相同的生成多项式进行计算,并将计算得到的余数与接收到的数据进行比较。
如果两者不相等,则说明数据存在错误。
接下来,我们将使用C语言实现一个简单的CRC校验算法。
```c#include <stdio.h>#include <stdbool.h>unsigned long crc_table[256];//初始化CRC表void init_crc_tablunsigned long crc;int i, j;for (i = 0; i < 256; i++)crc = i;for (j = 8; j > 0; j--)if (crc & 1)crc = (crc >> 1) ^ POLYNOMIAL;elsecrc >>= 1;}crc_table[i] = crc;}//计算CRC值unsigned long crc32(unsigned char *message, int length) unsigned long crc = 0xfffffffful;int i;for (i = 0; i < length; i++)crc = (crc >> 8) ^ crc_table[(crc & 0xff) ^ message[i]]; return crc ^ 0xfffffffful;int maiint length = sizeof(message) - 1;init_crc_table(;unsigned long crc = crc32(message, length);printf("CRC32: %lx\n", crc);return 0;```上述代码中,我们首先定义了一个生成多项式POLYNOMIAL,并定义了一个包含256个元素的CRC表crc_table。
c语言crc校验程序查表法
c语言crc校验程序查表法CRC校验是一种常用的数据校验方法,通过生成多项式对数据进行计算,以检测数据传输是否发生错误。
本文将以人类视角,以生动的语言描述CRC校验的原理和过程,避免使用数学公式和计算公式,确保文章内容的独一性和流畅度。
【引言】在现代通信中,数据的准确传输至关重要。
然而,由于各种原因,数据在传输过程中可能会发生错误。
为了解决这个问题,CRC(循环冗余校验)应运而生。
它可以有效地检测出数据传输中的错误,并提供可靠的数据校验手段。
【CRC校验的原理】CRC校验的核心思想是利用多项式的除法来计算校验值。
在发送数据前,发送方先根据事先约定的生成多项式对数据进行计算,得到校验值。
接收方则根据相同的生成多项式对接收到的数据进行计算,并与发送方的校验值进行比对。
如果两者一致,说明数据传输无误;如果不一致,则说明数据传输中发生了错误。
【CRC校验的过程】生成多项式需要事先约定,并称之为生成多项式或者CRC多项式。
生成多项式的选取非常重要,它的不同会导致CRC校验的性能差异。
常用的生成多项式有CRC-16和CRC-32等。
接下来,发送方将待发送的数据和生成多项式进行计算。
具体步骤如下:1. 将待发送的数据进行左移,留出和生成多项式相同位数的空位。
2. 将生成多项式与左移后的数据进行异或操作。
3. 重复以上两步的操作,直到所有数据都被处理完毕。
4. 最后得到的结果就是校验值,将其附加在待发送的数据后面,一起发送给接收方。
接收方接收到数据后,将数据和生成多项式进行相同的计算,并得到一个校验值。
然后,将接收到的校验值与计算得到的校验值进行比对。
如果一致,说明数据传输无误;如果不一致,说明数据传输中发生了错误。
【总结】CRC校验是一种常用的数据校验方法,通过生成多项式对数据进行计算,以检测数据传输是否发生错误。
通过约定生成多项式、对数据进行异或操作,CRC校验可以有效地检测出数据传输中的错误。
虽然本文避免使用数学公式和计算公式,但通过生动的语言描述,读者可以清晰地了解CRC校验的原理和过程。
【转】crc16几种标准校验算法及c语言代码
【转】crc16⼏种标准校验算法及c语⾔代码⼀、CRC16校验码的使⽤ 现选择最常⽤的CRC-16校验,说明它的使⽤⽅法。
根据Modbus协议,常规485通讯的信息发送形式如下: 地址功能码数据信息校验码 1byte 1byte nbyte 2byte CRC校验是前⾯⼏段数据内容的校验值,为⼀个16位数据,发送时,低8位在前,⾼8为最后。
例如:信息字段代码为: 1011001,校验字段为:1010。
发送⽅:发出的传输字段为: 1 0 1 1 0 0 1 1 0 10 信息字段校验字段 接收⽅:使⽤相同的计算⽅法计算出信息字段的校验码,对⽐接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则信息正确。
⼆、CRC16校验码计算⽅法 常⽤查表法和计算法。
计算⽅法⼀般都是: (1)、预置1个16位的寄存器值0xFFFF,称此寄存器为CRC寄存器; (2)、把第⼀个8位⼆进制数据(既通讯信息帧的第⼀个字节)与16位的CRC寄存器的低 8位相异或,把结果放于CRC寄存器,⾼⼋位数据不变; (3)、把CRC寄存器的内容右移⼀位(朝⾼位)⽤0填补最⾼位,并检查右移后的移出位; (4)、如果移出位为0:重复第3步(再次右移⼀位);如果移出位为1,CRC寄存器与⼀多 项式(A001)进⾏异或; (5)、重复步骤3和4,直到右移8次,这样整个8位数据全部进⾏了处理; (6)、重复步骤2到步骤5,进⾏通讯信息帧下⼀个字节的处理; (7)、将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的⾼、低 字节进⾏交换; (8)、最后得到的CRC寄存器内容即为:CRC码。
以上计算步骤中的多项式A001是8005按位颠倒后的结果。
查表法是将移位异或的计算结果做成了⼀个表,就是将0~256放⼊⼀个长度为16位的寄存器中的低⼋位,⾼⼋位填充0,然后将该寄存器与多项式0XA001按照上述3、4步骤,直到⼋位全部移出,最后寄存器中的值就是表格中的数据,⾼⼋位、低⼋位分别单独⼀个表。
CRC算法原理及C语言实现(介绍了3种方法)
CRC算法原理及C语言实现(介绍了3种方法)摘要本文从理论上推导出CRC算法实现原理,给出三种分别适应不同计算机或微控制器硬件环境的C语言程序。
读者更能根据本算法原理,用不同的语言编写出独特风格更加实用的CRC计算程序。
关键词 CRC 算法 C语言1 引言循环冗余码CRC检验技术广泛应用于测控及通信领域。
CRC计算可以靠专用的硬件来实现,但是对于低成本的微控制器系统,在没有硬件支持下实现CRC检验,关键的问题就是如何通过软件来完成CRC 计算,也就是CRC算法的问题。
这里将提供三种算法,它们稍有不同,一种适用于程序空间十分苛刻但CRC计算速度要求不高的微控制器系统,另一种适用于程序空间较大且CRC计算速度要求较高的计算机或微控制器系统,最后一种是适用于程序空间不太大,且CRC计算速度又不可以太慢的微控制器系统。
2 CRC简介CRC校验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去。
在接收端,则根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。
16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(既乘以)后,再除以一个多项式,最后所得到的余数既是CRC码,如式(2-1)式所示,其中B(X)表示n位的二进制序列数,G(X)为多项式,Q(X)为整数,R(X)是余数(既CRC码)。
(2-1)求CRC码所采用模2加减运算法则,既是不带进位和借位的按位加减,这种加减运算实际上就是逻辑上的异或运算,加法和减法等价,乘法和除法运算与普通代数式的乘除法运算是一样,符合同样的规律。
生成CRC码的多项式如下,其中CRC-16和CRC-CCITT产生16位的CRC码,而CRC-32则产生的是32位的CRC码。
本文不讨论32位的CRC算法,有兴趣的朋友可以根据本文的思路自己去推导计算方法。
循环冗余检验 (CRC) 算法原理及C语言实现
{
unsigned long Table_CRC[256]; // CRC 表
unsigned long i;
unsigned short nAccum = 0;
BuildTable16( aPoly, Table_CRC ); //创建CRC表
//第一个字节以本字节作为索引查表,第二个字节开始,由上一次计算的B'[(nAccumm&0x00FF) xor *aData]作为索引
b1 110 1010 1000 ;S1最高位为,取多项式(去掉最高位);商对应位填,除数(S1')与被除数(b1)异或运算,因为除数(S1)
与多项式(被除数)最高位都为,异或为,因此运算时直接移位出去
-------------------
S2 111 1001 0010 ;S2=S1' xor b1
商补,移入下一位运算)
-------------------
S4
0 1100 0110 ;S4=S3' xor b3
S4'
1100 0110 ;S4最高位为,移位
b4
0000 0000 ;S4最高位为,取
-------------------
CRC
1100 0110 ;CRC=S4' xor b4=B23 xor (b1 xor b2 xor b3 xor b4)=B23 xor b',b'ort )Table_CRC[( nAccum&0x00ff) ^ *aData++];-----b' // nAccumm>>8-----第一个字节计算取,第二个字节开始取上次运算的低(X-八)位(S1->B2 B3) // ( nAccum>> 8 ) ^ ( unsigned short )Table_CRC[( nAccum&0x00ff) ^ *aData++];----S1->B2B3 xor b' // S1 B1 B2 // S1' B2 B3 // b' -----使用B1查表得到b' //----------------------------------// S2 B2' B3' -----B2'B3'=(B2B3) xor b' // S2' B3' B4 // b' -----使用B2'查表得到b' //----------------------------------// S2 B3'' B4' -----B3''B4'=(B3'B4) xor b' // S2' B4' B5 // b' -----使用B3''查表得到b' //............ //把字符串分为每个字节处理的数学理论基础: //a xor b=a+b=a-b //word=byte_h + byte_l,例word=0xABCD,byte_h=0xAB00,byte_l=0x00CD //word xor b=(byte_h+byte_l)xor b=byte_h xor b xor byte_l ;//因此字符串可以按字节处理,并把上一字节的处理结果与下 一字节继续运算
CRC12_C语言实现
CRC12_C语言实现一概述CRC(Cyclical Redundancy Check)循环冗余码校验。
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的同步传输中。
二实现方法1、移位法2、查表法三 C语言案例移位法与查表法,是CRC12的具体实现形式,设计者可根据设计环境具体选择。
// 移位法CRC12校验码计算函数WORD CRC12(BYTE a cbyBuff[], int iLen){WORD wCRC;int i, iQ;BYTE iR;wCRC = 0;iQ = 0;iR = 0;while(iQ < iLen){// 多项式除法// 如果该位为1if(acbyBuff[iQ] & (0x80>>iR)){// 则在余数尾部添1否则添0wCRC |= 0x01;}// 如果12位除数中的最高位为1,则够除if(wCRC >= 0x1000){wCRC ^= 0x180D;}wCRC <<= 1;iR++;if(8 == iR){iR = 0;iQ++;}}// 对后面添加的12个0做处理for(i=0; i<12; i++){if(wCRC >= 0x1000){wCRC ^= 0x180D;}wCRC <<= 1;}wCRC >>= 1;return wCRC;}// 查表法CRC12校验码计算函数WORD TableCRC12(BYTE buff[], int len){int n;WORD Cn;BYTE ab, fg;WORD awCRC_Code[] ={0x0000, 0x080D, 0x0817, 0x001A, 0x0823, 0x002E, 0x0034, 0x0839,0x084B, 0x0046, 0x005C, 0x0851, 0x0068, 0x0865, 0x087F, 0x0072,0x089B, 0x0096, 0x008C, 0x0881, 0x00B8, 0x08B5, 0x08AF, 0x00A2,0x00D0, 0x08DD, 0x08C7, 0x00CA, 0x08F3, 0x00FE, 0x00E4, 0x08E9,0x093B, 0x0136, 0x012C, 0x0921, 0x0118, 0x0915, 0x090F, 0x0102,0x0170, 0x097D, 0x0967, 0x016A, 0x0953, 0x015E, 0x0144, 0x0949,0x01A0, 0x09AD, 0x09B7, 0x01BA, 0x0983, 0x018E, 0x0194, 0x0999,0x09EB, 0x01E6, 0x01FC, 0x09F1, 0x01C8, 0x09C5, 0x09DF, 0x01D2,0x0A7B, 0x0276, 0x026C, 0x0A61, 0x0258, 0x0A55, 0x0A4F, 0x0242,0x0230, 0x0A3D, 0x0A27, 0x022A, 0x0A13, 0x021E, 0x0204, 0x0A09,0x02E0, 0x0AED, 0x0AF7, 0x02FA, 0x0AC3, 0x02CE, 0x02D4, 0x0AD9,0x0AAB, 0x02A6, 0x02BC, 0x0AB1, 0x0288, 0x0A85, 0x0A9F, 0x0292,0x0340, 0x0B4D, 0x0B57, 0x035A, 0x0B63, 0x036E, 0x0374, 0x0B79,0x0B0B, 0x0306, 0x031C, 0x0B11, 0x0328, 0x0B25, 0x0B3F, 0x0332,0x0BDB, 0x03D6, 0x03CC, 0x0BC1, 0x03F8, 0x0BF5, 0x0BEF, 0x03E2,0x0390, 0x0B9D, 0x0B87, 0x038A, 0x0BB3, 0x03BE, 0x03A4, 0x0BA9,0x0CFB, 0x04F6, 0x04EC, 0x0CE1, 0x04D8, 0x0CD5, 0x0CCF, 0x04C2,0x04B0, 0x0CBD, 0x0CA7, 0x04AA, 0x0C93, 0x049E, 0x0484, 0x0C89,0x0460, 0x0C6D, 0x0C77, 0x047A, 0x0C43, 0x044E, 0x0454, 0x0C59,0x0C2B, 0x0426, 0x043C, 0x0C31, 0x0408, 0x0C05, 0x0C1F, 0x0412,0x05C0, 0x0DCD, 0x0DD7, 0x05DA, 0x0DE3, 0x05EE, 0x05F4, 0x0DF9,0x0D8B, 0x0586, 0x059C, 0x0D91, 0x05A8, 0x0DA5, 0x0DBF, 0x05B2,0x0D5B, 0x0556, 0x054C, 0x0D41, 0x0578, 0x0D75, 0x0D6F, 0x0562,0x0510, 0x0D1D, 0x0D07, 0x050A, 0x0D33, 0x053E, 0x0524, 0x0D29,0x0680, 0x0E8D, 0x0E97, 0x069A, 0x0EA3, 0x06AE, 0x06B4, 0x0EB9,0x0ECB, 0x06C6, 0x06DC, 0x0ED1, 0x06E8, 0x0EE5, 0x0EFF, 0x06F2,0x0E1B, 0x0616, 0x060C, 0x0E01, 0x0638, 0x0E35, 0x0E2F, 0x0622,0x0650, 0x0E5D, 0x0E47, 0x064A, 0x0E73, 0x067E, 0x0664, 0x0E69,0x0FBB, 0x07B6, 0x07AC, 0x0FA1, 0x0798, 0x0F95, 0x0F8F, 0x0782,0x07F0, 0x0FFD, 0x0FE7, 0x07EA, 0x0FD3, 0x07DE, 0x07C4, 0x0FC9,0x0720, 0x0F2D, 0x0F37, 0x073A, 0x0F03, 0x070E, 0x0714, 0x0F19,0x0F6B, 0x0766, 0x077C, 0x0F71, 0x0748, 0x0F45, 0x0F5F, 0x0752 };// 第n个字节Bn求CRC12相当于// Bn 00 00 添12个0对180DH求余// Bn:xy 00 0// -----------------// |(Hi) |(Lo)// Cn: | ab | c// Bn+1 | de | 0 00// +-----+---------// B'n | fg | c 00 B'n = Bn+1^Cn_Hi 查表求得Tn的校验码C'n = i jk // C'n i jk// ----------// l jk//// Cn+1 = ((Cn&0x0F) << 8) ^ C'nCn = 0;for(n=0; n<len; n++){ab = ( Cn & 0x0FF0 ) >> 4;fg = buff[n]^ab;Cn = ((Cn&0x000F) << 8) ^ awCRC_Code[fg];}return Cn;}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
上面的程序根据运算分析而来,很容易理解。为了节约内存空间,我们对程序作进一步的简化。分析可知,当二进制序列中上一位计算的余数第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 ^ 0x1021;
}
else
{
crc = crc << 1;
}
if((*ptr & i) != 0)
{ ห้องสมุดไป่ตู้
crc = crc ^ 0x1021;
}
}
ptr++;
}
printf("0x%x ",crc);
}
上面这段程序网上较为常见,但冇得详细的解释。通过我上面的详细分析,如果对此段程序理解还有困难,可以对比一下没简化之前的程序,细细品味一哈,还是比较容易理解的。要是还理解不了,还是从头再看下,我码这么多字容易吗。。。。。
现在开始分析运算:
<1>对第一个二进制分序列求余数,竖式除法即为0x10000 ^ 0x11021运算,后面的0位保留;
<2>接着对第二个二进制分序列求余数,将第一步运算的余数*2后再和第二个二进制分序列一起对0x11021求余,这一步理解应该没什么问题。如果该分序列为0,无需计算。
<3>对其余的二进制序列求余与上面两步相同。
unsigned char len = 16;
void main( void )
{
unsigned long temp = 0;
unsigned int crc;
unsigned char i;
unsigned char *ptr = test;
while( len-- )
{
for(i = 0x80; i != 0; i = i >> 1)
unsigned char test[16] ={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
unsigned char len = 16;
void main( void )
<4>计算到最后一位时即为整个二进制序列的余数,即为CRC校验码。
该计算方法相当于对每一位计算,运算过程很容易理解,所占内存少,缺点是一位一位计算比较耗时。 下面给出C语言实现方法:
unsigned char test[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
{
temp = temp * 2;
if((temp & 0x10000) != 0)
{
temp = temp ^ 0x11021;
}
if((*ptr & i) != 0)
{
temp = temp ^ (0x10000 ^ 0x11021);
}
}
ptr++;
}
crc = temp;
}
else if(crc < 0x100)
{
printf("00");
}
else if(crc < 0x1000)
{
printf("0");
}
printf("%x, ",crc);
}
}
如果你不是使用的0x11021多项式,只需把程序中0x1021换成其他的就可以了。后面的几个printf语句为了控制使生成的表比较整齐,如果无所谓,可直接用printf("0x%x, ",crc);代替。生成的表如下:
按位计算CRC代码比较简单,所占内存少,但要一位一位去计算,下面再介绍一种按字节查表快速计算CRC的方法。
3、按字节计算CRC
有了上面按位计算的知识,理解这个就是小case了。还是举前面的例子:当字节计算CRC时,例如计算二进制序列为1001 1010 1010 1111时,即0x9a9f时,将二进制序列数左移16位,即为0x9a9f(0 0 0 0),实际上该二进制序列可拆分为0x9a00(0 0 0 0) + 0x009f(0 0 0 0),分析计算时和上面的步骤一样,唯一不同的是计算中上一步的余数CRC要乘以2的八次方参与下一步的运算,这个应该好理解撒。为了简化编程,将计算中的CRC拆成高八位和低八位的形式,高八位的值直接与本位值相加求余,低八位的值乘以2的八次方后作为余数和计算得的余数相加。为了提高计算速度,我们把8位二进制序列数的CRC全部计算出来,放在一个表中,采用查表法可大大提高计算速度。 表是怎么得到的呢?当然是计算出来的,下面的程序给出了多项式是0x11021的计算程序。
40x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,