fcs 校验和计算 以太网帧CRC校验 C语言

  • Post author:
  • Post category:其他


#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_u32 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;

}