生活随笔
收集整理的這篇文章主要介紹了
CRC16协议
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
CRC碼由發送端計算,放置于發送信息報文的尾部。接收信息的設備再重新計算接收到信息報文的CRC,比較計算得到的CRC是否與接收到的相符,如果兩者不相符,則表明出錯。
校驗碼的計算多項式為(X16 + X15 + X2 + 1)。具體CRC16碼的計算方法是:
??????? 1.預置1個16位的寄存器為十六進制FFFF(即全為1);稱此寄存器為CRC寄存器;
??????? 2.把第一個8位二進制數據 (既通訊信息幀的第一個字節)與16位的CRC寄存器的低8位相異或,把結果放于CRC寄存器;
??????? 3.把CRC寄存器的內容右移一 位(朝低位)用0填補最高位,并檢查右移后的移出位;
??????? 4.如果移出位為0:重復第3步(再次右移一位);
??????? 如果移出位為1:CRC寄存器與多項式A001(1010 0000 0000 0001)進行異或;(Modbus)
??????? 5.重復步驟3和4,直到右移8次,這樣整個8位數據全部進行了處理;
??????? 6.重復步驟2到步驟5,進行通訊信息幀下一個字節的處理;
??????? 7.將該通訊信息幀所有字節按上述步驟計算完成后,得到的16位CRC寄存器的高、低字節進行交換;
??????? 8.最后得到的CRC寄存器內容即為:CRC碼。
CRC16常見的標準有以下幾種,被用在各個規范中,其算法原理基本一致,就是在數據的輸入和輸出有所差異,下邊把這些標準的差異列出,并給出C語言的算法實現。
CRC16_CCITT:多項式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,高位在后,結果與0x0000異或
CRC16_CCITT_FALSE:多項式x16+x12+x5+1(0x1021),初始值0xFFFF,低位在后,高位在前,結果與0x0000異或
CRC16_XMODEM:多項式x16+x12+x5+1(0x1021),初始值0x0000,低位在后,高位在前,結果與0x0000異或
CRC16_X25:多項式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,高位在后,結果與0xFFFF異或
?
CRC16_MODBUS:多項式x16+x15+x2+1(0x8005),初始值0xFFFF,低位在前,高位在后,結果與0x0000異或
CRC16_IBM:多項式x16+x15+x2+1(0x8005),初始值0x0000,低位在前,高位在后,結果與0x0000異或
CRC16_MAXIM:多項式x16+x15+x2+1(0x8005),初始值0x0000,低位在前,高位在后,結果與0xFFFF異或
CRC16_USB:多項式x16+x15+x2+1(0x8005),初始值0xFFFF,低位在前,高位在后,結果與0xFFFF異或
?
| 模式 | 多項式 | 初始值 | 數據位序 | 結果處理 |
| CRC16_CCITT | x16+x12+x5+1(0x1021) | 0x0000 | 低位在前,高位在后 | 與0x0000異或 |
| CRC16_CCITT_FALSE | x16+x12+x5+1(0x1021) | 0xFFFF | 低位在后,高位在前 | 與0x0000異或 |
| CRC16_XMODEM | x16+x12+x5+1(0x1021) | 0x0000 | 低位在后,高位在前 | 與0x0000異或 |
| CRC16_X25 | x16+x12+x5+1(0x1021) | 0x0000 | 低位在后,高位在前 | 與0xFFFF異或 |
| CRC16_ MODBUS | x16+x15+x2+1(0x8005) | 0xFFFF | 低位在前,高位在后 | 與0x0000異或 |
| CRC16_ IBM | x16+x15+x2+1(0x8005) | 0x0000 | 低位在前,高位在后 | 與0x0000異或 |
| CRC16_ MAXIM | x16+x15+x2+1(0x8005) | 0x0000 | 低位在前,高位在后 | 與0xFFFF異或 |
| CRC16_ USB | x16+x15+x2+1(0x8005) | 0xFFFF | 低位在前,高位在后 | 與0xFFFF異或 |
多項式產生:
如x16+x12+x5+1
x16表示第16位為1,x5表示第5位為1
(1 << 16) | (1 << 12) | (1 << 5) | (1) = 0x11021
但是CRC16只取低16位,寫成16進制數就是 0x1021
CRC16的算法原理:
1.根據CRC16的標準選擇初值CRCIn的值。
2.將數據的第一個字節與CRCIn高8位異或。
3.判斷最高位,若該位為 0 左移一位,若為 1 左移一位再與多項式Hex碼異或。
4.重復3直至8位全部移位計算結束。
5.重復將所有輸入數據操作完成以上步驟,所得16位數即16位CRC校驗碼。
根據算法原理與標準要求就能簡單的寫出具體程序:
?
[cpp]?view plain?copy
unsigned?short?CRC16_CCITT(unsigned?char?*puchMsg,?unsigned?int?usDataLen)??{????unsigned?short?wCRCin?=?0x0000;????unsigned?short?wCPoly?=?0x1021;????unsigned?char?wChar?=?0;????????while?(usDataLen--)???????{??????????wChar?=?*(puchMsg++);??????????InvertUint8(&wChar,&wChar);??????????wCRCin?^=?(wChar?<<?8);??????????for(int?i?=?0;i?<?8;i++)??????????{????????????if(wCRCin?&?0x8000)??????????????wCRCin?=?(wCRCin?<<?1)?^?wCPoly;????????????else??????????????wCRCin?=?wCRCin?<<?1;??????????}????}????InvertUint16(&wCRCin,&wCRCin);????return?(wCRCin)?;??}??unsigned?short?CRC16_CCITT_FALSE(unsigned?char?*puchMsg,?unsigned?int?usDataLen)??{????unsigned?short?wCRCin?=?0xFFFF;????unsigned?short?wCPoly?=?0x1021;????unsigned?char?wChar?=?0;????????while?(usDataLen--)???????{??????????wChar?=?*(puchMsg++);??????????wCRCin?^=?(wChar?<<?8);??????????for(int?i?=?0;i?<?8;i++)??????????{????????????if(wCRCin?&?0x8000)??????????????wCRCin?=?(wCRCin?<<?1)?^?wCPoly;????????????else??????????????wCRCin?=?wCRCin?<<?1;??????????}????}????return?(wCRCin)?;??}??unsigned?short?CRC16_XMODEM(unsigned?char?*puchMsg,?unsigned?int?usDataLen)??{????unsigned?short?wCRCin?=?0x0000;????unsigned?short?wCPoly?=?0x1021;????unsigned?char?wChar?=?0;????????while?(usDataLen--)???????{??????????wChar?=?*(puchMsg++);??????????wCRCin?^=?(wChar?<<?8);??????????for(int?i?=?0;i?<?8;i++)??????????{????????????if(wCRCin?&?0x8000)??????????????wCRCin?=?(wCRCin?<<?1)?^?wCPoly;????????????else??????????????wCRCin?=?wCRCin?<<?1;??????????}????}????return?(wCRCin)?;??}????unsigned?short?CRC16_X25(unsigned?char?*puchMsg,?unsigned?int?usDataLen)??{????unsigned?short?wCRCin?=?0xFFFF;????unsigned?short?wCPoly?=?0x1021;????unsigned?char?wChar?=?0;????????while?(usDataLen--)???????{??????????wChar?=?*(puchMsg++);??????????InvertUint8(&wChar,&wChar);??????????wCRCin?^=?(wChar?<<?8);??????????for(int?i?=?0;i?<?8;i++)??????????{????????????if(wCRCin?&?0x8000)??????????????wCRCin?=?(wCRCin?<<?1)?^?wCPoly;????????????else??????????????wCRCin?=?wCRCin?<<?1;??????????}????}????InvertUint16(&wCRCin,&wCRCin);????return?(wCRCin^0xFFFF)?;??}????unsigned?short?CRC16_MODBUS(unsigned?char?*puchMsg,?unsigned?int?usDataLen)??{????unsigned?short?wCRCin?=?0xFFFF;????unsigned?short?wCPoly?=?0x8005;????unsigned?char?wChar?=?0;????????while?(usDataLen--)???????{??????????wChar?=?*(puchMsg++);??????????InvertUint8(&wChar,&wChar);??????????wCRCin?^=?(wChar?<<?8);??????????for(int?i?=?0;i?<?8;i++)??????????{????????????if(wCRCin?&?0x8000)??????????????wCRCin?=?(wCRCin?<<?1)?^?wCPoly;????????????else??????????????wCRCin?=?wCRCin?<<?1;??????????}????}????InvertUint16(&wCRCin,&wCRCin);????return?(wCRCin)?;??}??unsigned?short?CRC16_IBM(unsigned?char?*puchMsg,?unsigned?int?usDataLen)??{????unsigned?short?wCRCin?=?0x0000;????unsigned?short?wCPoly?=?0x8005;????unsigned?char?wChar?=?0;????????while?(usDataLen--)???????{??????????wChar?=?*(puchMsg++);??????????InvertUint8(&wChar,&wChar);??????????wCRCin?^=?(wChar?<<?8);??????????for(int?i?=?0;i?<?8;i++)??????????{????????????if(wCRCin?&?0x8000)??????????????wCRCin?=?(wCRCin?<<?1)?^?wCPoly;????????????else??????????????wCRCin?=?wCRCin?<<?1;??????????}????}????InvertUint16(&wCRCin,&wCRCin);????return?(wCRCin)?;??}??unsigned?short?CRC16_MAXIM(unsigned?char?*puchMsg,?unsigned?int?usDataLen)??{????unsigned?short?wCRCin?=?0x0000;????unsigned?short?wCPoly?=?0x8005;????unsigned?char?wChar?=?0;????????while?(usDataLen--)???????{??????????wChar?=?*(puchMsg++);??????????InvertUint8(&wChar,&wChar);??????????wCRCin?^=?(wChar?<<?8);??????????for(int?i?=?0;i?<?8;i++)??????????{????????????if(wCRCin?&?0x8000)??????????????wCRCin?=?(wCRCin?<<?1)?^?wCPoly;????????????else??????????????wCRCin?=?wCRCin?<<?1;??????????}????}????InvertUint16(&wCRCin,&wCRCin);????return?(wCRCin^0xFFFF)?;??}??unsigned?short?CRC16_USB(unsigned?char?*puchMsg,?unsigned?int?usDataLen)??{????unsigned?short?wCRCin?=?0xFFFF;????unsigned?short?wCPoly?=?0x8005;????unsigned?char?wChar?=?0;????????while?(usDataLen--)???????{??????????wChar?=?*(puchMsg++);??????????InvertUint8(&wChar,&wChar);??????????wCRCin?^=?(wChar?<<?8);??????????for(int?i?=?0;i?<?8;i++)??????????{????????????if(wCRCin?&?0x8000)??????????????wCRCin?=?(wCRCin?<<?1)?^?wCPoly;????????????else??????????????wCRCin?=?wCRCin?<<?1;??????????}????}????InvertUint16(&wCRCin,&wCRCin);????return?(wCRCin^0xFFFF)?;??}??
[cpp]?view plain?copy
void?InvertUint8(unsigned?char?*dBuf,unsigned?char?*srcBuf)??{??????int?i;??????unsigned?char?tmp[4];??????tmp[0]?=?0;??????for(i=0;i<?8;i++)??????{????????if(srcBuf[0]&?(1?<<?i))??????????tmp[0]|=1<<(7-i);??????}??????dBuf[0]?=?tmp[0];????????}??void?InvertUint16(unsigned?short?*dBuf,unsigned?short?*srcBuf)??{??????int?i;??????unsigned?short?tmp[4];??????tmp[0]?=?0;??????for(i=0;i<?16;i++)??????{????????if(srcBuf[0]&?(1?<<?i))??????????tmp[0]|=1<<(15?-?i);??????}??????dBuf[0]?=?tmp[0];??}??void?InvertUint32(unsigned?int?*dBuf,unsigned?int?*srcBuf)??{??????int?i;??????unsigned?int?tmp[4];????????tmp[0]?=?0;????????????for(i=0;i<?32;i++)??????{????????if(srcBuf[0]&?(1?<<?i))??????????tmp[0]|=1<<(15?-?i);??????}??????dBuf[0]?=?tmp[0];??}??
具體驗證使用這個工具,內含CRC算法的計算,和后邊的博客中提到的其他算法的工具合集
加密解密算法工具集
在這個基礎上也加入CRC32 的校驗算法
[html]?view plain?copy
?
//CRC32算法:??unsigned?int?CRC32(unsigned?char?*puchMsg,?unsigned?int?usDataLen)??{????int?i;????unsigned?int?wCRCin?=?0xFFFFFFFF;????unsigned?int?wCPoly?=?0x04C11DB7;????unsigned?int?wChar?=?0;????while?(usDataLen--)???????{??????????wChar?=?*(puchMsg++);??????????InvertUint8((unsigned?char?*)&wChar,(unsigned?char?*)&wChar);??????????wCRCin?^=?(wChar?<<?24);??????????for(i?=?0;i?<?8;i++)??????????{????????????if(wCRCin?&?0x80000000)??????????????wCRCin?=?(wCRCin?<<?1)?^?wCPoly;????????????else??????????????wCRCin?=?wCRCin?<<?1;??????????}????}????InvertUint32(&wCRCin,&wCRCin);????return?(wCRCin?^?0xFFFFFFFF)?;??}??
對于CRC32可能還有其他的多項式和初始值和結果值是否需要異或以及輸入數據是否需要位序倒轉等要求在源碼中修改
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的CRC16协议的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。