CRC校驗字節型算法總結

CRC校驗 crc算法已經有成熟和比較經典的現成代碼可供我們利用。CRC計算可以靠專用的硬件來實現,但是對於低成本的微控制器系統,在沒有硬件支持下實現CRC檢驗,關鍵的問題就是如何通過軟件來完成CRC計算,也就是CRC算法的問題。CRC校驗的基本思想是利用線性編碼理論,在發送端根據要傳送的k位二進制碼序列,以一定的規則產生一個校驗用的監督碼(既CRC碼)r位,並附在信息後邊,構成一個新的二進制碼序列數共(k+r)位,最後發送出去。在接收端,則根據信息碼和CRC碼之間所遵循的規則進行檢驗,以確定傳送中是否出錯。 1.生成多項式。 16位的CRC碼產生的規則是先將要發送的二進制序列數左移16位(既乘以 )後,再除以一個多項式,最後所得到的餘數既是CRC碼。任意一個由二進制位串組成的代碼都可以和一個係數僅爲‘0’和‘1’取值的多項式一一對應。例如:代碼1010111對應的多項式爲x6+x4+x2+x+1,而多項式爲x5+x3+x2+x+1對應的代碼101111。 標準CRC生成多項式如下表: 名稱 生成多項式 簡記式* 標準引用 CRC-4 x4+x+1 3 ITU G.704 CRC-8 x8+x5+x4+1 0x31 CRC-8 x8+x2+x1+1 0x07 CRC-8 x8+x6+x4+x3+x2+x1 0x5E CRC-12 x12+x11+x3+x+1 80F CRC-16 x16+x15+x2+1 8005 IBM SDLC CRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS CRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS CRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP //葉子:這裏不知道問什麼省略了,有些迷惑哦。要是生成多項式要是都省了,那還怎麼校驗?我猜想可能是中間的全爲一吧。 生成多項式的最高位固定的1,故在簡記式中忽略最高位1了,如0x1021實際是0x11021。 I、基本算法(人工筆算): 以CRC16-CCITT爲例進行說明,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]。 III、計算機算法2(字節型算法):256^n表示256的n次方 把按字節排列的數據流表示成數學多項式,設數據流爲BYTE[n]BYTE[n-1]BYTE[n-2]、、、BYTE[1]BYTE[0],表示成數學表達式爲BYTE[n]×256^n+BYTE[n-1]×256^(n-1) +...+BYTE[1]*256+BYTE[0],在這裏+表示爲異或運算。設生成多項式爲G17(17bit),CRC碼爲CRC16。 則,CRC16=(BYTE[n]×256^n+BYTE[n-1]×256^(n-1)+...+BYTE[1]×256+BYTE[0])×256^2/G17,即數據流左移16位,再除以生成多項式G17。 先變換BYTE[n-1]、BYTE[n-1]擴大後的形式, CRC16=BYTE[n]×256^n×256^2/G17+BYTE[n-1]×256^(n-1)×256^2/G17+...+BYTE[1]×256×256^2/G17+BYTE[0]×256^2/G17 =(Z[n]+Y[n]/G17)×256^n+BYTE[n-1]×256^(n-1)×256^2/G17+...+BYTE[1]×256×256^2/G17+BYTE[0]×256^2/G17 =Z[n]×256^n+{Y[n]×256/G17+BYTE[n-1]×256^2/G17}×256^(n-1)+...+BYTE[1]×256×256^2/G17+BYTE[0]×256^2/G17 =Z[n]×256^n+{(YH8[n]×256+YHL[n])×256/G17+BYTE[n-1]×256^2/G17}×256^(n-1)+...+BYTE[1]×256×256^2/G17+BYTE[0]×256^2/G17 =Z[n]×256^n+{YHL[n]×256/G17+(YH8[n]+BYTE[n-1])×256^2/G17}×256^(n-1)+...+BYTE[1]×256×256^2/G17+BYTE[0]×256^2/G17 這樣就推導出,BYTE[n-1]字節的CRC校驗碼爲{YHL[n]×256/G17+(YH8[n]+BYTE[n-1])×256^2/G17},即上一字節CRC校驗碼Y[n]的高8位(YH8[n])與本字節BYTE[n-1]異或, 該結果單獨計算CRC校驗碼(即單字節的16位CRC校驗碼,對單字節可建立表格,預先生成對應的16位CRC校驗碼),所得的CRC校驗碼與上一字節CRC校驗碼Y[n]的低8位(YL8[n]) 乘以256(即左移8位)異或。然後依次逐個字節求出CRC,直到BYTE[0]。 字節型算法的一般描述爲:本字節的CRC碼,等於上一字節CRC碼的低8位左移8位,與上一字節CRC右移8位同本字節異或後所得的CRC碼異或。 字節型算法如下: 1)CRC寄存器組初始化爲全"0"(0x0000)。(注意:CRC寄存器組初始化全爲1時,最後CRC應取反。) 2)CRC寄存器組向左移8位,並保存到CRC寄存器組。 3)原CRC寄存器組高8位(右移8位)與數據字節進行異或運算,得出一個指向值表的索引。 4)索引所指的表值與CRC寄存器組做異或運算。 5)數據指針加1,如果數據沒有全部處理完,則重複步驟2)。 6)得出CRC。 unsigned short GetCrc_16(unsigned char * pData, int nLength) //函數功能:計算數據流* pData的16位CRC校驗碼,數據流長度爲nLength { unsigned short cRc_16 = 0x0000; // 初始化 while(nLength>0) { cRc_16 = (cRc_16 << 8) ^ cRctable_16[((cRc_16>>8) ^ *pData) & 0xff]; //cRctable_16表由函數mK_cRctable生成 nLength--; pData++; } return cRc_16; } void mK_cRctable(unsigned short gEnpoly) //函數功能:生成0-255對應的16CRC校驗碼,其實就是計算機算法1(比特型算法) //gEnpoly爲生成多項式 //注意,低位先傳送時,生成多項式應反轉(低位與高位互換)。如CRC16-CCITT爲0x1021,反轉後爲0x8408 { unsigned short cRc_16=0; unsigned short i,j,k; for(i=0,k=0;i<256;i++,k++) { cRc_16 = i<<8; for(j=8;j>0;j--) { if(cRc_16&0x8000) //反轉時cRc_16&0x0001 cRc_16=(cRc_16<<=1)^gEnpoly; //反轉時cRc_16=(cRc_16>>=1)^gEnpoly else cRc_16<<=1; //反轉時cRc_16>>=1 } cRctable_16[k] = cRc_16; } } 2:CRC碼集選擇的原則 若設碼字長度爲N,信息字段爲K位,校驗字段爲R位(N=K+R),則對於CRC碼集中的任一碼字,存在且僅存在一個R次多項式g(x),使得 V(x)=A(x)g(x)=xRm(x)+r(x); 其中: m(x)爲K次信息多項式, r(x)爲R-1次校驗多項式, g(x)稱爲生成多項式: g(x)=g0+g1x+ g2x2+...+g(R-1)x(R-1)+gRxR 發送方通過指定的g(x)產生CRC碼字,接收方則通過該g(x)來驗證收到的CRC碼字。 3、CRC校驗碼軟件生成方法: 藉助於多項式除法,其餘數爲校驗字段。 例如:信息字段代碼爲: 1011001;對應m(x)=x6+x4+x3+1 假設生成多項式爲:g(x)=x4+x3+1;則對應g(x)的代碼爲: 11001 x4m(x)=x10+x8+x7+x4 對應的代碼記爲:10110010000; 採用多項式除法: 得餘數爲: 1010 (即校驗字段爲:1010) 發送方:發出的傳輸字段爲: 1 0 1 1 0 0 1 1 0 10 信息字段 校驗字段 接收方:使用相同的生成碼進行校驗:接收到的字段/生成碼(二進制除法), 如果能夠除盡,則正確。 以上字節型算法(紅字部分)解讀: 比特型算法較易理解,這裏不做解釋.一般我們應用中更多的是用字節型的算法,而大部字節型算法爲了提高效率是利用查表法實現的,對於查表法,表是如何產生的,有時迷惑,所以在此對字節型查表法推導過程的理解做一個備忘: 由等式一到等式二的推導:Z[n] 和Y[n]分別爲BYTE[N]/G17的商和餘子式,所以可以進行轉換;其它的BYTE暫不變; 由等式二到等式三的推導:由於只關心餘子式,所以可以不理Z[n],對Y[n]與後一字節進行進一步的結合處理,提取256^(n-1); 由等式三到等式四的推導:把Y[n]進一步分解成高低8位Y[n]×256/G17 = (YH8[n]×256+YL8[n])×256/G17; 由等式四到等式五的推導:重新組合得{YHL[n]×256/G17+(YH8[n]+BYTE[n-1])×256^2/G17}; 這樣就推導出,BYTE[n-1]字節的CRC校驗碼爲{YHL[n]×256/G17+(YH8[n]+BYTE[n-1])×256^2/G17},即上一字節CRC校驗碼Y[n]的高8位(YH8[n])與本字節BYTE[n-1]異或,該結果單獨計算CRC校驗碼(即單字節的16位CRC校驗碼,對單字節可建立表格,預先生成對應的16位CRC校驗碼),所得的CRC校驗碼與上一字節CRC校驗碼Y[n]的低8位(YL8[n])乘以256(即左移8位)異或。然後依次逐個字節求出CRC,直到BYTE[0]。 表的生成則是對0~255每個數進行求CRC得到的!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章