常见CRC算法定义如下
CRC算法 | 多项式公式 | 多项式 | 初始值 | 结果异或值 | 输入反转 | 输出反转 |
---|---|---|---|---|---|---|
CRC8 | x8+x2+x1+1 | 07 | 00 | 00 | false | false |
CRC8/ITU | 07 | 00 | 55 | false | false | |
CRC8/ROHC | 07 | FF | 00 | true | true | |
CRC8/MAXIM | x8+x5+x4+1 | 31 | 00 | 00 | true | true |
CRC16/IBM | x16 + x15 + x2 + 1 | 8005 | 0000 | 0000 | true | true |
CRC16/MAXIM | 8005 | 0000 | FFFF | true | true | |
CRC16/USB | 8005 | FFFF | FFFF | true | true | |
CRC16/MODBUS | 8005 | FFFF | 0000 | true | true | |
CRC16/CCITT | x16 + x12 + x5 + 1 | 1021 | 0000 | 0000 | true | true |
CRC16/CCITT-FALSE | 1021 | FFFF | 0000 | false | false | |
CRC16/X25 | 1021 | FFFF | FFFF | true | true | |
CRC16/XMODEM | 1021 | 0000 | 0000 | false | false | |
CRC16/DNP | x16 + x13 + x12 + x11 + x10 + x8 + x6 + x5 + x2 + 1 | 3D65 | 0000 | FFFF | true | true |
CRC32 | x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 | 04C11DB7 | FFFFFFFF | FFFFFFFF | true | true |
CRC32/MPEG-2 | 04C11DB7 | FFFFFFFF | 00000000 | false | false |
说明:
-
多项式公式与多项式是对应的,生成多项式的最高位固定的1,故在简记式中忽略最高位1了
-
初始值是给CRC计算一个初始值,即初始化与输入数据进行异或;
-
结果异或值是把计算结果再异或某一个值;这么做的目的是防止全0数据的CRC一直为0。
-
输入数据反转是指输入数据以字节为单位按位逆序处理;
-
输出数据反转是指CRC计算结果整体按位逆序处理;
CRC算法的本质是将输入数据对除数(包括最高位的1的多项式,如CRC16/CCITT,除数即为0x11021)做模二运算求余数,余数即为CRC值;
CRC16通用算法
quint16 CRC_Normal::calculate_crc16(
quint16 wCRCin, //初始值
quint16 wCPoly, //多项式
quint16 wResultXOR, //结果异或值
bool input_invert, //输入反转
bool ouput_invert, //输出反转
const char *puchMsg, //输入数据
int usDataLen) //输入数据长度
{
quint8 wChar = 0;
while (usDataLen--)
{
wChar = *(puchMsg++);
if(input_invert)//输入值反转
{
quint8 temp_char = wChar;
wChar=0;
for(int i=0;i<8;++i)
{
if(temp_char&0x01)
wChar|=0x01<<(7-i);
temp_char>>=1;
}
}
wCRCin ^= (wChar << 8);
/*以uint8输入,wCRCin的低8bit for循环后,再与输入的uint8[1]左移8bit后异或
与wCRCin的低8bit与uint8[1]异或后,再for循环的值相同(即以uint16输入,即uint8[1]一直参与到除法求余运算中)
因为从每个wCRCin的低8bit每个bit考虑,两者的操作只有异或先后顺序变更,其他一样。
以uint8输入 循环计算,即除法运算时被除数不断向末端移动
wCRCin也可以理解为除法运算时每次运算的余数*/
for (int i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
/* 最高位为1,即被除数可以除以除数,后续bit需要对wCPol异或求余数 */
wCRCin = (wCRCin << 1) ^ wCPoly;
else
wCRCin = wCRCin << 1;
}
}
if(ouput_invert)
{
quint16 temp_short = wCRCin;
wCRCin=0;
for(int i=0;i<16;++i)
{
if(temp_short&0x01)
wCRCin|=0x01<<(15-i);
temp_short>>=1;
}
}
return (wCRCin^wResultXOR);
}
CRC32/MPEG-2算法实现如下,其他算法类似
unsigned int CRC32_MPEG2(unsigned char *data, unsigned int datalen)
{
unsigned int wCRCin = 0xFFFFFFFF;
unsigned int wCPoly = 0x04C11DB7;
unsigned char wChar = 0;
int i = 0;
while (datalen--) {
wChar = *(data++);
wCRCin ^= (wChar<<24);
for (i = 0; i < 8; i++) {
if (wCRCin & 0x80000000)
wCRCin = (wCRCin << 1) ^ wCPoly;
else
wCRCin = wCRCin << 1;
}
}
return wCRCin;
}
Reference
CRC-16原理及通用的16位CRC校验算法代码_crc16校验-优快云博客