日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【嵌入式算法】CRC校验算法

發(fā)布時(shí)間:2023/12/31 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【嵌入式算法】CRC校验算法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

數(shù)據(jù)傳輸過(guò)程中差錯(cuò)不可避免,接收方在收到數(shù)據(jù)后,先對(duì)數(shù)據(jù)的準(zhǔn)確性進(jìn)行校驗(yàn),異常數(shù)據(jù)特殊處理。校驗(yàn)的方式有很多,常見(jiàn)的有CRC循環(huán)冗余校驗(yàn)。CRC算法檢錯(cuò)能力強(qiáng),效率高,是信息通信領(lǐng)域最為普遍的校驗(yàn)方式。CRC校驗(yàn)算法應(yīng)用廣,且實(shí)現(xiàn)算法簡(jiǎn)單,但其背后的涉及的糾錯(cuò)碼的代數(shù)理論,不是一般人可以理解的。所以,在不理解循環(huán)校驗(yàn)原理的基礎(chǔ)上,貿(mào)然分析算法流程是不明智的,根據(jù)源碼倒推實(shí)現(xiàn)流程,也不會(huì)明白為什么要這樣執(zhí)行?一般關(guān)注CRC以應(yīng)用為主,以及為什么都是CRC16算法,得出的結(jié)果卻不同。本文的意圖只是這個(gè)。

1、CRC定義
假設(shè)要發(fā)送996這個(gè)數(shù)字,將其除以7余數(shù)為2,發(fā)送時(shí)將996-2合并后發(fā)出,接收方按同樣運(yùn)算判斷數(shù)據(jù)包是否正確。同樣的源數(shù)據(jù),因?yàn)槌龜?shù)不同而余數(shù)不同。CRC算法也是因?yàn)轭愃圃怼?/p>

CRC算法中參數(shù)解釋如下:
1、除法定為模2除法

2、除數(shù)定為多項(xiàng)式,如x16+x12+x^5+1(0x1021) 216+212+25+20=65536+4096+32+1= 69665=0x11021 。依據(jù)不可描述的標(biāo)準(zhǔn),多項(xiàng)式最高位和最低位必須為1,所以一般簡(jiǎn)化為0x1021,忽略最高位,記為Poly。

3、因?yàn)槎囗?xiàng)式長(zhǎng)度不同,一般分為CRC8、CRC16和CRC32,因?yàn)槟?除法簡(jiǎn)化為異或和移位操作,其初始值為Init。

4、還有三個(gè)參數(shù)

RefIn:待測(cè)數(shù)據(jù)的每個(gè)字節(jié)是否按位反轉(zhuǎn),TRUE或FALSE。

RefOut:在計(jì)算后之后,異或輸出之前,整個(gè)數(shù)據(jù)是否按位反轉(zhuǎn),TRUE或FALSE。

XorOut:計(jì)算結(jié)果與此參數(shù)異或后得到最終的CRC值。但是任何數(shù)與0異或還是它本身,所以該值為0時(shí)可以忽略。

5、因?yàn)槎囗?xiàng)式Poly,初始值等差異,CRC有不同的版本。理論上是多項(xiàng)式是可以隨意定義的,但是通用的標(biāo)準(zhǔn)多項(xiàng)式是經(jīng)過(guò)數(shù)學(xué)推導(dǎo)的,盡可能的保證不同的數(shù)據(jù)求出的CRC值不相同。

6、參考https://crccalc.com/ 的定義,不同場(chǎng)景使用不同的多項(xiàng)式。


2、CRC算法與模板
通用版的CRC算法如下:
CRC8

//以CRC-8/ITU為參考 unsigned char CRC8(unsigned char *data, unsigned int len) {unsigned char i;unsigned char poly = 0x07;//與表中的Poly列對(duì)應(yīng)unsigned char init = 0x00;//與表中的Init列對(duì)應(yīng)unsigned char wChar = 0;while (len--){wChar = *(data++);//RefIn為TRUE時(shí)執(zhí)行,FALSE時(shí)刪除//InvertUint8(&wChar,&wChar);init ^= wChar;for( i = 0;i < 8;i++){if(init & 0x80){init = (init << 1) ^ poly;}else{init = init << 1;}}}//RefOut為TRUE時(shí)執(zhí)行,FALSE時(shí)刪除//InvertUint8(&init,&init);//與XorOut進(jìn)行異或,若為0時(shí)執(zhí)行或不執(zhí)行沒(méi)有區(qū)別init=init^0x55;return (init);}

CRC16

//以CRC-16/X-25為參考 unsigned short CRC16(unsigned char *data, unsigned int len) {unsigned char i;unsigned short poly = 0x1021;//與表中的Poly列對(duì)應(yīng)unsigned short init = 0xFFFF;//與表中的Init列對(duì)應(yīng)unsigned char wChar = 0;while (len--){wChar = *(data++);//RefIn為TRUE時(shí)執(zhí)行,FALSE時(shí)刪除InvertUint8(&wChar,&wChar);init ^= (wChar << 8);for( i = 0;i < 8;i++){if(init & 0x8000){init = (init << 1) ^ poly;}else{init = init << 1;}}}//RefOut為TRUE時(shí)執(zhí)行,FALSE時(shí)刪除InvertUint16(&init,&init);//與XorOut進(jìn)行異或,若為0時(shí)執(zhí)行或不執(zhí)行沒(méi)有區(qū)別init=init^0xFFFF;return (init); }

CRC8和CRC16,根據(jù)不同版本的參數(shù)差異,查表,將模板里的參數(shù)改為對(duì)應(yīng)值,即可得出對(duì)應(yīng)版本的CRC值。其中涉及到數(shù)據(jù)反轉(zhuǎn)的代碼如下:

void InvertUint8(unsigned char *DesBuf, unsigned char *SrcBuf) {int i;unsigned char temp = 0;for(i = 0; i < 8; i++){if(SrcBuf[0] & (1 << i)){temp |= 1 << (7 - i);}}*DesBuf = temp; }void InvertUint16(unsigned short *DesBuf, unsigned short *SrcBuf) {int i;unsigned short temp = 0;for(i = 0; i < 16; i++){if(SrcBuf[0] & (1 << i)){temp |= 1 << (15 - i);}}*DesBuf = temp; }

3、查表
針對(duì)上面的代碼,求解CRC移位異或運(yùn)算的循環(huán)體,對(duì)時(shí)間要求較高的場(chǎng)景,可以提前計(jì)算生成數(shù)值表,以空間換時(shí)間。

//以CRC-8/ITU為例,生成數(shù)組查表 void creatTable(void) {unsigned char i,init;unsigned short j;for(j=0;j<=255;j++){if(j%16==0){printf("\r\n");}init=j;for( i = 0;i < 8;i++){if(init & 0x80){init = (init << 1) ^ 0x07;//以實(shí)際poly為準(zhǔn);}else{init = init << 1;}}printf("0x%02X,", init);} }

確定poly后,假設(shè)init為0-255,求出256個(gè)參數(shù),轉(zhuǎn)為一維數(shù)組。如上,以CRC-8/ITU為例,生成數(shù)組如下:

原來(lái)的直接計(jì)算改為查表,如下:

//以CRC-8/ITU為參考 unsigned char CRC8(unsigned char *data, unsigned int len) {unsigned char i;unsigned char poly = 0x07;//與表中的Poly列對(duì)應(yīng)unsigned char init = 0x00;//與表中的Init列對(duì)應(yīng)unsigned char wChar = 0;while (len--){wChar = *(data++);//RefIn為TRUE時(shí)執(zhí)行,FALSE時(shí)刪除//InvertUint8(&wChar,&wChar);init ^= wChar;/************************************************************/ #if 1init=crcTable[init];//查表,空間換時(shí)間 #elsefor( i = 0;i < 8;i++){if(init & 0x80){init = (init << 1) ^ poly;}else{init = init << 1;}} #endif /************************************************************/}//RefOut為TRUE時(shí)執(zhí)行,FALSE時(shí)刪除//InvertUint8(&init,&init);//與XorOut進(jìn)行異或,若為0時(shí)執(zhí)行或不執(zhí)行沒(méi)有區(qū)別init=init^0x55;return (init); }

對(duì)于CRC16也可以使用查表法。

總結(jié)

以上是生活随笔為你收集整理的【嵌入式算法】CRC校验算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。