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得到的!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.