這裡,不討論crc的糾錯原理以及為什麼要選下面提及的生成多項式,只是針對以下的生成多項式,如何獲得crc校驗碼,作乙個比較詳細的說明。
標準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+×256^(n-1)+...+byte[1]×256×256^2/g17+byte[0]×256^2/g17
=z[n]×256^n+×256^(n-1)+...+byte[1]×256×256^2/g17+byte[0]×256^2/g17
=z[n]×256^n+×256^(n-1)+...+byte[1]×256×256^2/g17+byte[0]×256^2/g17
這樣就推導出,byte[n-1]位元組的crc校驗碼為,即上一位元組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]。
位元組型演算法如下:
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
return crc_16;
}void mk_crctable(unsigned short genpoly)
//函式功能:生成0-255對應的16crc校驗碼,其實就是計算機演算法1(位元型演算法)
//genpoly為生成多項式
//注意,低位先傳送時,生成多項式應反轉(低位與高位互換)。如crc16-ccitt為0x1021,反轉後為0x8408
crctable_16[k] = crc_16;}}
查表法計算CRC
查表法 crc檢驗碼的計算過程 1 將上次計算出的crc校驗碼右移乙個位元組 2 將移出的這個位元組與新的要校驗的位元組進行xor 運算 3 用運算出的值在預先生成碼表中進行索引,獲取對應的值 稱為余式 4 用獲取的值與第 1 步右移後的值進行xor 運算 5 如果要校驗的資料已經處理完,則第 4 ...
arctan查表法 查表法
查表法是將一些事先計算好的結果,儲存在常量陣列中,執行時節省計算開銷。例如,計算位元組中位1的個數,int countbits unsigned char dat static char nbittab 256 return nbittab dat 或將位元組按位逆序,unsigned char r...
CRC校驗之查表法C語言實現
本文主要參考 實現查表法快速計算crc7.crc7應用在sd mmc的資料校驗,生成多項式x 7 x 3 1,生成的校驗值為7bit.很容易想到資料以 1byte 為單位進行計算比較方便.c語言 實現 include include includeusing namespace std const ...