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異或
多項式產生:
如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校驗碼。
根據算法原理與標准要求就能簡單的寫出具體程序:
CRC算法參數模型解釋: NAME:參數模型名稱。 WIDTH:寬度,即CRC比特數。 POLY:生成項的簡寫,以16進制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生 成項是0x104C11DB7。 INIT:這是算法開始時寄存器(crc)的初始化預置值,十六進制表示。 REFIN:待測數據的每個字節是否按位反轉,True或False。 REFOUT:在計算后之后,異或輸出之前,整個數據是否按位反轉,True或False。 XOROUT:計算結果與此參數異或后得到最終的CRC值。 Alias:別名及其應用范圍。
/****************************Info********************************************** * Name: CRC-16/CCITT x16+x12+x5+1 * Width: 16 * Poly: 0x1021 * Init: 0x0000 * Refin: True * Refout: True * Xorout: 0x0000 * Alias: CRC-CCITT,CRC-16/CCITT-TRUE,CRC-16/KERMIT *****************************************************************************/ #if 0 unsigned short CRC16_CCITT(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0x0000; unsigned short wCPoly = 0x1021; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); 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); } #else //這里為了效率,我們不需要將所有Refin和refout為true的輸入輸出數據移位轉換 //只需要將poly二項式轉換后,運算時將左移變為右移 unsigned short CRC16_CCITT(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0x0000; unsigned short wCPoly = 0x1021; unsigned char wChar = 0; InvertUint16(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = wCRCin >> 1; } } return (wCRCin); } #endif /****************************Info********************************************** * Name: CRC-16/CCITT-FALSE x16+x12+x5+1 * Width: 16 * Poly: 0x1021 * Init: 0xFFFF * Refin: False * Refout: False * Xorout: 0x0000 * Note: *****************************************************************************/ unsigned short CRC16_CCITT_FALSE(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0xFFFF; unsigned short wCPoly = 0x1021; while (datalen--) { wCRCin ^= *(data++) << 8; for(int i = 0;i < 8;i++) { if(wCRCin & 0x8000) wCRCin = (wCRCin << 1) ^ wCPoly; else wCRCin = wCRCin << 1; } } return (wCRCin); } /****************************Info********************************************** * Name: CRC-16/XMODEM x16+x12+x5+1 * Width: 16 * Poly: 0x1021 * Init: 0x0000 * Refin: False * Refout: False * Xorout: 0x0000 * Alias: CRC-16/ZMODEM,CRC-16/ACORN *****************************************************************************/ unsigned short CRC16_XMODEM(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0x0000; unsigned short wCPoly = 0x1021; while (datalen--) { wCRCin ^= (*(data++) << 8); for(int i = 0;i < 8;i++) { if(wCRCin & 0x8000) wCRCin = (wCRCin << 1) ^ wCPoly; else wCRCin = wCRCin << 1; } } return (wCRCin); } /****************************Info********************************************** * Name: CRC-16/X25 x16+x12+x5+1 * Width: 16 * Poly: 0x1021 * Init: 0xFFFF * Refin: True * Refout: True * Xorout: 0XFFFF * Note: *****************************************************************************/ #if 0 unsigned short CRC16_X25(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0xFFFF; unsigned short wCPoly = 0x1021; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); 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); } #else unsigned short CRC16_X25(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0xFFFF; unsigned short wCPoly = 0x1021; InvertUint16(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = wCRCin >> 1; } } return (wCRCin^0xFFFF); } #endif /****************************Info********************************************** * Name: CRC-16/MODBUS x16+x15+x2+1 * Width: 16 * Poly: 0x8005 * Init: 0xFFFF * Refin: True * Refout: True * Xorout: 0x0000 * Note: *****************************************************************************/ #if 0 unsigned short CRC16_MODBUS(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0xFFFF; unsigned short wCPoly = 0x8005; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); 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); } #else unsigned short CRC16_MODBUS(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0xFFFF; unsigned short wCPoly = 0x8005; InvertUint16(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = wCRCin >> 1; } } return (wCRCin); } #endif /****************************Info********************************************** * Name: CRC-16/IBM x16+x15+x2+1 * Width: 16 * Poly: 0x8005 * Init: 0x0000 * Refin: True * Refout: True * Xorout: 0x0000 * Alias: CRC-16,CRC-16/ARC,CRC-16/LHA *****************************************************************************/ #if 0 unsigned short CRC16_IBM(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0x0000; unsigned short wCPoly = 0x8005; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); 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); } #else unsigned short CRC16_IBM(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0x0000; unsigned short wCPoly = 0x8005; InvertUint16(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = wCRCin >> 1; } } return (wCRCin); } #endif /****************************Info********************************************** * Name: CRC-16/MAXIM x16+x15+x2+1 * Width: 16 * Poly: 0x8005 * Init: 0x0000 * Refin: True * Refout: True * Xorout: 0xFFFF * Note: *****************************************************************************/ #if 0 unsigned short CRC16_MAXIM(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0x0000; unsigned short wCPoly = 0x8005; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); 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); } #else unsigned short CRC16_MAXIM(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0x0000; unsigned short wCPoly = 0x8005; InvertUint16(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = wCRCin >> 1; } } return (wCRCin^0xFFFF); } #endif /****************************Info********************************************** * Name: CRC-16/USB x16+x15+x2+1 * Width: 16 * Poly: 0x8005 * Init: 0xFFFF * Refin: True * Refout: True * Xorout: 0xFFFF * Note: *****************************************************************************/ #if 0 unsigned short CRC16_USB(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0xFFFF; unsigned short wCPoly = 0x8005; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); 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); } #else unsigned short CRC16_USB(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0xFFFF; unsigned short wCPoly = 0x8005; InvertUint16(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = wCRCin >> 1; } } return (wCRCin^0xFFFF); } #endif /****************************Info********************************************** * Name: CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1 * Width: 16 * Poly: 0x3D65 * Init: 0x0000 * Refin: True * Refout: True * Xorout: 0xFFFF * Use: M-Bus,ect. *****************************************************************************/ #if 0 unsigned short CRC16_DNP(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0x0000; unsigned short wCPoly = 0x3D65; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); 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) ; } #else unsigned short CRC16_DNP(unsigned char *data, unsigned int datalen) { unsigned short wCRCin = 0x0000; unsigned short wCPoly = 0x3D65; InvertUint16(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = (wCRCin >> 1); } } return (wCRCin^0xFFFF); } #endif
/****************************Info********************************************** * Name: InvertUint8 * Note: 把字節顛倒過來,如0x12變成0x48 0x12: 0001 0010 0x48: 0100 1000 *****************************************************************************/ void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf) { int i; unsigned char tmp[4]={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]={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]={0}; for(i=0;i< 32;i++) { if(srcBuf[0]& (1 << i)) tmp[0]|=1<<(31 - i); } dBuf[0] = tmp[0]; }
具體驗證使用這個工具,內含CRC算法的計算,和后邊的博客中提到的其他算法的工具合集
在這個基礎上也加入CRC32 的校驗算法
/****************************Info********************************************** * Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 * Width: 32 * Poly: 0x4C11DB7 * Init: 0xFFFFFFF * Refin: True * Refout: True * Xorout: 0xFFFFFFF * Alias: CRC_32/ADCCP * Use: WinRAR,ect. *****************************************************************************/ #if 0 unsigned int CRC32(unsigned char *data, unsigned int datalen) { unsigned int wCRCin = 0xFFFFFFFF; unsigned int wCPoly = 0x04C11DB7; unsigned int wChar = 0; while (datalen--) { wChar = *(data++); InvertUint8((unsigned char *)&wChar,(unsigned char *)&wChar); wCRCin ^= (wChar << 24); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80000000) wCRCin = (wCRCin << 1) ^ wCPoly; else wCRCin = wCRCin << 1; } } InvertUint32(&wCRCin,&wCRCin); return (wCRCin ^ 0xFFFFFFFF) ; } #else unsigned int CRC32(unsigned char *data, unsigned int datalen) { unsigned int wCRCin = 0xFFFFFFFF; unsigned int wCPoly = 0x04C11DB7; InvertUint32(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = wCRCin >> 1; } } return (wCRCin ^ 0xFFFFFFFF) ; } #endif /****************************Info********************************************** * Name: CRC-32/MPEG-2 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 * Width: 32 * Poly: 0x4C11DB7 * Init: 0xFFFFFFF * Refin: False * Refout: False * Xorout: 0x0000000 * Note: *****************************************************************************/ unsigned int CRC32_MPEG(unsigned char *data, unsigned int datalen) { unsigned int wCRCin = 0xFFFFFFFF; unsigned int wCPoly = 0x04C11DB7; unsigned int wChar = 0; while (datalen--) { wChar = *(data++); wCRCin ^= (wChar << 24); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80000000) wCRCin = (wCRCin << 1) ^ wCPoly; else wCRCin = wCRCin << 1; } } return (wCRCin) ; }
對於CRC32可能還有其他的多項式和初始值和結果值是否需要異或以及輸入數據是否需要位序倒轉等要求在源碼中修改 本次在CRC算法的基礎上加入CRC-4,5,6,7,8的各個算法實現:
/****************************Info********************************************** * Name: CRC-4/ITU x4+x+1 * Width: 4 * Poly: 0x03 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/ unsigned char CRC4_ITU(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00; unsigned char wCPoly = 0x03; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); InvertUint8(&wChar,&wChar); wCRCin ^= (wChar); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ (wCPoly << 4); else wCRCin = wCRCin << 1; } } InvertUint8(&wCRCin,&wCRCin); return (wCRCin); } /****************************Info********************************************** * Name: CRC-5/EPC x5+x3+1 * Width: 5 * Poly: 0x09 * Init: 0x09 * Refin: False * Refout: False * Xorout: 0x00 * Note: *****************************************************************************/ unsigned char CRC5_EPC(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x09<<3; unsigned char wCPoly = 0x09<<3; while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ (wCPoly); else wCRCin = wCRCin << 1; } } return (wCRCin >> 3); } /****************************Info********************************************** * Name: CRC-5/USB x5+x2+1 * Width: 5 * Poly: 0x05 * Init: 0x1F * Refin: True * Refout: True * Xorout: 0x1F * Note: *****************************************************************************/ #if 0 unsigned char CRC5_USB(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x1F<<3; unsigned char wCPoly = 0x05; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); InvertUint8(&wChar,&wChar); wCRCin ^= (wChar); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ (wCPoly << 3); else wCRCin = wCRCin << 1; } } InvertUint8(&wCRCin,&wCRCin); return (wCRCin^0x1F); } #else unsigned char CRC5_USB(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x1F; unsigned char wCPoly = 0x05; InvertUint8(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ (wCPoly >> 3); else wCRCin = wCRCin >> 1; } } return (wCRCin^0x1F); } #endif /****************************Info********************************************** * Name: CRC-5/ITU x5+x4+x2+1 * Width: 5 * Poly: 0x15 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/ #if 0 unsigned char CRC5_ITU(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00; unsigned char wCPoly = 0x15; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); InvertUint8(&wChar,&wChar); wCRCin ^= (wChar); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ (wCPoly << 3); else wCRCin = wCRCin << 1; } } InvertUint8(&wCRCin,&wCRCin); return (wCRCin); } #else unsigned char CRC5_ITU(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00; unsigned char wCPoly = 0x15; InvertUint8(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ (wCPoly >> 3); else wCRCin = wCRCin >> 1; } } return (wCRCin); } #endif /****************************Info********************************************** * Name: CRC-6/ITU x6+x+1 * Width: 6 * Poly: 0x03 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/ unsigned char CRC6_ITU(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00; unsigned char wCPoly = 0x03; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); InvertUint8(&wChar,&wChar); wCRCin ^= (wChar); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ (wCPoly << 2); else wCRCin = wCRCin << 1; } } InvertUint8(&wCRCin,&wCRCin); return (wCRCin); } /****************************Info********************************************** * Name: CRC-7/MMC x7+x3+1 * Width: 7 * Poly: 0x09 * Init: 0x00 * Refin: False * Refout: False * Xorout: 0x00 * Use: MultiMediaCard,SD,ect. *****************************************************************************/ unsigned char CRC7_MMC(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00; unsigned char wCPoly = 0x09; while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ (wCPoly<<1); else wCRCin = wCRCin << 1; } } return (wCRCin>>1); } /****************************Info********************************************** * Name: CRC-8 x8+x2+x+1 * Width: 8 * Poly: 0x07 * Init: 0x00 * Refin: False * Refout: False * Xorout: 0x00 * Note: *****************************************************************************/ unsigned char CRC8(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00; unsigned char wCPoly = 0x07; while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ wCPoly; else wCRCin = wCRCin << 1; } } return (wCRCin); } /****************************Info********************************************** * Name: CRC-8/ITU x8+x2+x+1 * Width: 8 * Poly: 0x07 * Init: 0x00 * Refin: False * Refout: False * Xorout: 0x55 * Alias: CRC-8/ATM *****************************************************************************/ unsigned char CRC8_ITU(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00; unsigned char wCPoly = 0x07; while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ wCPoly; else wCRCin = wCRCin << 1; } } return (wCRCin^0x55); } /****************************Info********************************************** * Name: CRC-8/ROHC x8+x2+x+1 * Width: 8 * Poly: 0x07 * Init: 0xFF * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/ #if 0 unsigned char CRC8_ROHC(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0xFF; unsigned char wCPoly = 0x07; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); InvertUint8(&wChar,&wChar); wCRCin ^= (wChar << 0); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ wCPoly; else wCRCin = wCRCin << 1; } } InvertUint8(&wCRCin,&wCRCin); return (wCRCin); } #else unsigned char CRC8_ROHC(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0xFF; unsigned char wCPoly = 0x07; InvertUint8(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = wCRCin >> 1; } } return (wCRCin); } #endif /****************************Info********************************************** * Name: CRC-8/MAXIM x8+x5+x4+1 * Width: 8 * Poly: 0x31 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Alias: DOW-CRC,CRC-8/IBUTTON * Use: Maxim(Dallas)'s some devices,e.g. DS18B20 *****************************************************************************/ #if 0 unsigned char CRC8_MAXIM(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00; unsigned char wCPoly = 0x31; unsigned char wChar = 0; while (datalen--) { wChar = *(data++); InvertUint8(&wChar,&wChar); wCRCin ^= (wChar << 0); for(int i = 0;i < 8;i++) { if(wCRCin & 0x80) wCRCin = (wCRCin << 1) ^ wCPoly; else wCRCin = wCRCin << 1; } } InvertUint8(&wCRCin,&wCRCin); return (wCRCin); } #else unsigned char CRC8_MAXIM(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00; unsigned char wCPoly = 0x31; InvertUint8(&wCPoly,&wCPoly); while (datalen--) { wCRCin ^= *(data++); for(int i = 0;i < 8;i++) { if(wCRCin & 0x01) wCRCin = (wCRCin >> 1) ^ wCPoly; else wCRCin = wCRCin >> 1; } } return (wCRCin); } #endif
最后附上代碼,里面含有測試程序
轉:https://blog.csdn.net/leumber/article/details/54311811
/****************************Info********************************************** * Name: CRC-4/ITUx4+x+1 * Width:4 * Poly: 0x03 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/unsigned char CRC4_ITU(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x03;unsigned char wChar = 0;while (datalen--) {wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly << 4);elsewCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin);}/****************************Info********************************************** * Name: CRC-5/EPCx5+x3+1 * Width:5 * Poly: 0x09 * Init: 0x09 * Refin: False * Refout: False * Xorout: 0x00 * Note: *****************************************************************************/unsigned char CRC5_EPC(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x09<<3;unsigned char wCPoly = 0x09<<3;while (datalen--) {wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly);elsewCRCin = wCRCin << 1;}}return (wCRCin >> 3);}/****************************Info********************************************** * Name: CRC-5/USBx5+x2+1 * Width:5 * Poly: 0x05 * Init: 0x1F * Refin: True * Refout: True * Xorout: 0x1F * Note: *****************************************************************************/#if 0unsigned char CRC5_USB(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x1F<<3;unsigned char wCPoly = 0x05;unsigned char wChar = 0;while (datalen--) {wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly << 3);elsewCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin^0x1F);}#elseunsigned char CRC5_USB(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x1F;unsigned char wCPoly = 0x05;InvertUint8(&wCPoly,&wCPoly);while (datalen--) {wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ (wCPoly >> 3);elsewCRCin = wCRCin >> 1;}}return (wCRCin^0x1F); } #endif/****************************Info********************************************** * Name: CRC-5/ITUx5+x4+x2+1 * Width:5 * Poly: 0x15 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/ #if 0unsigned char CRC5_ITU(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x15;unsigned char wChar = 0;while (datalen--) {wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly << 3);elsewCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin);}#elseunsigned char CRC5_ITU(unsigned char *data, unsigned int datalen) { unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x15;InvertUint8(&wCPoly,&wCPoly);while (datalen--) {wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ (wCPoly >> 3);elsewCRCin = wCRCin >> 1;}}return (wCRCin); } #endif/****************************Info********************************************** * Name: CRC-6/ITUx6+x+1 * Width:6 * Poly: 0x03 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/unsigned char CRC6_ITU(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x03;unsigned char wChar = 0;while (datalen--) {wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly << 2);elsewCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin);}/****************************Info********************************************** * Name: CRC-7/MMC x7+x3+1 * Width:7 * Poly: 0x09 * Init: 0x00 * Refin: False * Refout: False * Xorout: 0x00 * Use: MultiMediaCard,SD,ect. *****************************************************************************/unsigned char CRC7_MMC(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x09;while (datalen--) {wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ (wCPoly<<1);elsewCRCin = wCRCin << 1;}}return (wCRCin>>1);}/****************************Info********************************************** * Name: CRC-8 x8+x2+x+1 * Width:8 * Poly: 0x07 * Init: 0x00 * Refin: False * Refout: False * Xorout: 0x00 * Note: *****************************************************************************/unsigned char CRC8(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x07;while (datalen--) {wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}return (wCRCin);}/****************************Info********************************************** * Name: CRC-8/ITU x8+x2+x+1 * Width:8 * Poly: 0x07 * Init: 0x00 * Refin: False * Refout: False * Xorout: 0x55 * Alias: CRC-8/ATM *****************************************************************************/unsigned char CRC8_ITU(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x07;while (datalen--) {wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}return (wCRCin^0x55);}/****************************Info********************************************** * Name: CRC-8/ROHC x8+x2+x+1 * Width:8 * Poly: 0x07 * Init: 0xFF * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/#if 0unsigned char CRC8_ROHC(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0xFF;unsigned char wCPoly = 0x07;unsigned char wChar = 0;while (datalen--) {wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 0);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin);}#else unsigned char CRC8_ROHC(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0xFF;unsigned char wCPoly = 0x07;InvertUint8(&wCPoly,&wCPoly);while (datalen--) {wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = wCRCin >> 1;}}return (wCRCin);}#endif/****************************Info********************************************** * Name: CRC-8/MAXIM x8+x5+x4+1 * Width:8 * Poly: 0x31 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Alias: DOW-CRC,CRC-8/IBUTTON * Use: Maxim(Dallas)'s some devices,e.g. DS18B20 *****************************************************************************/ #if 0unsigned char CRC8_MAXIM(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x31;unsigned char wChar = 0;while (datalen--) {wChar = *(data++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 0);for(int i = 0;i < 8;i++){if(wCRCin & 0x80)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint8(&wCRCin,&wCRCin);return (wCRCin);}#else unsigned char CRC8_MAXIM(unsigned char *data, unsigned int datalen){unsigned char wCRCin = 0x00;unsigned char wCPoly = 0x31;InvertUint8(&wCPoly,&wCPoly);while (datalen--) {wCRCin ^= *(data++);for(int i = 0;i < 8;i++){if(wCRCin & 0x01)wCRCin = (wCRCin >> 1) ^ wCPoly;elsewCRCin = wCRCin >> 1;}}return (wCRCin);}#endif
