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

news2025/1/17 21:47:27

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 data
    uint32_t data_t = 0; //Process data of CRC computing

	uint16_t index_t = 63;  ///bit shifting index for initial '1' searching
	uint16_t index = 63;    //bit shifting index for CRC computing
	uint8_t rec = 0; //bit number needed to be compensated for next CRC computing

    uint32_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 data

    if(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' searching
 	 		index = 63;    //bit shifting index for CRC computing
 	 		rec = 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 register

    for (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;
            else
            	data_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 register

	uint16_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 data

        for (uint8_t j = 0; j < 16; j++)
        {
            if (data_t & 0x8000)
            	data_t = (data_t << 1) ^ crc_poly;
            else
            	data_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 register

	uint8_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 data

        for (uint8_t j = 0; j < 8; j++)
        {
            if (data_t & 0x8000)
            	data_t = (data_t << 1) ^ crc_poly;
            else
            	data_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 0x8005
	uint16_t data_t = 0; //CRC register

    for(uint32_t i = 0; i < len; i++)
    {
    	data_t ^= di[i]; //8-bit data

        for (uint8_t j = 0; j < 8; j++)
        {
            if (data_t & 0x0001)
            	data_t = (data_t >> 1) ^ crc_poly;
            else
            	data_t >>= 1;
        }
    }

    return data_t ^ 0xFFFF;
}

算法验证

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

android studio APP工程的项目结构说明

目录 1.APP工程的项目结构图 2.功能说明 2.1app 2.2Gradle Scripts 1.APP工程的项目结构图 2.功能说明 该项目下两个分类&#xff1a;一个是app&#xff08;代表app模块&#xff09;;另一个是Gradle Scripts。 2.1app app下面有3个子目录&#xff0c;功能如下&#xff1a;…

代码随想录之动态规划(力扣题号)

62 不同路径 很简单的dp class Solution {public int uniquePaths(int m, int n) {//58-02int[][] dp new int[m][n];//初始化for(int i 0;i<m;i){dp[i][0] 1;}for(int i 0;i<n;i){dp[0][i] 1;}for(int i1;i<m;i){for(int j 1;j<n;j){dp[i][j] dp[i-1][j]d…

开发小程序需要多少钱

开发小程序是如今网络世界中的一项重要活动&#xff0c;越来越多的企业和个人开始意识到通过开发小程序来提高自己的品牌价值和商业利益。那么&#xff0c;开发小程序需要多少钱呢&#xff1f; 首先&#xff0c;我们需要明确几个概念&#xff1a;小程序开发的成本通常包括以下…

kubespray-offline 下载并离线部署 kubernetes 自定义版本

kubespray-offline v2.21.0-0 默认部署 kubernetes 版本为 v1.25.6 我们以自定义部署 kubernetes 版本 v1.24.10为例。 下载&#xff1a;https://github.com/tmurakam/kubespray-offline/releases/tag/v2.21.0-0 unzip v2.21.0-0.zip cd kubespray-offline-2.21.0-0在下载介…

网络性能定位

根据tcp协议进行分析 目录 一、SYN_RECV阶段 1.1 确定半连接队列是否有丢包&#xff1a; 1.2 确定全连接队列是否有丢包现象 二、close_wait 三、TIME_WAIT ​ 一、SYN_RECV阶段 内核在监听套接字的时候&#xff0c;在三次握手时&#xff0c;会创建两个队列&#xff0c;在…

求解:使用Antv x6引入插件出现‘ToolItem’问题

一、前言 救救孩子&#xff0c;被困扰一周多了。 二、问题概述 2023年发布了antV X6的2.*版本&#xff0c;发现使用过程中会出现很多错误。 首先&#xff0c;个人使用的框架是Vue3&#xff0c;感觉有可能会是兼容性问题&#xff0c;但是有一个同事的电脑上是可以正常运行的。…

【C语言】基础语法2:运算符和表达式

❤️‍&#x1f525;前情提要❤️‍&#x1f525;   欢迎来到C语言基本语法教程   在本专栏结束后会将所有内容整理成思维导图&#xff08;结束换链接&#xff09;并免费提供给大家学习&#xff0c;希望大家纠错指正。本专栏将以基础出发&#xff0c;在之后的教程中将会不断…

【历史上的今天】4 月 19 日:摩尔定律被提出;微软发布 Pocket PC;第一个 FORTRAN 程序开始运行

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 4 月 19 日&#xff0c;在 1918 年的今天&#xff0c;克利福德贝里&#xff08;Clifford Berry&#xff09;出生。他是世界上第一台电子数字计算设备 Atanasof…

springboot中记录链路日志traceId

一 相关概念 在分布式服务架构下&#xff0c;一个 Web 请求从网关流入&#xff0c;有可能会调用多个服务对请求进行处理&#xff0c;拿到最终结果。在这个过程中每个服务之间的通信又是单独的网络请求&#xff0c;无论请求流经的哪个服务除了故障或者处理过慢都会对前端造成影…

基于PCA和NSST算法联合实现红外与可见光图像融合的Matlab仿真(完整源码+35组数据集)

以下是一个使用PCA和NSST算法实现红外与可见光图像融合的Matlab仿真完整源码。源码中只需修改红外图像&#xff08;IR.bmp&#xff09;和可见光图像&#xff08;VI.bmp&#xff09;名字即可 文章目录 效果展示数据集展示步骤说明完整源码下载地址 效果展示 最终融合效果展示&am…

cifar-10数据集+ResNet50

CIFAR-10-ObjectRecognition 作为一个古老年代的数据集&#xff0c;用ResNet来练一下手也是不错的。 比赛链接&#xff1a;CIFAR-10 - Object Recognition in Images | Kaggle 1. 预设置处理 创建各类超参数&#xff0c;其中如果是在Kaggle上训练的话batch_size是可以达到40…

安全狗深度参与编写《数据安全产品与服务观察报告》发布!

4月11日&#xff0c;由中国通信标准化协会联合数据安全推进计划主办的《数据安全产品与服务观察报告》发布会在北京顺利开展。 作为国内云原生安全领导厂商&#xff0c;安全狗也参与了数据安全推进计划《数据安全产品与服务观察报告》撰写。 此次活动针对数据安全产业、技术、…

排序算法合集(1)

前言&#xff1a; 今天我们正式开始讲述算法中的排序。排序算法是我们十分重要的算法&#xff0c;为什么呢&#xff1f; 排序是在各种情况下都非常重要的&#xff0c;无论是在人类社会还是在计算机科学中。以下是一些排序的重要性&#xff1a; 数据分析&#xff1a;在数据分析…

多连接数据库管理Navicat Premium 中文

Navicat Premium 是一款强大的数据库管理工具&#xff0c;它支持多种关系型数据库&#xff0c;包括 MySQL、MariaDB、Oracle、SQL Server、PostgreSQL 等等。 以下是 Navicat Premium 的一些主要功能&#xff1a; 连接管理&#xff1a;可以在一个用户界面中同时连接到多个数据库…

HCIP-6.7BGP的路径选择

BGP的路径选择 1、BGP路径属性1.1、路由选择1.1.1、BGP路由选择过程1.1.2、BGP选路参数2、BGP的路由策略2.1、Preferred-Value相当权重weight2.2、local-preference本地优先级2.3、AS_PATH经过的AS号 不常用2.4、Origin起源属性修改2.5、MED多出口鉴别器3、BGP非策略性选路原则…

【C++】右值引用(极详细版)

在讲右值引用之前&#xff0c;我们要了解什么是右值&#xff1f;那提到右值&#xff0c;就会想到左值&#xff0c;那左值又是什么呢&#xff1f; 我们接下来一起学习&#xff01; 目录 1.左值引用和右值引用 1.左值和右值的概念 2.左值引用和右值引用的概念 2.左值引用和右…

C++linux高并发服务器项目实践 day2

Clinux高并发服务器项目实践 day2 静态库的制作静态库命名规则静态库的制作 动态库的制作命名规则制作使用动态库与静态库的区别解决动态库连接失败问题静态库和动态库的对比静态库的优缺点动态库的优缺点 Makefile什么是MakefileMakefile文件命名和规则Makefile的使用工作原理…

SpringSpringBoot常用注解总结

0.前言 可以毫不夸张地说&#xff0c;这篇文章介绍的 Spring/SpringBoot 常用注解基本已经涵盖你工作中遇到的大部分常用的场景。对于每一个注解我都说了具体用法&#xff0c;掌握搞懂&#xff0c;使用 SpringBoot 来开发项目基本没啥大问题了&#xff01; 为什么要写这篇文章…

【分享】Excel表格的密码忘记了怎么办?附解决办法

我们知道通过设置密码可以保护Excel表格&#xff0c;可有时候设置后很久没用就把密码忘记了&#xff0c;而Excel并没有找回密码的选项&#xff0c;那要怎么办呢&#xff1f;今天小编就来分享一下忘记Excel密码的解决方法。 Excel表格可以设置多种密码&#xff0c;不同密码对应…

短视频平台-小说推文(Lofter)推广任务详情

​Lofter日结内测中&#xff0c;可能暂只对部分优质会员开放! 注意 Lofter 关键词7天未使用&#xff0c;可能会被下线。 Lofter 不再需要回填视频链接了。 接Lofter官方通知 关于近期部分博主反馈播放量高但搜索量很低的问题尤其是快手平台&#xff0c;我们做了代码、服务器…