




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第20講CRC算法詳解青島科技大學王澤本思想發(fā)送端根據(jù)要傳送的m位二進制碼序列,以一定的規(guī)則產(chǎn)生校驗用的r位CRC碼,并附在信息后邊,構成一個新的二進制碼序列,共(m+r)位,發(fā)送出去。接收端,將接收到的二進制序列數(shù)(m+r位)除以多項式,如果余數(shù)為0,則說明傳輸中無錯誤發(fā)生。用軟件計算CRC碼時,接收方可以將接收到的信息碼求CRC碼,與接收到的CRC碼比較是否相同來判斷傳輸數(shù)據(jù)是否有誤。一CRC基本概念二進制數(shù)與多項式任意一個二進制數(shù)都對應一個多項式例:1011,0001對應的多項式為1·x7+0·x6+1·x5+1·x4+0·x3+0·x2+0·x1+1·x0即x7+x5+x4+1生成多項式任一種CRC校驗都對應著一個生成多項式;生成多項式最高冪次和最低冪次的系數(shù)始終為1。名稱生成多項式16進制數(shù)應用舉例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的本質是模-2除法的余數(shù)。求CRC碼所采用模2加減運算法則,即是不帶進位和借位的按位加減,這種加減運算實際上是邏輯上的異或運算,加法和減法等價;乘法和除法運算與普通代數(shù)式的乘除法運算是一樣。假定要發(fā)送的二進制數(shù)對應的多項式為K(x),生成多項式為G(x),最高冪次為r。設xr·K(x)/G(x)得到的余數(shù)多項式為R(x)。則R(x)對應的二進制數(shù)即為CRC校驗碼,位數(shù)為r位。用數(shù)學表達式表示為xr·K(x)=G(x)·Q(x)+R(x)其中Q(x)為得到的整數(shù)商多項式。舉例:采用CRC4校驗,傳送的信息碼為0101,1001,生成多項式為x4+x+1。解:信息碼0101,1001對應多項式為x6+x4+x3+1,乘以x4得x10+x8+x7+x4,對應二進制10110010000生成多項式x4+x+1對應被除數(shù)10011。10011
10110010000
10011
101010000
10011
1100000
10011
101100
100111010101011異或運算異或運算余數(shù)余數(shù)余數(shù)CRC碼異或運算異或運算為0不做處理為0不做處理算法特點m位信息碼添加r位0構成要處理的碼塊每次處理5位,可設置一個5位寄存器,初始值為0。信息碼左移一位進入REG0檢測寄存器中的最高位REG4為1,將寄存器與10011異或運算,為0返回步驟3若沒處理完m+r位,返回步驟3;否則取REG3…0作為CRC碼REG4REG3REG2REG1REG010110010000左移左移缺點:算法用到5位寄存器,不方便簡單改進m位信息碼添加r位0構成要處理的碼塊每次處理4位,可設置一個4位寄存器,初始值為0。信息碼左移一位進入REG0,同時檢測寄存器中的移出位為1,將寄存器與0011異或運算,為0返回步驟3若沒處理完m+r位,返回步驟3;否則寄存器內(nèi)容為CRC碼REG3REG2REG1REG010110010000左移左移生成多項式最高位始終為1,可省掉該位左移待檢測的標志位crcReg實際只用4位16位crcReg=0x0000;實際編程時的考慮
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,異或多項式
crcReg^=0x0300;}}注:以上算法得到的CRC值和實際CRC4算法不相同。因CRC4實際模型與上述有細微差別,暫時把這個問題先放一下。for(i=0;i<4;i++) //補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);}運行結果左移待檢測的標志位crcReg實際只用16位32位crcReg=0x00000000;
crcReg寄存器為32位,低8位存儲加載的信息碼字節(jié)crcReg寄存器的Bit8-23用于CRC碼,Bit24位用于檢測左移出的值為1或0。以上算法可擴充到其它寬度的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,異或多項式
crcReg^=0x102100;}}for(i=0;i<16;i++) //補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);}運行結果注:實際上此程序計算的是CRC16/XMODEM三CRC寄存器的優(yōu)化處理第二節(jié)介紹的算法優(yōu)缺點分析優(yōu)點算法簡單直觀,同原理直接對應,易于理解缺點算法開始時,計算了多位無用的初值。算法結束前,補零運算僅僅是為了將最后一個字節(jié)每一位都處理完。CRC寄存器用后8位存放新讀入的信息碼字節(jié);另外用單獨1位存放移出的位。算法不優(yōu)美,顯得業(yè)余。正常算法(當前字節(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最后結果優(yōu)化算法當前字節(jié)后面補零,處理完一個字節(jié)前4位后,得到的結果10100000第i字節(jié)后四位(1)移出一位1異或0111
00000100
00000011已處理前四位,后面已補了4個0(2)移出一位01110
0000(3)移出一位1,異或11
00
0000001111
11
0000(4)移出一位1,異或1
0
00
000000111
0
11
000011011001下一字節(jié)XOR移完后四位得到的結果01101001最后結果從以上分析看出兩種算法結果一樣。第二種算法每次處理一個字節(jié),得到的結果與下一字節(jié)異或去掉前導的無用初值不需要末位補零CRC4寄存器優(yōu)化算法CrcReg00000000前四位有效待處理的信息段每次進入一個字節(jié)與crcReg作異或運算,然后移位比較移出的位是否為1,若為1,則異或多項式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,異或多項式
{ 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);}運行結果注:以上算法得到的CRC值和實際CRC4算法不相同。因CRC4實際模型與上述有細微差別,暫時把這個問題先放一下。CRC16寄存器優(yōu)化算法CrcRegBit7Bit0Bit8Bit15······Bit7Bit0···信息碼字節(jié)XOR待處理的信息段每次進入一個字節(jié)左移8位與crcReg作異或運算,然后左移1位,若移出位為1,則異或多項式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,異或多項式
{ 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);}運行結果注:實際上此程序計算的是CRC16/XMODEM四CRC的參數(shù)模型CRC參數(shù)模型是編寫CRC程序時必須要參考的模型,對CRC16來說,雖然都是16位CRC校驗,但參數(shù)不同,最后CRC碼也不同,下面是CRC16/XMODEM模型,前幾節(jié)的CRC16程序可直接應用于該模型 Name:“CRC16/XMODEM" Width:16 Poly:0x1021 Init:0x0000 RefIn:False RefOut:False XorOut:0x0000 Alias:CRC16/ZMODEM,CRC16/ACORN Use:
Poly:生成多項式的16進制數(shù)(省略最高位的1),例如 CRC-4/ITU的生成項為x16+x12+x5+1,對應十六 進,0001,0000,0010,0001,省略最高位的二進制 是001,0000,0010,0001,對應16進制0x1021
Init: CRC寄存器初始化值。CRC參數(shù)模型解釋 Name:CRC名稱 Width:CRC比特數(shù) RefIn 取值TRUE或FALSE。
FALSE,表示信息碼不用“顛倒”;TRUE,表示信 息碼每個字節(jié)都要先“顛倒”。
注:若采用直接算法編程,應顛倒后再補r位0 RefOut 取值TRUE或FALSE。 FALSE,表示計算結束后,寄存器中的值直接進 入XOROUT處理即可。TRUE,表示計算結束 后,寄存器中的值要先“顛倒”,再進入XOROUT處 理。注意,這是將整個寄存器的值顛倒,如果只 是對各個字節(jié)各自顛倒,那結果值就錯誤了。 XorOut 這個值與經(jīng)RefOut后的寄存器的值相XOR,得 到的值就是最終正式的CRC值! Check(可選) 這不是定義值的一部分。是字串“123456789”用該 CRC參數(shù)模型計算得到的CRC值,作為參考。
Use(可選) 這不是模型定義值的一部分。僅僅表示該算法應 用在什么地方 對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é)不逆序左移,多項式不逆序)設定crcReg寄存器初始值;取信息碼一字節(jié)(視情況需或不需移位)異或crcReg寄存器;左移1位,若移出位為1,則多項式異或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,異或多項式
{ 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,異或多項式
{ 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即為x的逆序。0x010x020x040x080x100x200x400x80待逆序的字節(jié)xbitVal[8]=例:11000010的逆序為01000011字節(jié)逆序若RefIn=TrueRefOut=True,此時需多項式逆序左移,最后結果逆序,才能得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設為8位無符號數(shù)(實際只有高四位有效);待處理的信息段每次進入一個字節(jié)逆序后與crcReg作異或運算,然后左移1位,若移出位為1,則異或多項式0x30。直到8次左移當前字節(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);}運行結果注:以上算法得到的CRC值和實際CRC4算法相同。比較前面CRC4算法可知,僅僅添加字節(jié)逆序和crcReg逆序CRC16/Modbus字節(jié)逆序算法CrcRegBit7Bit0Bit8Bit15······Bit7Bit0···逆序的信息碼字節(jié)XOR待處理的信息段每次進入一個字節(jié)逆序后左移8位與crcReg作異或運算。然后左移1位,若移出位為1,則異或多項式0x30。直到8次左移當前字節(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);}運行結果缺點分析信息碼逆序算法每個字節(jié)逆序,算法開銷大。計算得到最后結果需要再次逆序得到CRC碼。考察字節(jié)不逆序,多項式逆序。字節(jié)左移改為右移,若移出為為1,異或逆序多項式。六信息碼逆序算法優(yōu)化不需要信息字節(jié)的逆序和最后結果的逆序;僅僅了逆序多項式;由于多項式是固定的,逆序一次即可。減小了逆序所需要的開銷。設信息碼的一字節(jié)為 10010101字節(jié)逆序左移算法10101001
001101100010011101110011010000111100
10010101110010001101100111011100001011000011多項式逆序字節(jié)右移算法鏡像逆序得CRC碼直接CRC算法2(多項式逆序,字節(jié)不逆序右移)設定crcReg寄存器初始值;取信息碼一字節(jié)異或crcReg寄存器;右移1位,若移出位為1,則逆序多項式異或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);//多項式逆序0x0cprintf("HEX%x\n",crcCode8);return(0);}運行結果CRC16/Modbus通訊協(xié)議所用的算法描述Name:CRC16/ModbusWidth:16Poly:0x8005Init:0xFFFFRefIn:TrueRefOut:TrueXorOut:0x0000從描述看和CRC4ITU算法基本一樣,除了初始值為0xFFFF之外,因此算法在CRC4基礎上稍加修改即可。#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;
//多項式逆序0xA001crcCode16=simpCrc16R(x,3,0xA001,0xFFFF,0x0000);printf("0x%x\n",crcCode16);return(0);}運行結果查詢表CRC算法原理直接CRC算法1和2的開銷分析無論CRC4,CRC8,CRC16還是CRC32,都需要兩重循環(huán)。第一重循環(huán)從信息碼中加載一字節(jié)數(shù)據(jù)。第二重循環(huán)進行8次移位處理這一字節(jié)數(shù)據(jù)。有大量的開銷消耗在每字節(jié)8次移位異或運算中。減少算法開銷的總體思路每字節(jié)8位數(shù)據(jù),共256種組合;對應256種CRC碼。對字節(jié)數(shù)據(jù)從0-255,預先計算出對應的CRC碼,存儲為一張CRC查詢表。對信息碼每字節(jié)數(shù)據(jù)用查表方法去計算CRC值。前幾節(jié)講的CRC直接算法1和2,都是計算多字節(jié)信息碼的,稍加修改就可計算單字節(jié)數(shù)據(jù)的CRC碼。以生成CRC查詢表crcReg寄存器初始值始設為0;crcReg寄存器異或要計算的字節(jié)對要計算的8bit數(shù)據(jù)右移1位,若移出位為1,則異或poly。若未處理完8位數(shù)據(jù),返回第3步繼續(xù)返回CRC結果,不要異或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)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025汽車銷售合同常用范本
- 施工技術裝飾工程題單選題100道及答案
- 工圖網(wǎng)公文寫作培訓
- 護理心理導圖模板
- 2025年伊春貨運從業(yè)資格證模擬考試下載安裝
- 妊娠合并先天性主動脈口狹窄的健康宣教
- 突聾的護理查房
- 老年人心理護理和溝通技巧
- 模板工技能培訓大綱
- 2025與勞務合同范本
- 2025年上海浦東新區(qū)高三二模高考語文試卷試題(含答案)
- 浙江國企招聘2025寧波樞智交通科技有限公司招聘21人筆試參考題庫附帶答案詳解
- 廣東省清遠市清新區(qū)2025年中考一模語文試題(含答案)
- 2024年廣州市天河區(qū)總工會招聘工會社會工作者考試真題
- 2025餐飲服務承包經(jīng)營合同書
- 湖北省漢陽一中、江夏一中、洪山高中2024-2025學年高一下學期3月聯(lián)考化學試卷 含解析
- 護理安全與護理質量管理課件
- 涉密和非涉密計算機保密管理制度
- DB32T 5061.1-2025中小學生健康管理技術規(guī)范 第1部分:心理健康
- 糖尿病酮癥酸中毒患者的護理查房
- 網(wǎng)絡周期竊取演變-洞察分析
評論
0/150
提交評論