海明码和CRC校验的C语言实现

合集下载

CRC12_C语言实现

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;}。

CRC校验算法分析及C语言实现

CRC校验算法分析及C语言实现
# # & # # & & # # # # & & & & & & # & & # # # & # # & # & & # # # & # & & # & & # # & # # # 2 ( 3 4 # && ## ) 0 1 , * . 0 ) & & & & ! ##&&&&&& * + , . /& # # && * + , . # # & && ’ ( ) # & ## * + , . # & # #& & # &# ’ ( ) * + , . & # & #& * + , . # & # && ’ ( ) & # ##
运算, 让被校验数据能为某一提前选定的生成多项式所除, 如果能除尽, 表明代码正确, 如果除不尽, 表明代 码错误, 余数则指明出错位所在位置% 因为任意一组仅由信息位组成的码, 很可能除不尽, 所以在信息位后附 加若干称为校验位的冗余位, 可以保证由信息位和冗余位组成的码组能被生成多项式整除, 如图’所示% 生成多项式的选取决定了校验位的宽度以及编码的检纠错能力, 通信系统中常用的生成 * + * 校验中, 多项式为: / * + *$ ’ , 0 + * / * + *$ ’ , * 7 . . (5) , 4 $$% ’ % " " 1 6 (5) , 4 $$% ’ ’ " ! ’ 6 … ’ … ’ " " " ’ ’ ’ &$ ’ &$ ! " " ($ ’ ($ ! ’ " " ! #" ! #

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]。

crc校验程序-c语言

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校验函数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多项式和初始值,并根据实际需求进行定制化的实现。

通过合理的设计和实现,可以保证数据的完整性和准确性,提高系统的稳定性和可靠性。

C语言实现CRC校验(多种方法)

C语言实现CRC校验(多种方法)
printf("0x%x ",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算法原理及C语言实现

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语言实现的内容。

CRC校验原理及其C语言实现-机电之家网PLC技术网

CRC校验原理及其C语言实现-机电之家网PLC技术网

CRC校验原理及其C语言实现-机电之家网PLC技术网CRC校验原理及其C语言实现在数据存储和数据通讯领域,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)&gt;&gt;16=G(x)Q(x)+R(x)求CRC码所采用模2加减运算法则,既是不带进位和借位的按位加减,这种加减运算实际上就是逻辑上的异或运算,加法和减法等价,乘法和除法运算与普通代数式的乘除法运算是一样,符合同样的规律。

生成CRC码的多项式如下,其中CRC-16和CRC-CCITT产生16位的CRC码,而CRC-32则产生的是32位的CRC码PLC资料网接收方将接收到的二进制序列数(包括信息码和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+x 2+x+1 以上是摘录的一段介绍,是不是觉得很玄?我第一次看也是觉得很晕,后来查询了一些规约和协议的实现资料以后,才恍然大悟。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

海明码和CRC校验的C语言实现1.海明码//code by zxf 2010.4.10#include <stdio.h>#include <conio.h>#include <math.h>//N代表待编码数据的上限位数#define N 100int HmLength(int k);//计算海明码校验位位数void InCode(char *data,char *c,int k,int r);//计算海明码每个校验位的数值void main(){int k=0,r=0,dnum=0,cnum=0;char data[N];char c[N];clrscr();printf("Now please input the data you want to Incode:");for(k=0;k<N;k++)//循环输入待编码数据并记录数据长度,遇到非'1'非'0'输入结束输入{data[k]=getche();if(data[k]!='0'&&data[k]!='1'){break;}}printf("\n__________________________________________________________\n");r=HmLength(k);//求取校验位数printf("k=%d r=%d The length of Hamming code=%d\n",k,r,r+k);//输出海明码相关位数信息InCode(data,c,k,r);//计算海明码printf("The Hamming code is:");for(int j=1;j<r+k+1;j++)//组合输出数据和校验码{if(j==(int)pow(2,cnum)){printf("%c",c[cnum]);cnum++;}else{printf("%c",data[dnum]);dnum++;}}getch();}/**@func:计算校验码*@param:data 待编码数据,c 校验码,k 数据长度,r 校验码位数*code by zxf*/void InCode(char *data,char *c,int k,int r){for(int i=0;i<r;i++)//循环计算第i位校验位{int sum=0,dnum=0,cnum=0;for(int j=1;j<r+k+1;j++)//计算海明码和矩阵第r-i列的乘积{if(j==(int)pow(2,cnum))//去掉矩阵的全零行{cnum++;//记录校验码循环位数}else{int x=0,y=0;x=pow(2,i);y=j%(x*2);x=y/x;//通过取余取商计算获取矩阵第r-i列第j行元素的值sum+=data[dnum]*x;//累加乘积dnum++;//记录数据的循环位数}}c[i]=sum%2==0?'0':'1';//通过结果的奇偶设置校验位的值}}/**@func:计算校验码的位数*@param: k 数据长度*@return: 校验码位数*code by zxf*/int HmLength(int k){int r=0,flag=1;while (flag!=0)//循环到2^r-1>=r+K时即得到校验码的位数{int temp=0;temp=pow(2,r);temp=temp-1;flag=(temp-r-k<0);r++;}return r-1;}程序演示:计算1100计算1000001计算10101010101010101010101010101010101010CRC校验//code by zxf 2010.4.10#include <stdio.h>#include <conio.h>#include <string.h>//N代表待编码数据的上限位数#define N 100void InputBinary(char *data);//输入二进制int DelZero(char *data);//去掉二进制字符串前面的零位int Div(char *data,char *div);//进行一次模2除法void main(){char datacpy[N];char data[N];char div[N];char res[N];int reslen=0;clrscr();printf("now please input the data:");InputBinary(data);//输入Mprintf("\nnow please input the div:");InputBinary(div);//输入除数DelZero(data);DelZero(div);//取得有效的M和除数strcpy(datacpy,data);//备份Mprintf("\nThe effective data is:%s",data);printf("\nThe effective div is:%s",div);for(int i=0;i<strlen(div)-1;i++)//得到2^nM{data[strlen(data)]='0';}data[strlen(data)]='\0';res[reslen]='0';while (Div(data,div))//进行模2除法{int i=DelZero(data);res[reslen]='1';//记录商reslen++;if(strlen(data)>=strlen(div))//记录零商{for(int j=0;j<i;j++){res[reslen]='0';reslen++;}}}res[reslen]='\0';while(strlen(data)<strlen(div)-1)//若FCS位数不足n则进行补零操作{for(int i=strlen(data);i>0;i--){data[i]=data[i-1];}data[0]='0';}//输出结果printf("\n_______________________________________________________________");printf("\nThe div result is:%s",res);printf("\nThe FCS is:%s",data);printf("\nThe data wish FCS is:%s%s",datacpy,data);getch();}/**@func:二进制输入*@param:data 用于存储输入数据的字符串*code by zxf*/void InputBinary(char *data){for(int i=0;i<N;i++)//循环输入待编码数据,遇到非'1'非'0'输入结束输入{data[i]=getche();if(data[i]!='0'&&data[i]!='1'){data[i]='\0';break;}}}/**@func:删除二进制串的起始'0'*@param:data 待处理字符串*@return:返回删除零的个数-1*code by zxf*/int DelZero(char *data){int res=-1;while(data[0]=='0')//如果data第一位为'0'继续前移字符串{for(int i=0;i<strlen(data);i++)//前移字符串{data[i]=data[i+1];}res++;}return res;}/**@func:进行一次模2除法*@param:data 被除数, div 除数*@return:返回0:被除数小于除数,返回1:成功进行了一次模2除法*code by zxf*/int Div(char *data,char *div){int res=0;if(strlen(data)<strlen(div)) ;//被除数小于除数不操作else{for(int i=0;i<strlen(div);i++)//按位进行模2除法{data[i]=data[i]==div[i]?'0':'1';}res=1;}return res;}程序演示:计算101001计算1101011011。

相关文档
最新文档