以太网帧FCS校验码CRC32的三种实现方法

提供了三种实现方法。

方法一:按位计算CRC32校验码。

方法二:使用非翻转的查找表进行快速计算,按字节计算CRC32校验码。但计算过程中有位翻转操作,计算速度慢。

方法三:使用翻转的查找表进行快速计算,按字节计算CRC校验码。速度极快。


#include <stdio.h>
#include <stdlib.h>
#include <io.h>




#define alt_8    char
#define alt_u8   unsigned char
#define alt_32   int
#define alt_u32  unsigned int
#define alt_64   long long
#define alt_u64  unsigned long long


//位翻转函数
alt_u64 Reflect(alt_u64 ref,alt_u8 ch)
{	
	int i;
	alt_u64 value = 0;
	for( i = 1; i < ( ch + 1 ); i++ )
	{
		if( ref & 1 )
			value |= 1 << ( ch - i );
		ref >>= 1;
	}
	return value;
}


//标准的CRC32多项式
#define poly  0x04C11DB7
//翻转的CRC32多项式
#define upoly 0xEDB88320



alt_u32 crc32_bit(alt_u8 *ptr, alt_u32 len, alt_u32 gx)
{
    alt_u8 i;
	alt_u32 crc = 0xffffffff;
    while( len-- )
    {
        for( i = 1; i != 0; i <<= 1 )
        {
            if( ( crc & 0x80000000 ) != 0 )
			{
				crc <<= 1;
				crc ^= gx;
			}
            else 
				crc <<= 1;
            if( ( *ptr & i ) != 0 ) 
				crc ^= gx;
        }
        ptr++;
    }
    return ( Reflect(crc,32) ^ 0xffffffff );
}






alt_u32 Table1[256];
alt_u32 Table2[256];




 // 生成CRC32 普通表 , 第二项是04C11DB7
void gen_direct_table(alt_u32 *table)
{
	alt_u32 gx = 0x04c11db7;
	unsigned long i32, j32;
	unsigned long nData32;
	unsigned long nAccum32;
	for ( i32 = 0; i32 < 256; i32++ )
	{
		nData32 = ( unsigned long )( i32 << 24 );
		nAccum32 = 0;
		for ( j32 = 0; j32 < 8; j32++ )
		{
			if ( ( nData32 ^ nAccum32 ) & 0x80000000 )
				nAccum32 = ( nAccum32 << 1 ) ^ gx;
			else
				nAccum32 <<= 1;
			nData32 <<= 1;
		}
		table[i32] = nAccum32;
	}
}


// 生成CRC32 翻转表 第二项是77073096
void gen_normal_table(alt_u32 *table)
{
	alt_u32 gx = 0x04c11db7;
	alt_u32 temp,crc;
	for(int i = 0; i <= 0xFF; i++) 
	{
		temp=Reflect(i, 8);
		table[i]= temp<< 24;
		for (int j = 0; j < 8; j++)
		{
			unsigned long int t1,t2;
			unsigned long int flag=table[i]&0x80000000;
			t1=(table[i] << 1);
			if(flag==0)
			t2=0;
			else
			t2=gx;
			table[i] =t1^t2 ;
		}
		crc=table[i];
		table[i] = Reflect(table[i], 32);
	}
}



alt_u32 DIRECT_TABLE_CRC(alt_u8 *ptr,int len, alt_u32 * table) 
{
	alt_u32 crc = 0xffffffff; 
	alt_u8 *p= ptr;
	int i;
	for ( i = 0; i < len; i++ )
		crc = ( crc << 8 ) ^ table[( crc >> 24 ) ^ (alt_u8)Reflect((*(p+i)), 8)];
	return ~(alt_u32)Reflect(crc, 32) ;
}




alt_u32 Reverse_Table_CRC(alt_u8 *data, alt_32 len, alt_u32 * table)
{
	alt_u32 crc = 0xffffffff;  
	alt_u8 *p = data;
	int i;
	for(i=0; i <len; i++)
		crc =  table[( crc ^( *(p+i)) ) & 0xff] ^ (crc >> 8);
	return  ~crc ; 
}



//这是一个完整的以太网帧。最后四个字节 8b 6b f5 13是其FCS字段,用于与后面生成的CRC32对照
alt_u8  tx_data[] = {
        0xff,   0xff,   0xff,   0xff,   0xff,   0xff,   0x00,   0x1f,   //8
        0x29,   0x00,   0xb5,   0xfa,   0x08,   0x06,   0x00,   0x01,   //15
        0x08,   0x00,   0x06,   0x04,   0x00,   0x01,   0x00,   0x1f,   //24
        0x29,   0x00,   0xb5,   0xfa,   0xac,   0x15,   0x0e,   0xd9,   //32
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0xac,   0x15,   //40
        0x0e,   0x8e,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   //48
        0x00,   0x00 ,  0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   //56
        0x00,   0x00,   0x00,   0x00,   0x8b,   0x6b,   0xf5,   0x13    //64
};




int main()
{
    alt_u8 *data = tx_data;
    alt_u8 dataLen = sizeof(tx_data) -4;
  
	int sum = 256;
	int i = 0;

	//生成普通表,用于直接计算的表
	gen_direct_table(Table1);
	printf("Table1 :\n");
	for( i = 0; i < sum; i++)
	{
		if(i<16)
			printf("%08x ",Table1[i]);
	}
	printf("\n\n");


	//生成翻转表,是官方推荐的,故称其为normal_table
	gen_normal_table(Table2);
	printf("Table2 :\n");
	for( i = 0; i < sum; i++)
	{
		if(i<16)
			printf("%08x ",Table2[i]);
	}
	printf("\n\n");



	printf("dataLen = %d\n",dataLen);//打印数据长度,应该是60字节。



	//计算并打印出CRC32校验码,应该是0x13f56b8b

	//按照bit进行校验,最慢
	printf("Slow CRC by bit          : %08x\n",crc32_bit( data, dataLen, 0x04c11db7 ));
	//使用普通表,非官方,很慢
	printf("Direct Table  ref + xor  : %08x\n",DIRECT_TABLE_CRC (data,dataLen,Table1)); 
	//使用翻转表,官方推荐的,很快
	printf("Reverse Table  ref + xor : %08x\n",Reverse_Table_CRC(data,dataLen,Table2)); 


    system("pause");    
    return 0;
}



转自:  http://blog.csdn.net/delacroix_xu/article/details/7589333

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值