这个算法是在逐BYTE法的基础上进行修改的,在上一篇文章里我们说过,如果不查表的话,逐BYTE法和逐BIT法没什么区别,现在我们就把这个算法写出来,注意在调用CRC校验函数前需要先调用表生成函数:
u32 CRC_Table[]; /*******************************CRC校验程序***********************************/ //作者 Skystalker //输入32位 //多项式,省略最高位1 0x4C11DB7 CCITT-32: 0x04C11DB7 = x32 + x26 + x23 + x22 + x16 + x12 + // x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 //数据不revert 结果不revert //初值0x00000000或0xFFFFFFFF,其实所谓的初值就是原始数据要不要跟0xFFFFFFFF先异或先放到Reg中计算,用0xFFFFFFFF只是为了让别人不 //会一下就看出生成多项式是多少 //结果不异或 //验证网址:http://www.zorc.breitbandkatze.de/crc.html //算法中数据向左移动,相对手工计算等效于生成多项式向右移动,所以不需要在后面加一大堆0 u32 CRC_Check_Software(u8 *ucpData,u8 Length) { u32 Reg;//CRC寄存器,即传统除法中的余数 u32 tempbyte=; u8 i; u8 count; u8 j=; u8 u32DataLen=((Length/)>)?((Length/)+):(Length/); u32 uipData[]={}; //把byte组合成32位一组的数据放入uipData ;i<Length;i++) { uipData[i/]|=((u32)(*(ucpData+i)))<<(*(j-)); j--; ) { j=; } } //以下是算法开始 //查表法 ;count<u32DataLen;count++) { Reg=uipData[count]; //Reg^=0xffffffff;//如果初值为0x00000000就把这行注释掉,否则不要注释 ;i<;i++) { tempbyte=CRC_Table[(u8)(( Reg >> ) & 0xff)]; //取一个字节,查表 Reg=Reg<<; //丢掉计算过的头一个BYTE Reg^=tempbyte; //与前一个BYTE的计算结果异或 } } //查表法 return Reg; } /***********************************单字节32位CRC校验表生成函数*******************************/ //作者 Skystalker //多项式,省略最高位1 0x4C11DB7 CCITT-32: 0x04C11DB7 = x32 + x26 + x23 + x22 + x16 + x12 + // x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 //数据不revert 结果不revert //结果不异或 //算法中数据向左移动,相对手工计算等效于生成多项式向右移动,所以不需要在后面加一大堆0 void CreateCRCTable(void) { u16 Data,j; u32 tempbyte; u32 poly=0x4C11DB7; //生成多项式 ;Data<;Data++) { tempbyte=((u32)Data)<<; ;j<;j++) { if(tempbyte&0x80000000) { tempbyte=tempbyte<<; //要异或时Reg的最高位是1,CRC多项式最高位一直就是1,异或后必为0,所以一开始就偷懒把CRC多项式去掉最高位变成 //0x4C11DB7 ,所以相应的这时候要把Reg左移一位,只要异或后边的32位 tempbyte^=poly; } else { tempbyte=tempbyte<<; } } CRC_Table[Data]=tempbyte; } }
上面的算法每次初始化都要计算一次表,何不直接把表做出来放到程序里:
以下程序在VS2008调试通过,使用时在工程目录里新建一个文件a.c ,运行一遍下面的程序,在a.c 里就有可以直接使用的驱动表:
#include <stdio.h> #include <windows.h> UINT CRC_Table[]; void CreateCRCTable(void) { FILE * fp; unsigned __int16 Data,j; UINT tempbyte; UINT poly=0x4C11DB7; //生成多项式 if((fp=fopen("a.c","w"))==NULL) { printf("error\n"); } fprintf(fp,"%s\n","UINT CRC_Table[256]="); fprintf(fp,"%c\n",'{'); ;Data<;Data++) { tempbyte=((UINT)Data)<<; ;j<;j++) { if(tempbyte&0x80000000) { tempbyte=tempbyte<<; //要异或时Reg的最高位是1,CRC多项式最高位一直就是1,异或后必为0,所以一开始就偷懒把CRC多项式去掉最高位变成 //0x4C11DB7 ,所以相应的这时候要把Reg左移一位,只要异或后边的32位 tempbyte^=poly; } else { tempbyte=tempbyte<<; } } CRC_Table[Data]=tempbyte; ) fprintf(fp,"%s%x\n","0x",CRC_Table[Data]); else fprintf(fp,"%s%x%c","0x",CRC_Table[Data],','); } fprintf(fp,"%s\n","};"); } int main() { CreateCRCTable(); return TRUE; }