CRC16校验

CRC校验本质就是将数据视作一个大整数使用指定POLY进行模二除法(异或)。行业上的CRC算法和网页上( 比如CRC(循环冗余校验)在线计算_ip33.com)的算法刚好左右相反比如0x8408会视为0x1021。这或许是手写和计算机数字表达方式不一致导致的。所以下面代码考虑了这点而写的。转换算法用碟式运算。此代码是基于c51设计的,仅是为了节省代码空间,所以尽量设计更通用。

#define CONFIG_CRC_POLY_INVERT 0 // 行业算法一般不使用反转,如果要在网页得出一致结果可以在调试时使用反转
 
typedef struct CRC16_PARAMS_ST{
	u16 preval;             // crc初始值
	u16 xorout;             // 输出值异或
	u16 poly;               // 表达式
	bt is_input_invert;     // 是否输入反转
	bt is_output_invert;    // 是否输出发转
}CRC16_PARAMS;
 
// 8位数据反转
u8 invert_u8_in_bit(u8 val)
{
	u8 _dat;
	_dat = (val << 4)|(val >> 4);
	_dat = ((_dat << 2) & 0xcc)|((_dat >> 2) & 0x33);
	_dat = ((_dat << 1) & 0xaa)|((_dat >> 1) & 0x55);
	return _dat;
}
 
// 16位数据反转
u16 invert_u16_in_bit(u16 val)
{
	u16 _dat;
	_dat = (val << 8) | (val >> 8);
	_dat = ((_dat << 4) & 0xF0FF) | ((_dat >> 4) & 0xFF0F);
	_dat = ((_dat << 2) & 0xCCCC) | ((_dat >> 2) & 0x3333);
	_dat = ((_dat << 1) & 0xAAAA) | ((_dat >> 1) & 0x5555);
	return _dat;
}
 
u16 crypto_crc16_common(u8 xdata* buf, u16 len, CRC16_PARAMS xdata* params)
{
    u8 _i, _dat;
	u16 _chksum;
	
#if CONFIG_CRC_POLY_INVERT
	u16 _poly;
	_poly = invert_u16_in_bit(params->poly);
#else
	#define _poly (params->poly)
#endif
	
	_chksum = params->preval;
	
	for (; len > 0; len--)
	{
		if(!params->is_input_invert)
			_dat = invert_u8_in_bit(buf[0]);
		else 
			_dat = buf[0]; 
 
		_chksum ^= _dat; buf++;
			
		for (_i = 0; _i < 8; _i++) 
		{
			if (_chksum & 1)
				_chksum = (_chksum >> 1) ^ _poly;
			else
				_chksum >>= 1; 
		}
	}
		
	if(!params->is_output_invert)
		_chksum = invert_u16_in_bit(_chksum);
	
    return(_chksum ^ params->xorout);
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值