不同的CRC编写函数,重点差异就在多项式公式, crc初始值, 结果异或值, 输入翻转, 输出翻转这5个参数的不同。
- 定义结构图
typedef struct
{
u32 poly; //多项式
u32 InitValue; //初始值
u32 xor; //结果异或值
BOOL InputReverse; //输入翻转
BOOL OutputReverse; //输出翻转
}S_CRC;
- 定义crc校验的变量
//const S_CRC 变量 = {多项式公式, crc初始值, 结果异或值, 输入翻转, 输出翻转}
const S_CRC crc_8 = {0x07, 0x00, 0x00, FALSE, FALSE}; //0x07 - x8+x2+x1+1
const S_CRC crc_8_ITU = {0x07, 0x00, 0x55, FALSE, FALSE};
const S_CRC crc_8_ROHC = {0x07, 0xff, 0x00, TRUE, TRUE};
const S_CRC crc_8_MAXIM = {0x31, 0x00, 0x00, TRUE, TRUE}; //0x31 - x8+x4+x3+1
const S_CRC crc_16_IBM = {0x8005, 0x0000, 0x0000, TRUE, TRUE}; //0x8005 - x16+x15+x2+1
const S_CRC crc_16_MAXIM = {0x8005, 0x0000, 0xffff, TRUE, TRUE};
const S_CRC crc_16_USB = {0x8005, 0xffff, 0xffff, TRUE, TRUE};
const S_CRC crc_16_MODBUS = {0x8005, 0xffff, 0x0000, TRUE, TRUE};
const S_CRC crc_16_CCITT = {0x1021, 0x0000, 0x0000, TRUE, TRUE}; //0x1021 - x16+x12+x5+1
const S_CRC crc_16_CCITT_FALSE = {0x1021, 0xffff, 0x0000, FALSE, FALSE};
const S_CRC crc_16_X5 = {0x1021, 0xffff, 0xffff, TRUE, TRUE};
const S_CRC crc_16_XMODEM = {0x1021, 0x0000, 0x0000, FALSE, FALSE};
const S_CRC crc_16_DNP = {0x3d65, 0x0000, 0xffff, TRUE, TRUE}; //0x3d65 - x16+x13+x12+x11+x10+x8+x6+x5+x2+1
const S_CRC crc_32 = {0x04c11db7, 0xffffffff, 0xffffffff, TRUE, TRUE};
const S_CRC crc_32_MPEG2 = {0x04c11db7, 0xffffffff, 0x00000000, FALSE, FALSE};
- 翻转函数
/*****************************************************************************
*function name: reverse
*function: 字节反转,如1100 0101 反转后为1010 0011;1100 0101 1011 1111 反转后为1111 1101 1010 0011
*input: data -待反转的数据指针;
* bit -反转位数;
*output: 返回反转后的数据
******************************************************************************/
static u32 reverse(u32 data, u8 bit)
{
u8 i;
u32 temp = 0;
u8 bitlen = bit;
for(i = 0; i < bitlen; i++)
temp |= ((data>>i) & 0x01) << (bitlen-1-i);
return temp;
}
- 通用crc校验函数
/*****************************************************************************
*function name: crc
*function: 通用CRC校验,8位、16位、32位校验通用,根据type和mode来选择具体的crc选项
*input: addr -数据首地址;
* num -数据长度(字节);
* type -CRC的算法类型
* bit -crc校验位数
*output: 32位校验值,bit位数数据有效
******************************************************************************/
u32 crc(u8 *addr, int num, S_CRC type, u8 bit)
{
u8 i;
u8 data;
u8 offset = bit - 8; //高八位 位移数
u32 maxbit = 1 << (bit-1); //对应位数的最高位为1
u32 crc = type.InitValue; //初始值
for (; num > 0; num--)
{
data = *addr++;
if(type.InputReverse == TRUE)
data = reverse(data, M_CRC_8); //字节反转
crc = crc ^ (data << offset); //与crc初始值高8位异或
for (i = 0; i < 8; i++) //循环8位
{
if (crc & maxbit) //左移移出的位为1,左移后与多项式异或
crc = (crc << 1) ^ type.poly;
else //否则直接左移
crc <<= 1;
}
}
if(type.OutputReverse == TRUE) //满足条件,反转
crc = reverse(crc, bit);
crc = crc^type.xor; //最后返与结果异或值异或
//0xffffffff默认int型,位移操作要小于32位
if (bit < M_CRC_32)
crc &= ~(0xffffffff << bit);
return(crc); //返回最终校验值
}