C语言CRC-16 MAXIM格式校验函数

news/2024/5/17 15:20:24/文章来源:https://blog.csdn.net/hwytree/article/details/130114675

C语言CRC-16 MAXIM格式校验函数

CRC-16校验产生2个字节长度的数据校验码,通过计算得到的校验码和获得的校验码比较,用于验证获得的数据的正确性。基本的CRC-16校验算法实现,参考: C语言标准CRC-16校验函数。

不同厂家通过对输入数据前处理和输出数据后处理的方式不同,又产生了不同的厂家校验函数,这里介绍MAXIM格式的CRC-16校验函数。MAXIM格式对输入数据,按照单个字节进行位反序。对于输出的校验码,进行整体位反序, 然后异或0xFFFF。

生成多项式为x^16 + x^15 + x^2 + 1

正向算法

正向算法是符合标准CRC-16的计算理论,从左向右计算,也即计算过程中移位时,向左移出。几种正向算法的实现如下:

CRC-16 MAXIM格式校验函数一(8位输入数据格式,64位装载计算):

#include <stdio.h>
#include <stdlib.h>
uint16_t PY_CRC_16_MAXIM(uint8_t *di, uint32_t len)
{uint32_t crc_poly = 0x00018005;  //X^16+X^15+X^2+1 total 17 effective bits. Computed total data shall be compensated 16-bit '0' before CRC computing.uint8_t *datain;uint64_t cdata = 0; //Computed total datauint32_t data_t = 0; //Process data of CRC computinguint16_t index_t = 63;  ///bit shifting index for initial '1' searchinguint16_t index = 63;    //bit shifting index for CRC computinguint8_t rec = 0; //bit number needed to be compensated for next CRC computinguint32_t cn=(len+2)/6;uint32_t cr=(len+2)%6;uint32_t j;datain = malloc(len+2);for(j=0;j<len;j++){datain[j] = 0;for(uint8_t m=0; m<=7; m++){datain[j] |= ( ( di[j]>>(7-m) ) & 1 ) << m;}}datain[len] = 0; datain[len+1] = 0;//Compensate 16-bit '0' for input dataif(len<=6)   //Mount data for only one segment{for(j=0;j<=(len+1);j++){cdata = (cdata<<8);cdata = cdata|datain[j];}cn = 1;}else{if(cr==0){cr = 6;}else if(cr==1){cr = 7;}else if(cr==2){cr = 8;}else{cn++;}for(j=0;j<cr;j++){cdata = (cdata<<8);cdata = cdata|datain[j];}}do{cn--;while(index_t>0){if( (cdata>>index_t)&1 ){index = index_t;index_t = 0;data_t |= (cdata>>(index-16));{data_t = data_t ^ crc_poly;}while((index!=0x5555)&&(index!=0xaaaa)){for(uint8_t n=1;n<17;n++){if ((data_t>>(16-n))&1) {rec = n;break;}if (n==16) rec=17;}if((index-16)<rec){data_t = data_t<<(index-16);data_t |=  (uint32_t)((cdata<<(64-(index-16)))>>(64-(index-16)));index = 0x5555;}else{for(uint8_t i=1;i<=rec;i++){data_t = (data_t<<1)|((cdata>>(index-16-i))&1) ;}if(rec!= 17){data_t = data_t ^ crc_poly;index -= rec;}else{data_t = 0;index_t = index-16-1;index = 0xaaaa;}}}if(index==0x5555) break;}else{index_t--;if(index_t<16) break;}}if(cn>0) //next segment{cdata = data_t&0x00ffff;for(uint8_t k=0;k<6;k++){cdata = (cdata<<8);cdata = cdata|datain[j++];}data_t = 0;index_t = 63;  ///bit shifting index for initial '1' searchingindex = 63;    //bit shifting index for CRC computingrec = 0; //bit number needed to be compensated for next CRC computing}}while(cn>0);free(datain);uint16_t i_data_t = 0;for(uint8_t n=0; n<=15; n++){i_data_t |=  ( ( data_t>>(15-n) ) & 1 ) << n;}return i_data_t ^ 0xFFFF;
}

CRC-16 MAXIM格式校验函数二(8位输入数据格式):

uint16_t PY_CRC_16_S_MAXIM(uint8_t *di, uint32_t len)
{uint16_t crc_poly = 0x8005;  //X^16+X^15+X^2+1 total 16 effective bits without X^16. Computed total data shall be compensated 16-bit '0' before CRC computing.uint32_t clen = len+2;uint8_t cdata[clen] ;for(uint32_t j=0;j<len;j++){cdata[j] = 0;for(uint8_t m=0; m<=7; m++){cdata[j] |= ( ( di[j]>>(7-m) ) & 1 ) << m;}}cdata[len]=0; cdata[len+1]=0;uint16_t data_t = (((uint16_t)cdata[0]) << 8) + cdata[1]; //CRC registerfor (uint32_t i = 2; i < clen; i++){for (uint8_t j = 0; j <= 7; j++){if(data_t&0x8000)data_t = ( (data_t<<1) | ( (cdata[i]>>(7-j))&0x01) ) ^ crc_poly;elsedata_t = ( (data_t<<1) | ( (cdata[i]>>(7-j))&0x01) ) ;}}uint16_t i_data_t = 0;for(uint8_t n=0; n<=15; n++){i_data_t |=  ( ( data_t>>(15-n) ) & 1 ) << n;}return i_data_t ^ 0xFFFF;
}

CRC-16 MAXIM格式校验函数三(16位输入数据格式):

uint16_t PY_CRC_16_T16_MAXIM(uint16_t *di, uint32_t len)
{uint16_t crc_poly = 0x8005;  //X^16+X^15+X^2+1 total 16 effective bits without X^16. uint16_t data_t = 0; //CRC registeruint16_t cdata[len];for(uint32_t j=0;j<len;j++){cdata[j] = 0;for(uint8_t m=0; m<=7; m++){cdata[j] |= ( ( ( (di[j]>>8)>>(7-m) ) & 1 ) << m ) | ( ( ( ( (di[j]&0x00ff)>>(7-m) ) & 1 ) << m ) <<8 );}}for(uint32_t i = 0; i < len; i++){data_t ^= cdata[i]; //16-bit datafor (uint8_t j = 0; j < 16; j++){if (data_t & 0x8000)data_t = (data_t << 1) ^ crc_poly;elsedata_t <<= 1;}}uint16_t i_data_t = 0;for(uint8_t n=0; n<=15; n++){i_data_t |=  ( ( data_t>>(15-n) ) & 1 ) << n;}return i_data_t ^ 0xFFFF;
}

CRC-16 MAXIM格式校验函数四(8位输入数据格式):

uint16_t PY_CRC_16_T8_MAXIM(uint8_t *di, uint32_t len)
{uint16_t crc_poly = 0x8005;  //X^16+X^15+X^2+1 total 16 effective bits without X^16. uint16_t data_t = 0; //CRC registeruint8_t cdata[len];for(uint32_t j=0;j<len;j++){cdata[j] = 0;for(uint8_t m=0; m<=7; m++){cdata[j] |= ( ( di[j]>>(7-m) ) & 1 ) << m;}}for(uint32_t i = 0; i < len; i++){data_t ^= cdata[i]<<8; //8-bit datafor (uint8_t j = 0; j < 8; j++){if (data_t & 0x8000)data_t = (data_t << 1) ^ crc_poly;elsedata_t <<= 1;}}uint16_t i_data_t = 0;for(uint8_t n=0; n<=15; n++){i_data_t |=  ( ( data_t>>(15-n) ) & 1 ) << n;}return i_data_t ^ 0xFFFF;
}

反向算法

反向算法是从由右向左计算,也即计算过程中移位时,向右移出。而计算过程中的输入数据高优先计算位和校验参数的对齐关系不变。因此把一个字节放在CRC计算寄存器的最低字节时,对于MAXIM格式,最右侧最低位实际上是高优先计算位,而校验参数要相应倒序,从而计算位置对照关系不变。

CRC-16 MAXIM格式校验函数五(反向算法,8位输入数据格式):

uint16_t PY_CRC_16_T8_MAXIM_i(uint8_t *di, uint32_t len)
{uint16_t crc_poly = 0xA001; //Bit sequence inversion of 0x8005uint16_t data_t = 0; //CRC registerfor(uint32_t i = 0; i < len; i++){data_t ^= di[i]; //8-bit datafor (uint8_t j = 0; j < 8; j++){if (data_t & 0x0001)data_t = (data_t >> 1) ^ crc_poly;elsedata_t >>= 1;}}return data_t ^ 0xFFFF;
}

算法验证

5种算法结果相同:
在这里插入图片描述
通过在线CRC工具对照验证成功:
在这里插入图片描述
–End–

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_285753.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于ESP32和blinker的红外小夜灯控制

一. 系统设计及框图&#xff1a; 本设计可以实现通过手机APP使用蓝牙或WIFI远程控制红外设备&#xff0c;也可以通过离线语音模块语音控制红外设备。可以控制市面上常见的NEC格式的红外设备, 这里是控制小夜灯&#xff0c;其它红外设备在控制原理上是相通的。本设计可用作课程…

如何免费使用ChatGPT 4?

自从ChatGPT发布以来&#xff0c;它就取得了巨大的成功。无论是常春藤法学考试还是商学院作业&#xff0c;ChatGPT都被用于各种试验。统计数据显示&#xff0c;ChatGPT每月吸引约9600万用户。随着ChatGPT的巨大成功&#xff0c;Open AI最近推出了它的最新版本&#xff0c;名为“…

Docker本地推送到hub,以及上传时遇到的问题解决

1.在本地创建一个 Dockerfile FROM ubuntu:latest RUN apt-get update && apt-get install -y curl CMD ["curl", "https://www.baidu.com"]2.在本地构建 Docker 镜像 在创建本地docker镜像的时候[TAG] .和[TAG] /PATH/TO 需要注意dockerfile文件…

Rust China Conf 2023 筹备启动:议题征集开始

大会介绍Rust China Conf 2023 由 Rust 中文社区发起主办、知名企业和开源组织联合协办&#xff0c;是年度国内规模最大并唯一的 Rust 线下大型会议&#xff0c;深受 Rust 中文社区开发者与相关企业的喜爱与推崇。本次大会为线下会议&#xff0c;将于6月17日-18日在上海举办&am…

企业推广常用的网络推广方法有哪些?

网络推广是指通过互联网向目标用户推广产品、服务或品牌的过程&#xff0c;其主要目的是为了扩大业务范围&#xff0c;提高企业知名度&#xff0c;增加销售额。在当今的数字化时代&#xff0c;网络推广已经成为了企业不可或缺的一部分。本文将介绍一些常见的网络推广方法和途径…

yolov5详解与改进

https://github.com/z1069614715/objectdetection_script YOLOV5改进-Optimal Transport Assignment Optimal Transport Assignment&#xff08;OTA&#xff09;是YOLOv5中的一个改进&#xff0c;它是一种更优的目标检测框架&#xff0c;可以在保证检测精度的同时&#xff0c…

一份两年前一个月的工作经历没写在简历上,背调前主动坦白,却被背调公司亮了红灯,到手的offer没了!...

只因为简历上漏写了一份一个月的工作&#xff0c;就被亮了背调红灯&#xff0c;这公平吗&#xff1f;一位网友就被狠狠坑了一把&#xff0c;来看下他的遭遇&#xff1a;他有一份两年前、时长一个月的工作经历没写在简历上&#xff0c;背调前主动和背调公司还有招聘方hr都说了这…

【Linux】浅析Input子系统

文章目录1. 框架1.1 数据结构1.2 evdev_handler1.3 evdev_init1.4 input_register_handler2. 应用如何打开节点并读取到事件数据2.1 evdev_fops2.2 evdev_open2.3 evdev_release2.4 evdev_read2.5 evdev_write2.6 evdev_poll2.7 evdev_fasync2.8 evdev_ioctl2.9 evdev_ioctl_co…

opcua 获取自定义结构体的成员值

示例中的节点值的数据类型为自定义的多层嵌套的结构体如下: 获取改结构体的成员值: import opcua from opcua import ua from opcua.ua import uatypesdef user_defined_vars(value_dict, # 自定义数据类型的变量值name_prefix, # 成员名前缀比如aa.bbdata_dict2, # 用…

API 接口设计

1、场景描述 比如说我们要做一款 APP&#xff0c;需要通过 api 接口给 app 提供数据。假设我们是做商城&#xff0c;比如我们卖书的。我们可以想象下这个 APP 大概有哪些内容&#xff1a; 1&#xff09;首页&#xff1a;banner 区域&#xff08;可以是一些热门书籍的图片做推广…

第十四届蓝桥杯大赛软件赛省赛 C/C++ 大学 A 组题解+个人总结

提示&#xff1a;此题解为本人自己解决&#xff0c;如有差错请大家多多指正。 文章目录题解总结一、幸运数1.试题2.解法3.代码二、[有奖问答](https://blog.csdn.net/A2105153335/article/details/130038980?spm1001.2014.3001.5501)三、[平方差](https://blog.csdn.net/A2105…

js flyout 2: VScroll

目录版权描述测试页面showFlyout问题1 - scroll 实现可能不准?问题2 - 容器内容重排可导致浮层错位关于重排小结附录 - 完整代码版权 本文为原创, 遵循 CC 4.0 BY-SA 版权协议, 转载需注明出处: https://blog.csdn.net/big_cheng/article/details/130101031. 文中代码属于 pu…

数据结构与算法01 稀疏数组

稀疏数组问题 当一个二维数组中大部分数据都是0&#xff0c;对这个数组直接进行存储会很浪费空间&#xff0c;因此利用稀疏数组进行压缩&#xff0c;稀疏数组第一行的第一个元素是原二维数组行数。&#xff0c;第一行的第二个元素是原二维数组的列数&#xff0c;如图为11行11列…

6.S081——虚拟内存部分——xv6源码完全解析系列(4)

0.briefly speaking 点击跳转到上一篇博客 好&#xff0c;现在进入下一个话题&#xff0c;就是物理内存分配器(kernel/kalloc.c)。在简单介绍完内核态的物理内存分配器之后&#xff0c;之后简单带过一下两个头文件riscv.h和memorylayout.h这两个头文件&#xff0c;因为它们都…

2.5d风格的游戏模式如何制作

文章目录一、 介绍二、 绘制瓦片地图三、 添加场景物体&#xff0c;添加碰撞器四、 创建玩家五、 创建玩家动画六、 玩家脚本七、 2d转换成2.5d八、 “Q”键向左转动视角、“E”键向右转动视角九、 下载工程文件一、 介绍 制作一个类似饥荒风格的2.5d游戏模板。 2.5D游戏是指以…

表id自增的方法

数据库主键id自增的方法&#xff0c;列举了几种如下 一、数据库自增&#xff08;部分数据库支持&#xff09; 创建表的时候设置id自增即可&#xff0c;或者后期修改表id自增 # mysql 语法 create table your_table_name(id bigint(20) not null auto_increment primary key …

Markdown 语法大全

Markdown是一种轻量级标记语言&#xff0c;常用于撰写博客、文档、论文等。它可以让你使用易读易写的纯文本格式来编写文档&#xff0c;然后通过转换成有效的HTML文档进行发布。以下是Markdown常用的语法&#xff1a; 这里写目录标题标题列表引用一级引用嵌套引用粗体和斜体删除…

Java集合——Set接口学习总结

一、HashSet实现类 1.常用方法 增加&#xff1a;add(E e)删除&#xff1a;remove(Object o)、clear()修改&#xff1a;查看&#xff1a;iterator()判断&#xff1a;contains(Object o)、isEmpty()常用遍历方式&#xff1a;Set<String> set new HashSet<String>()…

Spark 对hadoopnamenode-log文件进行数据清洗并存入mysql数据库

一.查找需要清洗的文件 1.1查看hadoopnamenode-log文件位置 1.2 开启Hadoop集群和Hive元数据、Hive远程连接 具体如何开启可以看我之前的文章&#xff1a;(10条消息) SparkSQL-liunx系统Spark连接Hive_难以言喻wyy的博客-CSDN博客 1.3 将这个文件传入到hdfs中&#xff1a; hd…

windows系统管理_windows server 2016 用户管理

用户账户的概述 **计算机用户账户&#xff1a;**由将用户定义到某一系统的所有信息组成的记录,账户为用户或计算机提供安 全凭证&#xff0c;包括用户名和用户登陆所需要的密码&#xff0c;以及用户使用以便用户和计算机能够登录到网络并 访问域资源的权利和权限。不同的身份拥…