第20講 自己動手學(xué)習(xí)單片機(jī)系列講座-CRC算法詳解_第1頁
第20講 自己動手學(xué)習(xí)單片機(jī)系列講座-CRC算法詳解_第2頁
第20講 自己動手學(xué)習(xí)單片機(jī)系列講座-CRC算法詳解_第3頁
第20講 自己動手學(xué)習(xí)單片機(jī)系列講座-CRC算法詳解_第4頁
第20講 自己動手學(xué)習(xí)單片機(jī)系列講座-CRC算法詳解_第5頁
已閱讀5頁,還剩82頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第20講CRC算法詳解青島科技大學(xué)王澤本思想發(fā)送端根據(jù)要傳送的m位二進(jìn)制碼序列,以一定的規(guī)則產(chǎn)生校驗(yàn)用的r位CRC碼,并附在信息后邊,構(gòu)成一個新的二進(jìn)制碼序列,共(m+r)位,發(fā)送出去。接收端,將接收到的二進(jìn)制序列數(shù)(m+r位)除以多項(xiàng)式,如果余數(shù)為0,則說明傳輸中無錯誤發(fā)生。用軟件計算CRC碼時,接收方可以將接收到的信息碼求CRC碼,與接收到的CRC碼比較是否相同來判斷傳輸數(shù)據(jù)是否有誤。一CRC基本概念二進(jìn)制數(shù)與多項(xiàng)式任意一個二進(jìn)制數(shù)都對應(yīng)一個多項(xiàng)式例:1011,0001對應(yīng)的多項(xiàng)式為1·x7+0·x6+1·x5+1·x4+0·x3+0·x2+0·x1+1·x0即x7+x5+x4+1生成多項(xiàng)式任一種CRC校驗(yàn)都對應(yīng)著一個生成多項(xiàng)式;生成多項(xiàng)式最高冪次和最低冪次的系數(shù)始終為1。名稱生成多項(xiàng)式16進(jìn)制數(shù)應(yīng)用舉例CRC4x4+x+1ITUG.704CRC8/MAXIMx8+x5+x4+10x31MAXIM芯片CRC16x16+x15+x2+10x8005MODBUSCRC16-ITU*x16+x12+x5+10x1021ISOHDLCCRC32x32+x26+···+x2+x+10x04C11DB7ZIP,RAR,IEEE1394CRC32Cx32+x28+···+x8+x6+10x1EDC6F41SCTP*CRC16-ITU以前稱作CRC16-CITT二CRC算法基本原理CRC的本質(zhì)是模-2除法的余數(shù)。求CRC碼所采用模2加減運(yùn)算法則,即是不帶進(jìn)位和借位的按位加減,這種加減運(yùn)算實(shí)際上是邏輯上的異或運(yùn)算,加法和減法等價;乘法和除法運(yùn)算與普通代數(shù)式的乘除法運(yùn)算是一樣。假定要發(fā)送的二進(jìn)制數(shù)對應(yīng)的多項(xiàng)式為K(x),生成多項(xiàng)式為G(x),最高冪次為r。設(shè)xr·K(x)/G(x)得到的余數(shù)多項(xiàng)式為R(x)。則R(x)對應(yīng)的二進(jìn)制數(shù)即為CRC校驗(yàn)碼,位數(shù)為r位。用數(shù)學(xué)表達(dá)式表示為xr·K(x)=G(x)·Q(x)+R(x)其中Q(x)為得到的整數(shù)商多項(xiàng)式。舉例:采用CRC4校驗(yàn),傳送的信息碼為0101,1001,生成多項(xiàng)式為x4+x+1。解:信息碼0101,1001對應(yīng)多項(xiàng)式為x6+x4+x3+1,乘以x4得x10+x8+x7+x4,對應(yīng)二進(jìn)制10110010000生成多項(xiàng)式x4+x+1對應(yīng)被除數(shù)10011。10011

10110010000

10011

101010000

10011

1100000

10011

101100

100111010101011異或運(yùn)算異或運(yùn)算余數(shù)余數(shù)余數(shù)CRC碼異或運(yùn)算異或運(yùn)算為0不做處理為0不做處理算法特點(diǎn)m位信息碼添加r位0構(gòu)成要處理的碼塊每次處理5位,可設(shè)置一個5位寄存器,初始值為0。信息碼左移一位進(jìn)入REG0檢測寄存器中的最高位REG4為1,將寄存器與10011異或運(yùn)算,為0返回步驟3若沒處理完m+r位,返回步驟3;否則取REG3…0作為CRC碼REG4REG3REG2REG1REG010110010000左移左移缺點(diǎn):算法用到5位寄存器,不方便簡單改進(jìn)m位信息碼添加r位0構(gòu)成要處理的碼塊每次處理4位,可設(shè)置一個4位寄存器,初始值為0。信息碼左移一位進(jìn)入REG0,同時檢測寄存器中的移出位為1,將寄存器與0011異或運(yùn)算,為0返回步驟3若沒處理完m+r位,返回步驟3;否則寄存器內(nèi)容為CRC碼REG3REG2REG1REG010110010000左移左移生成多項(xiàng)式最高位始終為1,可省掉該位左移待檢測的標(biāo)志位crcReg實(shí)際只用4位16位crcReg=0x0000;實(shí)際編程時的考慮

crcReg寄存器為16位,Bit0-7位存儲加載的信息碼字節(jié)crcReg寄存器的Bit7-11用于crc碼,Bit12用于檢測左移出的值為1或0。加載要處理的8位信息碼Bit0Bit7Bit8Bit11Bit9Bit10Bit12/********************simpcrc40.c**************************************/#include<stdio.h>typedefunsignedcharuint8;typedefunsignedshortintuint16;uint8simpCrc4(uint8*p,intn){uint16crcReg=0x0000;//初始值

inti,j;for(i=0;i<n;i++)//信息碼共n個字節(jié)

{crcReg^=p[i];for(j=0;j<8;j++) //處理一個字節(jié)

{crcReg<<=1; //左移一位

if(crcReg&0x1000) //移出的值為1,異或多項(xiàng)式

crcReg^=0x0300;}}注:以上算法得到的CRC值和實(shí)際CRC4算法不相同。因CRC4實(shí)際模型與上述有細(xì)微差別,暫時把這個問題先放一下。for(i=0;i<4;i++) //補(bǔ)4個0,以便處理完最后一個字節(jié)的低四位

{crcReg<<=1;if(crcReg&0x1000)crcReg^=0x0300;}crcReg>>=8; //右移8位

return(crcReg&0x0F);//返回低4位值}intmain(){ uint8crcReg; uint8p[]={0x16,0x32,0xA9}; crcReg=simpCrc4(p,3); printf("0x%x",crcReg); return(0);}運(yùn)行結(jié)果左移待檢測的標(biāo)志位crcReg實(shí)際只用16位32位crcReg=0x00000000;

crcReg寄存器為32位,低8位存儲加載的信息碼字節(jié)crcReg寄存器的Bit8-23用于CRC碼,Bit24位用于檢測左移出的值為1或0。以上算法可擴(kuò)充到其它寬度的CRC碼,以16位CRC碼為例加載要處理的8位信息碼Bit0Bit7Bit8Bit23Bit24···/********************simpcrc160.c******************************/#include<stdio.h>typedefunsignedcharuint8;typedefunsignedshortintuint16;typedefunsignedintuint32;uint16simpCrc16(uint8*p,intn){uint32crcReg=0x00000000;//初始值

inti,j;for(i=0;i<n;i++)//信息碼共n個字節(jié)

{crcReg^=p[i];for(j=0;j<8;j++) //處理一個字節(jié)

{crcReg<<=1; //左移一位

if(crcReg&0x1000000) //移出的值為1,異或多項(xiàng)式

crcReg^=0x102100;}}for(i=0;i<16;i++) //補(bǔ)4個0,以便處理完最后一個字節(jié)的低四位

{crcReg<<=1;if(crcReg&0x1000000)crcReg^=0x102100;}crcReg>>=8; //右移8位

return(crcReg&0xFFFF);//返回低4位值}intmain(){ uint16crcReg; uint8p[]={0x16,0x32,0xA9}; crcReg=simpCrc16(p,3); printf("0x%x",crcReg); return(0);}運(yùn)行結(jié)果注:實(shí)際上此程序計算的是CRC16/XMODEM三CRC寄存器的優(yōu)化處理第二節(jié)介紹的算法優(yōu)缺點(diǎn)分析優(yōu)點(diǎn)算法簡單直觀,同原理直接對應(yīng),易于理解缺點(diǎn)算法開始時,計算了多位無用的初值。算法結(jié)束前,補(bǔ)零運(yùn)算僅僅是為了將最后一個字節(jié)每一位都處理完。CRC寄存器用后8位存放新讀入的信息碼字節(jié);另外用單獨(dú)1位存放移出的位。算法不優(yōu)美,顯得業(yè)余。正常算法(當(dāng)前字節(jié)緊跟下一字節(jié))101011011001第i字節(jié)后四位第i+1字節(jié)(1)移出一位1異或0110

10110101

10110011110

1

0110(2)移出一位0CRC寄存器的優(yōu)化處理10101100001110011100(3)移出一位1異或0101

1001(4)移出一位1,異或001101101001最后結(jié)果優(yōu)化算法當(dāng)前字節(jié)后面補(bǔ)零,處理完一個字節(jié)前4位后,得到的結(jié)果10100000第i字節(jié)后四位(1)移出一位1異或0111

00000100

00000011已處理前四位,后面已補(bǔ)了4個0(2)移出一位01110

0000(3)移出一位1,異或11

00

0000001111

11

0000(4)移出一位1,異或1

0

00

000000111

0

11

000011011001下一字節(jié)XOR移完后四位得到的結(jié)果01101001最后結(jié)果從以上分析看出兩種算法結(jié)果一樣。第二種算法每次處理一個字節(jié),得到的結(jié)果與下一字節(jié)異或去掉前導(dǎo)的無用初值不需要末位補(bǔ)零CRC4寄存器優(yōu)化算法CrcReg00000000前四位有效待處理的信息段每次進(jìn)入一個字節(jié)與crcReg作異或運(yùn)算,然后移位比較移出的位是否為1,若為1,則異或多項(xiàng)式0x30。直到8次移位處理完一字節(jié)。繼續(xù)處理下一字節(jié),直到信息碼所有字節(jié)處理完畢將crcReg0右移4位得到CRC碼。/******************simpcrc41.c*********************************/#include<stdio.h>typedefunsignedcharuint8;uint8simpCrc4(uint8*p,intn){uint8crcReg=0x00;//初始值

inti,j;for(i=0;i<n;i++)//信息碼共n個字節(jié)

{crcReg^=p[i];for(j=0;j<8;j++) //處理一個字節(jié)

{if(crcReg&0x80) //移出的值為1,異或多項(xiàng)式

{ crcReg<<=1; crcReg^=0x30;}else crcReg<<=1; }}crcReg>>=4; //右移4位

return(crcReg&0x0F);//返回低4位值}intmain(){ uint8crcReg; uint8p[]={0x16,0x32,0xA9}; crcReg=simpCrc4(p,3); printf("0x%x",crcReg); return(0);}運(yùn)行結(jié)果注:以上算法得到的CRC值和實(shí)際CRC4算法不相同。因CRC4實(shí)際模型與上述有細(xì)微差別,暫時把這個問題先放一下。CRC16寄存器優(yōu)化算法CrcRegBit7Bit0Bit8Bit15······Bit7Bit0···信息碼字節(jié)XOR待處理的信息段每次進(jìn)入一個字節(jié)左移8位與crcReg作異或運(yùn)算,然后左移1位,若移出位為1,則異或多項(xiàng)式0x1021。直到8次移位處理完一字節(jié)。繼續(xù)處理下一字節(jié),直到信息碼所有字節(jié)處理完畢/****************************simpcrc161.c*******************************/#include<stdio.h>typedefunsignedcharuint8;typedefunsignedshortintuint16;uint16simpCrc16(uint8*p,intn){uint16crcReg=0x0000;//初始值

inti,j;for(i=0;i<n;i++)//信息碼共n個字節(jié)

{crcReg^=p[i]<<8;for(j=0;j<8;j++) //處理一個字節(jié)

{if(crcReg&0x8000) //移出的值為1,異或多項(xiàng)式

{ crcReg<<=1; crcReg^=0x1021;} else crcReg<<=1; }}return(crcReg);//返回}intmain(){ uint16crcReg; uint8p[]={0x16,0x32,0xA9}; crcReg=simpCrc16(p,3); printf("0x%x",crcReg); return(0);}運(yùn)行結(jié)果注:實(shí)際上此程序計算的是CRC16/XMODEM四CRC的參數(shù)模型CRC參數(shù)模型是編寫CRC程序時必須要參考的模型,對CRC16來說,雖然都是16位CRC校驗(yàn),但參數(shù)不同,最后CRC碼也不同,下面是CRC16/XMODEM模型,前幾節(jié)的CRC16程序可直接應(yīng)用于該模型 Name:“CRC16/XMODEM" Width:16 Poly:0x1021 Init:0x0000 RefIn:False RefOut:False XorOut:0x0000 Alias:CRC16/ZMODEM,CRC16/ACORN Use:

Poly:生成多項(xiàng)式的16進(jìn)制數(shù)(省略最高位的1),例如 CRC-4/ITU的生成項(xiàng)為x16+x12+x5+1,對應(yīng)十六 進(jìn),0001,0000,0010,0001,省略最高位的二進(jìn)制 是001,0000,0010,0001,對應(yīng)16進(jìn)制0x1021

Init: CRC寄存器初始化值。CRC參數(shù)模型解釋 Name:CRC名稱 Width:CRC比特數(shù) RefIn 取值TRUE或FALSE。

FALSE,表示信息碼不用“顛倒”;TRUE,表示信 息碼每個字節(jié)都要先“顛倒”。

注:若采用直接算法編程,應(yīng)顛倒后再補(bǔ)r位0 RefOut 取值TRUE或FALSE。 FALSE,表示計算結(jié)束后,寄存器中的值直接進(jìn) 入XOROUT處理即可。TRUE,表示計算結(jié)束 后,寄存器中的值要先“顛倒”,再進(jìn)入XOROUT處 理。注意,這是將整個寄存器的值顛倒,如果只 是對各個字節(jié)各自顛倒,那結(jié)果值就錯誤了。 XorOut 這個值與經(jīng)RefOut后的寄存器的值相XOR,得 到的值就是最終正式的CRC值! Check(可選) 這不是定義值的一部分。是字串“123456789”用該 CRC參數(shù)模型計算得到的CRC值,作為參考。

Use(可選) 這不是模型定義值的一部分。僅僅表示該算法應(yīng) 用在什么地方 對RefIn=False,RefOut=False情況,第三節(jié)的程序很容易規(guī)格化為CRC參數(shù)模型的方式。 先給出這種模型的規(guī)格化算法,常用的有以下兩種CRC8/ITU算法Name:CRC8/ITUWidth:8Poly:0x07Init:0x00RefIn:FalseRefOut:FalseXorOut:0x55CRC16/XMODEM算法Name:CRC16/XMODEMWidth:16Poly:0x1021Init:0x0000RefIn:FalseRefOut:FalseXorOut:0x0000直接CRC左移算法1(字節(jié)不逆序左移,多項(xiàng)式不逆序)設(shè)定crcReg寄存器初始值;取信息碼一字節(jié)(視情況需或不需移位)異或crcReg寄存器;左移1位,若移出位為1,則多項(xiàng)式異或crcReg;若沒處理完一個字節(jié),返回第3步;若還有未處理完的信息字節(jié),返回第2步;得到的crcReg異或XorOut值,得到CRC碼。條件RefIN=False;RefOut=False/*********************simpcrcleft.c*********************************/#include<stdio.h>typedefunsignedcharuint8;typedefunsignedshortintuint16;uint8simpCrc8(uint8*p,intn,uint8poly,uint8initReg,uint8xorOut){uint8crcReg=initReg;//初始值

inti,j;for(i=0;i<n;i++)//信息碼共n個字節(jié)

{crcReg^=p[i]; //不需左移

for(j=0;j<8;j++) //處理一個字節(jié)

{if(crcReg&0x80)//移出的值為1,異或多項(xiàng)式

{ crcReg<<=1; crcReg^=poly;} else crcReg<<=1; }}return(crcReg^xorOut);}uint16simpCrc16(uint8*p,intn,uint16poly,uint16initReg,uint16xorOut){uint16crcReg=initReg;//初始值

inti,j;for(i=0;i<n;i++)//信息碼共n個字節(jié)

{crcReg^=p[i]<<8; //需要左移8位for(j=0;j<8;j++) //處理一個字節(jié)

{if(crcReg&0x8000)//移出的值為1,異或多項(xiàng)式

{ crcReg<<=1; crcReg^=poly;} else crcReg<<=1; }}return(crcReg^xorOut);//返回}intmain(){ uint8crcReg8; uint16crcReg16; uint8p[]={0x16,0x32,0xA9}; crcReg8=simpCrc8(p,3,0x07,0x00,0x00); printf("CRC8\t0x%x\n",crcReg8); crcReg16=simpCrc16(p,3,0x1021,0x0000,0x0000); printf("CRC16\t0x%x",crcReg16); return(0);}五信息碼字節(jié)逆序CRC算法字節(jié)逆序算法描述字節(jié)y=0x00;x每次左移一位,檢測最高位,若為1,則加上數(shù)組中對應(yīng)的值。最后得到的y即為x的逆序。0x010x020x040x080x100x200x400x80待逆序的字節(jié)xbitVal[8]=例:11000010的逆序?yàn)?1000011字節(jié)逆序若RefIn=TrueRefOut=True,此時需多項(xiàng)式逆序左移,最后結(jié)果逆序,才能得CRC碼兩種逆序算法模型CRC4/ITU算法Name:CRC4/ITUWidth:4Poly:0x03Init:0x00RefIn:TrueRefOut:TrueXorOut:0x00MODBUS通訊協(xié)議中的CRC算法Name:CRC16/ModbusWidth:16Poly:0x8005Init:0xFFFFRefIn:TrueRefOut:TrueXorOut:0x0000CRC4/ITU算法(字節(jié)逆序)CrcReg00000000前四位有效crcReg0設(shè)為8位無符號數(shù)(實(shí)際只有高四位有效);待處理的信息段每次進(jìn)入一個字節(jié)逆序后與crcReg作異或運(yùn)算,然后左移1位,若移出位為1,則異或多項(xiàng)式0x30。直到8次左移當(dāng)前字節(jié)都處理完畢。處理下一個字節(jié),直到信息碼的最后一個字節(jié)將crcReg逆序得到CRC碼。/***********************crc4invert.c**********************/#include<stdio.h>typedefunsignedcharuint8;uint8invertByte(uint8x) //字節(jié)逆序{uint8bitVal[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};uint8y=0x00;inti;for(i=0;i<=7;i++){if(x&0x80)y+=bitVal[i];x<<=1;}return(y);}uint8simpCrc4(uint8*p,intn){uint8crcReg=0x00;

inti,j;for(i=0;i<n;i++){crcReg^=invertByte(p[i]);for(j=0;j<8;j++){if(crcReg&0x80){ crcReg<<=1; crcReg^=0x30;}elsecrcReg<<=1;}}crcReg=invertByte(crcReg);return(crcReg);}intmain(void){uint8x[3]={0x16,0x32,0xA9};uint8crcCode8;crcCode8=simpCrc4(x,3);printf("0x%x\n",crcCode8);return(0);}運(yùn)行結(jié)果注:以上算法得到的CRC值和實(shí)際CRC4算法相同。比較前面CRC4算法可知,僅僅添加字節(jié)逆序和crcReg逆序CRC16/Modbus字節(jié)逆序算法CrcRegBit7Bit0Bit8Bit15······Bit7Bit0···逆序的信息碼字節(jié)XOR待處理的信息段每次進(jìn)入一個字節(jié)逆序后左移8位與crcReg作異或運(yùn)算。然后左移1位,若移出位為1,則異或多項(xiàng)式0x30。直到8次左移當(dāng)前字節(jié)都處理完畢。處理下一個字節(jié),直到信息碼的最后一個字節(jié)將crcReg逆序得到CRC碼。/*********************crc16invert.c**************************/#include<stdio.h>typedefunsignedcharuint8;typedefunsignedshortintuint16;uint8invertByte(uint8x){uint8bitVal[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};uint8y=0x00;inti;for(i=0;i<=7;i++){if(x&0x80)y+=bitVal[i];x<<=1;}return(y);}uint16invertWord(uint16x){uint16bitVal[16]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};uint16y=0x0000;inti;for(i=0;i<=15;i++){if(x&0x8000)y+=bitVal[i];x<<=1;}return(y);}uint16simpCrc16(unsignedchar*p,intn){uint16crcReg=0xFFFF;inti,j;for(i=0;i<n;i++){crcReg^=invertByte(p[i])<<8;for(j=0;j<8;j++){ if(crcReg&0x8000) { crcReg<<=1; crcReg^=0x8005; } else crcReg<<=1;}}return(invertWord(crcReg));}intmain(void){uint8x[3]={0x16,0x32,0xA9};uint16crcCode16;crcCode16=simpCrc16(x,3);printf("0x%x\n",crcCode16);return(0);}運(yùn)行結(jié)果缺點(diǎn)分析信息碼逆序算法每個字節(jié)逆序,算法開銷大。計算得到最后結(jié)果需要再次逆序得到CRC碼??疾熳止?jié)不逆序,多項(xiàng)式逆序。字節(jié)左移改為右移,若移出為為1,異或逆序多項(xiàng)式。六信息碼逆序算法優(yōu)化不需要信息字節(jié)的逆序和最后結(jié)果的逆序;僅僅了逆序多項(xiàng)式;由于多項(xiàng)式是固定的,逆序一次即可。減小了逆序所需要的開銷。設(shè)信息碼的一字節(jié)為 10010101字節(jié)逆序左移算法10101001

001101100010011101110011010000111100

10010101110010001101100111011100001011000011多項(xiàng)式逆序字節(jié)右移算法鏡像逆序得CRC碼直接CRC算法2(多項(xiàng)式逆序,字節(jié)不逆序右移)設(shè)定crcReg寄存器初始值;取信息碼一字節(jié)異或crcReg寄存器;右移1位,若移出位為1,則逆序多項(xiàng)式異或crcReg;若沒處理完一個字節(jié),返回第3步;若還有未處理完的信息字節(jié),返回第2步;得到的crcReg異或XorOut值,得到CRC碼。條件RefIN=True;RefOut=True/**********************crc4right.c*******************************************/#include<stdio.h>typedefunsignedcharuint8;uint8simpCrc4R(uint8*p,intn,uint8poly,uint8initReg,uint8xorOut){inti,j;uint8crcReg=initReg;for(i=0;i<n;i++){crcReg^=p[i];for(j=0;j<8;j++){if(crcReg&0x0001){ crcReg>>=1; crcReg^=poly;//}else crcReg>>=1;}}return(crcReg^xorOut);}intmain(void){uint8x[3]={0x16,0x32,0xA9};uint8crcCode8;crcCode8=simpCrc4R(x,3,0x0C,0x00,0x00);//多項(xiàng)式逆序0x0cprintf("HEX%x\n",crcCode8);return(0);}運(yùn)行結(jié)果CRC16/Modbus通訊協(xié)議所用的算法描述Name:CRC16/ModbusWidth:16Poly:0x8005Init:0xFFFFRefIn:TrueRefOut:TrueXorOut:0x0000從描述看和CRC4ITU算法基本一樣,除了初始值為0xFFFF之外,因此算法在CRC4基礎(chǔ)上稍加修改即可。#include<stdio.h>typedefunsignedcharuint8;typedefunsignedshortintuint16;uint16simpCrc16R(uint8*p,intn,uint16poly,uint16initReg,uint16xorOut){inti,j;uint16crcReg=initReg;for(i=0;i<n;i++){crcReg^=p[i];for(j=0;j<8;j++){if(crcReg&0x0001){ crcReg>>=1; crcReg^=poly;}else crcReg>>=1;}}return(crcReg^xorOut);}intmain(void){uint8x[3]={0x16,0x32,0xA9};uint16crcCode16;

//多項(xiàng)式逆序0xA001crcCode16=simpCrc16R(x,3,0xA001,0xFFFF,0x0000);printf("0x%x\n",crcCode16);return(0);}運(yùn)行結(jié)果查詢表CRC算法原理直接CRC算法1和2的開銷分析無論CRC4,CRC8,CRC16還是CRC32,都需要兩重循環(huán)。第一重循環(huán)從信息碼中加載一字節(jié)數(shù)據(jù)。第二重循環(huán)進(jìn)行8次移位處理這一字節(jié)數(shù)據(jù)。有大量的開銷消耗在每字節(jié)8次移位異或運(yùn)算中。減少算法開銷的總體思路每字節(jié)8位數(shù)據(jù),共256種組合;對應(yīng)256種CRC碼。對字節(jié)數(shù)據(jù)從0-255,預(yù)先計算出對應(yīng)的CRC碼,存儲為一張CRC查詢表。對信息碼每字節(jié)數(shù)據(jù)用查表方法去計算CRC值。前幾節(jié)講的CRC直接算法1和2,都是計算多字節(jié)信息碼的,稍加修改就可計算單字節(jié)數(shù)據(jù)的CRC碼。以生成CRC查詢表crcReg寄存器初始值始設(shè)為0;crcReg寄存器異或要計算的字節(jié)對要計算的8bit數(shù)據(jù)右移1位,若移出位為1,則異或poly。若未處理完8位數(shù)據(jù),返回第3步繼續(xù)返回CRC結(jié)果,不要異或xorOut;生成“右移CRC查詢表”算法/****************************rightcrc4table.c**********************************/#include<stdio.h>typedefunsignedcharuint8;uint8crcTable[256];uint8crc4Byte(uint8mCode){uint8crcReg=0x00;inti;crcReg^=mCode;for(i=0;i<8;i++){if(crcReg&0x01){ crcReg>>=1; crcReg^=0x0C;}CRC4/ITU右移查詢表else crcReg>>=1;}return(crcReg);}voidcrc4Table(void){

uint8mCode=0x00; intk; for(k=0x00;k<=0xFF;k++) { crcTable[k]=crc4Byte(mCode); mCode++; }}intmain(void){ inti; FILE*fp=fopen("crc4table.txt","w"); crc4Table(); for(i=0;i<=255;i++) { if(0==i%16&&0!=i) { fprintf(fp,"\n\r",crcTable[i]); } fprintf(fp,"0x%x",crcTable[i]); if(255!=i) fprintf(fp,","); } fclose(fp); return(0);}CRC4查詢表0x0,0x7,0xe,0x9,0x5,0x2,0xb,0xc,0xa,0xd,0x4,0x3,0xf,0x8,0x1,0x6,0xd,0xa,0x3,0x4,0x8,0xf,0x6,0x1,0x7,0x0,0x9,0xe,0x2,0x5,0xc,0xb,0x3,0x4,0xd,0xa,0x6,0x1,0x8,0xf,0x9,0xe,0x7,0x0,0xc,0xb,0x2,0x5,0xe,0x9,0x0,0x7,0xb,0xc,0x5,0x2,0x4,0x3,0xa,0xd,0x1,0x6,0xf,0x8,0x6,0x1,0x8,0xf,0x3,0x4,0xd,0xa,0xc,0xb,0x2,0x5,0x9,0xe,0x7,0x0,0xb,0xc,0x5,0x2,0xe,0x9,0x0,0x7,0x1,0x6,0xf,0x8,0x4,0x3,0xa,0xd,0x5,0x2,0xb,0xc,0x0,0x7,0xe,0x9,0xf,0x8,0x1,0x6,0xa,0xd,0x4,0x3,0x8,0xf,0x6,0x1,0xd,0xa,0x3,0x4,0x2,0x5,0xc,0xb,0x7,0x0,0x9,0xe,0xc,0xb,0x2,0x5,0x9,0xe,0x7,0x0,0x6,0x1,0x8,0xf,0x3,0x4,0xd,0xa,0x1,0x6,0xf,0x8,0x4,0x3,0xa,0xd,0xb,0xc,0x5,0x2,0xe,0x9,0x0,0x7,0xf,0x8,0x1,0x6,0xa,0xd,0x4,0x3,0x5,0x2,0xb,0xc,0x0,0x7,0xe,0x9,0x2,0x5,0xc,0xb,0x7,0x0,0x9,0xe,0x8,0xf,0x6,0x1,0xd,0xa,0x3,0x4,0xa,0xd,0x4,0x3,0xf,0x8,0x1,0x6,0x0,0x7,0xe,0x9,0x5,0x2,0xb,0xc,0x7,0x0,0x9,0xe,0x2,0x5,0xc,0xb,0xd,0xa,0x3,0x4,0x8,0xf,0x6,0x1,0x9,0xe,0x7,0x0,0xc,0xb,0x2,0x5,0x3,0x4,0xd,0xa,0x6,0x1,0x8,0xf,0x4,0x3,0xa,0xd,0x1,0x6,0xf,0x8,0xe,0x9,0x0,0x7,0xb,0xc,0x5,0x2/*******************************rightcrc16table.c*********************/#include<stdio.h>typedefunsignedcharuint8;typedefunsignedshortintuint16;uint16crcTable[256];uint16crc16Byte(uint8mCode,uint16poly){uint16crcReg=0x0000;inti;crcReg^=mCode;for(i=0;i<8;i++){if(crcReg&0x0001){ crcReg>>=1; crcReg^=poly;}CRC16/MODBUS右移查詢表 else crcReg>>=1;}return(crcReg);}voidcrc16Table(void){ uint8mCode=0x00; intk; for(k=0x00;k<=0xFF;k++) { crcTable[k]=crc16Byte(mCode,0xA001); mCode++; }}intmain(void){ inti; uint8p[]={0x16,0x32,0xA9}; FILE*fp=fopen("crc16table.txt","w"); crc16Table(); for(i=0;i<=255;i++) { if(0==i%8&&0!=i) { fprintf(fp,"\n\r",crcTable[i]); } fprintf(fp,"0x%x\t",crcTable[i]); if(255!=i) fprintf(fp,","); } fclose(fp); return(0);}0x0 ,0xc0c1 ,0xc181 ,0x140 ,0xc301 ,0x3c0 ,0x280 ,0xc241 ,0xc601 ,0x6c0 ,0x780 ,0xc741 ,0x500 ,0xc5c1 ,0xc481 ,0x440 ,0xcc01 ,0xcc0 ,0xd80 ,0xcd41 ,0xf00 ,0xcfc1 ,0xce81 ,0xe40 ,0xa00 ,0xcac1 ,0xcb81 ,0xb40 ,0xc901 ,0x9c0 ,0x880 ,0xc841 ,0xd801 ,0x18c0 ,0x1980 ,0xd941 ,0x1b00 ,0xdbc1 ,0xda81 ,0x1a40 ,0x1e00 ,0xdec1 ,0xdf81 ,0x1f40 ,0xdd01 ,0x1dc0 ,0x1c80 ,0xdc41 ,0x1400 ,0xd4c1 ,0xd581 ,0x1540 ,0xd701 ,0x17c0 ,0x1680 ,0xd641 ,0xd201 ,0x12c0 ,0x1380 ,0xd341 ,0x1100 ,0xd1c1 ,0xd081 ,0x1040 ,0xf001 ,0x30c0 ,0x3180 ,0xf141 ,0x3300 ,0xf3c1 ,0xf281 ,0x3240 ,0x3600 ,0xf6c1 ,0xf781 ,0x3740 ,0xf501 ,0x35c0 ,0x3480 ,0xf441 ,0x3c00 ,0xfcc1 ,0xfd81 ,0x3d40 ,0xff01 ,0x3fc0 ,0x3e80 ,0xfe41 ,0xfa01 ,0x3ac0 ,0x3b80 ,0xfb41 ,0x3900 ,0xf9c1 ,0xf881 ,0x3840 ,0x2800 ,0xe8c1 ,0xe981 ,0x2940 ,0xeb01 ,0x2bc0 ,0x2a80 ,0xea41 ,0xee01 ,0x2ec0 ,0x2f80 ,0xef41 ,0x2d00 ,0xedc1 ,0xec81 ,0x2c40 ,0xe401 ,0x24c0 ,0x2580 ,0xe541 ,0x2700 ,0xe7c1 ,0xe681 ,0x2640 ,CRC16/modbus查詢表0x2200 ,0xe2c1 ,0xe381 ,0x2340 ,0xe101 ,0x21c0 ,0x2080 ,0xe041 ,0xa001 ,0x60c0 ,0x6180 ,0xa141 ,0x6300 ,0xa3c1 ,0xa281 ,0x6240 ,0x6600 ,0xa6c1 ,0xa781 ,0x6740 ,0xa501 ,0x65c0 ,0x6480 ,0xa441 ,0x6c00 ,0xacc1 ,0xad81 ,0x6d40 ,0xaf01 ,0x6fc0 ,0x6e80 ,0xae41 ,0xaa01 ,0x6ac0 ,0x6b80 ,0xab41 ,0x6900 ,0xa9c1 ,0xa881 ,0x6840 ,0x7800 ,0xb8c1 ,0xb981 ,0x7940 ,0xbb01 ,0x7bc0 ,0x7a80 ,0xba41 ,0xbe01 ,0x7ec0 ,0x7f80 ,0xbf41 ,0x7d00 ,0xbdc1 ,0xbc81 ,0x7c40 ,0xb401 ,0x74c0 ,0x7580 ,0xb541 ,0x7700 ,0xb7c1 ,0xb681 ,0x7640 ,0x7200 ,0xb2c1 ,0xb381 ,0x7340 ,0xb101 ,0x71c0 ,0x7080 ,0xb041 ,0x5000 ,0x90c1 ,0x9181 ,0x5140 ,0x9301 ,0x53c0 ,0x5280 ,0x9241 ,0x9601 ,0x56c0 ,0x5780 ,0x9741 ,0x5500 ,0x95c1 ,0x9481 ,0x5440 ,0x9c01 ,0x5cc0 ,0x5d80 ,0x9d41 ,0x5f00 ,0x9fc1 ,0x9e81 ,0x5e40 ,0x5a00 ,0x9ac1 ,0x9b8

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論