CRC-16/XModem参数模型 C语言实现

在学习超子说物联网“GD32/STM32单片机,OTA网络远程升级,手把手编写BootLoader程序教程”视频时,本地传输程序需要使用分段传输,采用XModem协议,使用到16位CRC校验,而STM32自带的是一个32位CRC计算单元,所以我们需要手动实现一个CRC校验功能。结合超哥的代码和前辈的帖子,开此贴以作学习记录。如果本帖有侵权还请联系我删除!

简单介绍

​ CRC全名(Cyclic Redundancy Check,循环冗余校验)。CRC-16中的16指的是算法中使用了16位(2字节)的校验码,而非传入数据的长度等其它含义。

​ CRC对我们来说只是协议中的校验工具,我们关心实现而不在意原理,所以我们直接给出代码编写逻辑,参考自C语言版CRC-16系列校验算法,五行字让我会写代码,非常感谢!

​ 个人愚见,CRC(循环冗余校验)名字里的“循环”体现在:我们所进行的所有操作都在处理INIT这个初值,最终输出的返回值也是它,记住这点将帮助我们理解编写逻辑。

	 1.根据所用CRC-16协议选择初始值CRC16_INIT和多项式 CRC16_POLY的初值;
	 2.将当前待校验数据与CRC16_INIT的高8位异或;
	 3.判断CRC16_INIT的最高位,若该位为 0 则左移一位,若为 1 则左移一位并与CRC16_POLY异或;
	 4.重复第3步直至8位全部移位计算结束;
	 5.重复将所有输入数据完成2、3、4步操作,所得16位数即16位CRC校验码。

第1步中,我们通过CRC(循环冗余校验)在线计算这个网站可以获知初始值 INIT(Hex)和多项式 POLY(Hex),如下图所示:

CRC-16/在这里插入图片描述

代码实现

​ 最终的代码实现如下所示:

u16 XModem_CRC16(u8 *data, u16 datalen)
{
	u16 CRC16_INIT = 0x0000;	//初值
	u16 CRC16_POLY = 0x1021;	//多项式值
	
	while(datalen){
		CRC16_INIT = ((*data) << 8) ^ CRC16_INIT;	//将当前待校验数据与CRC16_INIT的高8位异或;
		for(u8 i=0; i < 8; i++){					//一个for循环完成一个8位数据的校验计算
			if((CRC16_INIT & 0x8000) == 0){			//判断CRC16_INIT的最高位
				CRC16_INIT = CRC16_INIT << 1;
			}else{
				CRC16_INIT = (CRC16_INIT << 1) ^ CRC16_POLY;
			}
		}
		data++;			//指向下一个数据
		datalen--;		//所有数据是否校验完成的标志
	}
	return CRC16_INIT;	//返回校验值
}

实验测试

​ 我们传入五个数据,获得最终校验值。

u8 test1[5] = {0x1,0x2, 0x3,0x4,0x5};
u1_printf("test1 XModem_CRC16 = %x !\r\n",XModem_CRC16(test1, 5));
u8 test2[5] = {0x5,0x6, 0x7,0x6,0x5};
u1_printf("test2 XModem_CRC16 = %x !\r\n",XModem_CRC16(test2, 5));

​ 串口打印结果如下:

在这里插入图片描述

​ 我们来看一下CRC(循环冗余校验)在线计算上的结果:

在这里插入图片描述

​ 两个结果均正确,实验成功!

ps:个人水平有限,如果文中有错误还请指正!

  • 15
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值