任意长度CRC计算C语言代码

CRC任意长度数据,任意长度多项式计算。

说明:将待检验数据存入iap中,用strdatasize表示需要计算的数据的字节数;Divisor表示多项式,可以是任意长度字节。

使用方法:首先定义一个package_t类型的变量package。然后直接调用M2stream函数来得到CRC校验码。通过读取package中的元素crc所指向的值来得到CRC校验码。程序带有自检功能,即得到CRC校验码后进行验证。

#include 
#include 
#include 
#include 

#define u8	unsigned char
#define u16	unsigned short
#define u32	unsigned int
#define u64	unsigned long

/***************************************/
u8 iap[] =
{
	0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
	0x07,0x06,0x05,0x00,0x03,0x01,0x02,0x03,
	0x00,0x01,0x62,0x03,0x04,0x05,0x06,0x07,
	0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
	0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
	0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
	0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
	0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
	0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
	0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
	0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
	0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
	0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
	0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
	0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,
	0x07,0x06,0x05,0x05,0x00,0x01,0x02,0x03,
	0x07,0x06,0x05,0x24,0x00,0x71,0x02,0x03,
	0x00,0x80,0x02,0x03,0x04,0x05,0x06,0x07,0x00
};

/***************************************/
/**/

/*包大小*/
#define strdatasize		64
/*除数*/
const u8 Divisor[] = { 0xf5,0x84,0x26 };
/*人为错误开关*/
#define ErKey	0
/*人为错误索引*/
#define ErIn	4
/*人为错误更改值*/
#define ErVa	0xa8
/*寄存器值打印开关*/
#define  RegKey	0
/*检查时被除数流值打印开关*/
#define  StrKey	0

/**/
/***************************************/

typedef struct
{
	u8 *data;//数据 
	u32 newdataBnum;//新数据有效字节数 
}reg_t;

typedef struct
{
	u8 *data;//数据 
	u8 *datastart;//空间最初位置
	u8 *dataend;//数据尾指针
	u32 newdataBnum;//新数据有效字节数 
	u32 newdatabnum;//新数据有效位数 
}divisor_t;

typedef struct
{
	u8 *stream;//流 
	u8 *crc;//校验码指针 
	u8 *streamstart;//流空间最初起始位置
	u8 *streamend;//流尾 
	u32 dednum;//被除数流的有效位数 
	u32 zeronumstr;//流数据前导零 
	u32 LMcountadd;//流数据左移总位数 (不包含初始左移) 
	u32 countover;

	reg_t reg; //寄存器 

	divisor_t  divisor;//除数

} package_t;

//计算前导零
u8 ZeroNum(u32 Value)
{
	u8 num = 0;
	for (;!(Value&(1 << (32 - 1 - num)));num++)
	{
		if (num >= 32)
		{
			//printf("大于32\n");
			break;
		}
	}
	return num;
}

//获取流数据前导零
u32  ZeroNumStream(u8 *p, u32 num)
{
	u32 i = 0;
	while (1)
	{
		if (ZeroNum(p[i]) == 32)i++;
		else
			return 8 * i + (8 - (32 - ZeroNum(p[i])));
		if (i == num)
		{
			printf("流数据全位0\n");
			return num * 8;
		}
	}
}
/**********************************************************************************************/
//流数据左移函数
u8* ML_stream(u8 *p, u16 size, u16 n)
{
	u32 i = n / 8;
	u8 j = n % 8;
	u32 temp = 0;

	p += i;
	size -= i;
	while (1)
	{
		p[temp] = p[temp] << j;
		if (temp>size)
		{
			break;
		}
		if (temp> (8 - j));
		}
		temp++;
	}
	return p;
}

//流数据右移函数
u8* MR_stream(u8 *p, u16 size, u16 n)
{
	u16 i = n / 8;
	u8 j = n % 8;
	u16 temp = size - i - 1;

	while (1)
	{
		p[temp] = p[temp] >> j;
		if (temp == 0)
		{
			break;
		}
		p[temp] |= (p[temp - 1] & (~(0xff << j))) << (8 - j);
		temp--;
	}
	return p;
}

//获取初始寄存器
void GetReg(package_t *Package)
{
	u8 i = 0;

	Package->reg.newdataBnum = Package->divisor.newdataBnum;//寄存器字节数 
	Package->reg.data = Package->stream;//寄存器数据指针指向流的开头 
#if RegKey
	printf("寄存器: ");
	for (i = 0;ireg.newdataBnum;i++)
	{
		printf("%x ", Package->reg.data[i]);
	}
	printf("\n");
#endif
}

void init_package(package_t *Package)
{
	int i = 0;
	u8 temp = 0;

	/*保证除数不为0*/
	for (i = 0;idivisor.datastart=Package->divisor.data = (u8 *)malloc(sizeof(Divisor)); //申请除数空间
	Package->divisor.dataend = Package->divisor.data + sizeof(Divisor);
	memset(Package->divisor.data, 0, Package->divisor.dataend - Package->divisor.data);//空间清零
	memcpy(Package->divisor.data, Divisor, Package->divisor.dataend - Package->divisor.data);//生成初始除数 

	printf("初始除数: ");
	for (i = 0;idivisor.dataend - Package->divisor.data;i++)
	{
		printf("%x ", Package->divisor.data[i]);
	}
	printf("\n");

	Package->divisor.newdatabnum = (Package->divisor.dataend - Package->divisor.data) * 8 - ZeroNumStream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data);
	Package->divisor.data = ML_stream(Package->divisor.data, Package->divisor.dataend- Package->divisor.data, ZeroNumStream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data));
	//Package->divisor.newdataBnum = (Package->divisor.newdatabnum + 8 - 1) / 8;
	Package->divisor.newdataBnum = Package->divisor.dataend - Package->divisor.data;

	printf("除数有效位数:%d", Package->divisor.newdatabnum);
	printf("\n");
	printf("有效除数: ");
	for (i = 0;idivisor.dataend - Package->divisor.data;i++)
	{
		printf("%x ", Package->divisor.data[i]);
	}
	printf("\n");

	/*获取被除数流相关数据*/
	Package->streamstart=Package->stream = (u8 *)malloc(strdatasize + Package->divisor.newdataBnum); //申请被除数流空间
	Package->streamend = Package->stream + strdatasize + Package->divisor.newdataBnum;
	memset(Package->stream, 0, Package->streamend- Package->stream);//空间清零
	memcpy(Package->stream, iap, strdatasize);//生成初始被除数流 

	printf("初始被除数流: ");
	temp = 0;
	for (i = 0;istreamend - Package->stream;i++)
	{
		printf("%x ", Package->stream[i]);
		
		temp |= Package->stream[i];
	}
	printf("\n");
	if (!temp)
	{
		printf("被除数除数不能为0\n");
		exit(-1);
	}

	Package->zeronumstr = ZeroNumStream(Package->stream, Package->streamend - Package->stream);//获取流数据前导零
	printf("流数据前导零:%d\n", Package->zeronumstr);
	Package->dednum = strdatasize * 8 - Package->zeronumstr + Package->divisor.newdatabnum - 1;//被除数流有效位数
	Package->LMcountadd = 0;//初始化流数据左移总位数值 
	printf("被除数流有效位数:%d\n", Package->dednum);
	Package->stream = ML_stream(Package->stream, Package->streamend - Package->stream, Package->zeronumstr);//左移获得有效初始流数据 

	/*获取初始寄存器相关数据*/
	GetReg(Package);

	/*申请CRC校验值空间*/
	Package->crc = (u8 *)malloc(Package->reg.newdataBnum); //申请CRC校验值空间

	printf("初始化完成\n");
}

#if 1

void init_package_check(package_t *Package)
{
	u32 i = 0;
	u8 temp = 0;

	/*保证除数不为0*/
	for (i = 0;idivisor.data = Package->divisor.datastart; //指回初始地址
	Package->divisor.dataend = Package->divisor.data + sizeof(Divisor);
	memset(Package->divisor.data, 0, Package->divisor.dataend - Package->divisor.data);//空间清零
	memcpy(Package->divisor.data, Divisor, Package->divisor.dataend - Package->divisor.data);//生成初始除数 

	printf("初始除数: ");
	for (i = 0;idivisor.dataend - Package->divisor.data;i++)
	{
		printf("%x ", Package->divisor.data[i]);
	}
	printf("\n");

	Package->divisor.newdatabnum = (Package->divisor.dataend - Package->divisor.data) * 8 - ZeroNumStream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data);
	Package->divisor.data = ML_stream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data, ZeroNumStream(Package->divisor.data, Package->divisor.dataend - Package->divisor.data));
	//Package->divisor.newdataBnum = (Package->divisor.newdatabnum + 8 - 1) / 8;
	Package->divisor.newdataBnum = Package->divisor.dataend - Package->divisor.data;

	printf("除数有效位数:%d", Package->divisor.newdatabnum);
	printf("\n");
	printf("有效除数: ");
	for (i = 0;idivisor.dataend - Package->divisor.data;i++)
	{
		printf("%x ", Package->divisor.data[i]);
	}
	printf("\n");

	/*获取被除数流相关数据*/
	Package->stream = Package->streamstart; //
	Package->streamend = Package->stream + strdatasize + Package->divisor.newdataBnum;
	memset(Package->stream, 0, Package->streamend - Package->stream);//空间清零
	memcpy(Package->stream, iap, strdatasize);//生成初始被除数流 

	for (i = 0;ireg.newdataBnum;i++)
	{
		Package->stream[strdatasize + i] = Package->crc[i];//将CRC校验值写入被除数流 
	}

	printf("被除数流: ");
	for (i = 0;istreamend - Package->stream;i++)
	{
		printf("%x ", Package->stream[i]);
	}
	printf("\n");

	Package->zeronumstr = ZeroNumStream(Package->stream, Package->streamend - Package->stream);//获取流数据前导零
	printf("流数据前导零:%d\n", Package->zeronumstr);
	Package->dednum = strdatasize * 8 - Package->zeronumstr + Package->divisor.newdatabnum - 1;//被除数流有效位数
	Package->LMcountadd = 0;//初始化流数据左移总位数值 
	printf("被除数流有效位数:%d\n", Package->dednum);
	Package->stream = ML_stream(Package->stream, Package->streamend - Package->stream, Package->zeronumstr);//左移获得有效初始流数据 

	/*获取初始寄存器相关数据*/
	GetReg(Package);
}

u8 check(u8 *p, u16 size)
{
	u32 i = 0;
	u8 temp = 0;

	for (i = 0;istream[ErIn] = ErVa;//制造人为错误 
#endif

	printf("开始验证-->\n");

	while (1)
	{
		//异或运算
		for (i = 0;ireg.newdataBnum;i++)
		{
			Package->reg.data[i] ^= Package->divisor.data[i];
		}
#if StrKey
		printf("被除数流数据为: ");
		for (i = 0;istreamend - Package->stream;i++)
		{
			printf("%x ", Package->stream[i]);
		}
		printf("\n");
#endif

		if (check(Package->stream, Package->streamend - Package->stream) == 0)
		{
			printf("LMcountadd=%d\n", Package->LMcountadd - Package->zeronumstr);
			break;
		}
		else if (Package->LMcountadd>Package->dednum)
		{
			printf("检查失败:左移次数过大\n");
			exit(1);
		}

		//Sleep(500);
		//左移
		Package->zeronumstr = ZeroNumStream(Package->stream, strdatasize + sizeof(Divisor));//获取流数据前导零
		Package->stream=ML_stream(Package->stream, strdatasize + sizeof(Divisor), Package->zeronumstr);
		Package->LMcountadd += Package->zeronumstr;

		//更新寄存器
		GetReg(Package);
	}
	printf("检查成功\n");
	return 1;
}
#endif

//模2除法针对于流数据 
u8 M2stream(package_t *Package)
{
	int i = 0;

	init_package(Package);//初始化结构体变量 

	printf("被除数流: ");
	for (i = 0;istreamend - Package->stream;i++)
	{
		printf("%x ", Package->stream[i]);
	}
	printf("\n");

	while (1)
	{
		//异或运算
		for (i = 0;ireg.newdataBnum;i++)
		{
			Package->reg.data[i] ^= Package->divisor.data[i];
		}
#if StrKey
		printf("被除数流数据为(%d): ", Package->streamend - Package->stream);
		for (i = 0;istreamend - Package->stream;i++)
		{
			printf("%x ", Package->stream[i]);
		}
		printf("\n");
#endif
		//左移
		Package->zeronumstr = ZeroNumStream(Package->stream, Package->streamend - Package->stream);//获取流数据前导零
		Package->stream=ML_stream(Package->stream, Package->streamend - Package->stream, Package->zeronumstr);
		Package->LMcountadd += Package->zeronumstr;

		//更新寄存器
		GetReg(Package);

		//检查是否操作完成 
		if (Package->LMcountadd >= Package->dednum - Package->divisor.newdatabnum + 1)
		{
			i = (Package->dednum - Package->divisor.newdatabnum + 1) - (Package->LMcountadd - Package->zeronumstr);//非校验值位数-该次左移前的总前导零=还需计算的位数
			printf("i=%d\n", i);
			printf("前导零:%d\n", Package->zeronumstr);
			if (Package->zeronumstr - i > Package->reg.newdataBnum)
			{
				Package->reg.data = MR_stream(Package->reg.data, Package->reg.newdataBnum, Package->reg.newdataBnum);
			}
			else
			{
				Package->reg.data = MR_stream(Package->reg.data, Package->reg.newdataBnum, Package->zeronumstr - i);//因为实际上计算到极限并且左移所以需要右移超出本该计算的位数
			}
			printf("校验码: ");
			for (i = 0;ireg.newdataBnum;i++)
			{
				printf("%x ", Package->reg.data[i]);
			}
			printf("\n");
			Package->countover = Package->LMcountadd - Package->zeronumstr;
			printf("countover=%d\n", Package->countover);

			//保存CRC校验值 
			memset(Package->crc, 0, Package->reg.newdataBnum);//空间清零
			memcpy(Package->crc, Package->reg.data, Package->reg.newdataBnum);//保存CRC校验值

			break;
		}
	}

	if (M2streamCheck(Package))
		return 1;//返回包含校验码的数据 
	else
		return 0;
}

int main()
{
	package_t package;

	M2stream(&package);

	return 0;
}

 

你可能感兴趣的:(嵌入式,CRC校验,C语言)