C按位操作实现CRC计算算法

github源码

CRC算法参数模型解释:

NAME:参数模型名称。
WIDTH:宽度,即CRC比特数。
POLY:生成项的简写,以16进制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的”1”,即完整的生成项是0x104C11DB7。
INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。
REFIN:待测数据的每个字节是否按位反转,True或False。
REFOUT:在计算后之后,异或输出之前,整个数据是否按位反转,True或False。
XOROUT:计算结果与此参数异或后得到最终的CRC值。

模型数据结构定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
typedef struct CRC8_TYPE{
uint8_t poly; //多项式
uint8_t init; //reg初始值
uint8_t xorout; //结果异或值
uint8_t refin; //输入数据反转
uint8_t refout; //输出数据反转
}CRC8_TYPE;

typedef struct CRC16_TYPE{
uint16_t poly; //多项式
uint16_t init; //reg初始值
uint16_t xorout; //结果异或值
uint8_t refin; //输入数据反转
uint8_t refout; //输出数据反转
}CRC16_TYPE;

typedef struct CRC32_TYPE{
uint32_t poly; //多项式
uint32_t init; //reg初始值
uint32_t xorout; //结果异或值
uint8_t refin; //输入数据反转
uint8_t refout; //输出数据反转
}CRC32_TYPE;

typedef struct CRC64_TYPE{
uint64_t poly; //多项式
uint64_t init; //reg初始值
uint64_t xorout; //结果异或值
uint8_t refin; //输入数据反转
uint8_t refout; //输出数据反转
}CRC64_TYPE;

按位计算算法大致流程

字节的左右反转

1
2
3
4
5
6
7
8
9
10
uint32_t reflect_uint32_t_bits(uint32_t data){
uint32_t result = 0,index = 0x01;
uint8_t i;
for (i = 0;i < 32;i++,index <<= 1){
if(data & index){
result |= 0x01 << (31 - i);
}
}
return result;
}

CRC按位计算的两种方式(一般计算与反序计算)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
uint32_t crc32(uint8_t *data, uint32_t length, uint32_t crc_reg,CRC32_TYPE crc_type){
uint8_t i;
while(length--){
if(crc_type.refin){
uint32_t poly_ref = reflect_uint32_t_bits(crc_type.poly);
crc_reg ^= *data++;
for (i=0;i<8;i++){
if (crc_reg & 0x01){
crc_reg = (crc_reg >> 1) ^ poly_ref;
}else{
crc_reg >>= 1;
}
}
}else{
crc_reg ^= (*data++ << 24);
for (i=0;i<8;i++){
if (crc_reg & 0x80000000){
crc_reg = (crc_reg << 1) ^ crc_type.poly;
}else{
crc_reg <<= 1;
}
}
}
}
return crc_reg;
}

CRC结果异或返回

1
2
3
4
5
6
uint32_t crc32_final_process(uint32_t crc_reg,CRC32_TYPE crc_type){
if(crc_type.refin ^ crc_type.refout){
crc_reg = reflect_uint32_t_bits(crc_reg);
}
return crc_reg ^ crc_type.xorout;
}

常用CRC计算模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CRC8_TYPE crc_8 = {0x07,0x00,0x00,0,0};
CRC8_TYPE crc_8_ITU = {0x07,0x00,0x55,0,0};
CRC8_TYPE crc_8_ROHC = {0x07,0xFF,0x00,1,1};
CRC8_TYPE crc_8_MAXIM = {0x31,0x00,0x00,1,1};

CRC16_TYPE crc_16_IBM = {0x8005,0x0000,0x0000,1,1};
CRC16_TYPE crc_16_MAXIM = {0x8005,0x0000,0xFFFF,1,1};
CRC16_TYPE crc_16_USB = {0x8005,0xFFFF,0xFFFF,1,1};
CRC16_TYPE crc_16_MODBUS = {0x8005,0xFFFF,0x0000,1,1};
CRC16_TYPE crc_16_CCITT = {0x1021,0x0000,0x0000,1,1};
CRC16_TYPE crc_16_CCITT_FALSE = {0x1021,0xFFFF,0x0000,0,0};
CRC16_TYPE crc_16_X25 = {0x1021,0xFFFF,0xFFFF,1,1};
CRC16_TYPE crc_16_XMODEM = {0x1021,0x0000,0x0000,0,0};
CRC16_TYPE crc_16_DNP = {0x3D65,0x0000,0xFFFF,1,1};

CRC32_TYPE crc_32 = {0x04C11DB7,0xFFFFFFFF,0xFFFFFFFF,1,1};
CRC32_TYPE crc_32_MPEG_2 = {0x04C11DB7,0xFFFFFFFF,0x00000000,0,0};
CRC32_TYPE crc_32_BZIP_2 = {0x04C11DB7,0xFFFFFFFF,0xFFFFFFFF,0,0};
CRC32_TYPE crc_32_SCTP = {0x1EDC6F41,0xFFFFFFFF,0xFFFFFFFF,0,0};
CRC32_TYPE crc_32_JAMCRC = {0x04C11DB7,0xFFFFFFFF,0x00000000,1,1};

CRC64_TYPE crc_64 = {0x000000000000001B,0x0000000000000000,0x0000000000000000,0,0};
CRC64_TYPE crc_64_ECMA = {0x42F0E1EBA9EA3693,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFFF,0,0};