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

article/2025/10/31 7:16:50

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

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

不同应用规范通过对输入数据前处理和输出数据后处理的方式不同,又产生了不同的应用规范校验函数,这里介绍CCITT-FALSE格式的CRC-16校验函数。CCITT-FALSE格式对输入数据,预置值为0XFFFF(当做最初的余数)。

生成多项式为x^16 + x^12 + x^5 + 1
由于反向算法更适合于有输入字节倒位序和输出整体数据倒位序的情况,这里只介绍正向算法。

正向算法

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

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

#include <stdio.h>
#include <stdlib.h>
uint16_t PY_CRC_16_CCIT_FALSE(uint8_t *di, uint32_t len)
{uint32_t crc_poly = 0x00011021;  //X^16+X^12+X^5+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] = di[j];}datain[len] = 0; datain[len+1] = 0;//Compensate 16-bit '0' for input datadatain[0] ^= 0xff; datain[1] ^= 0xff;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' searchingindex = 63;    //bit shifting index for CRC computingrec = 0; //bit number needed to be compensated for next CRC computing}}while(cn>0);free(datain);return (uint16_t)data_t;
}

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

uint16_t PY_CRC_16_S_CCIT_FALSE(uint8_t *di, uint32_t len)
{uint16_t crc_poly = 0x1021;  //X^16+X^12+X^5+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] ;memcpy(cdata, di, len); cdata[len]=0; cdata[len+1]=0;cdata[0] ^= 0xff; cdata[1] ^= 0xff;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) ) ;}}return data_t;
}

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

uint16_t PY_CRC_16_T16_CCIT_FALSE(uint16_t *di, uint32_t len)
{uint16_t crc_poly = 0x1021;  //X^16+X^12+X^5+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] = (di[j]>>8 | di[j]<<8);}cdata[0] ^= 0xffff;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;}}return (data_t);
}

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

uint16_t PY_CRC_16_T8_CCIT_FALSE(uint8_t *di, uint32_t len)
{uint16_t crc_poly = 0x1021;  //X^16+X^12+X^5+1 total 16 effective bits without X^16. uint16_t data_t = 0xffff; //CRC registerfor(uint32_t i = 0; i < len; i++){data_t ^= di[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;}}return (data_t);
}

算法验证

4种算法结果相同:
在这里插入图片描述

通过在线CRC工具对照验证成功:
在这里插入图片描述

–End–


http://chatgpt.dhexx.cn/article/8DCqnpmH.shtml

相关文章

Eclipse与JDK、JRE的关系

1、首先说明的是&#xff0c;eclipse人家需要jre&#xff0c;而不需要jdk&#xff0c;人家内置的有。你只要在你的电脑上安装一个jre就行。至于jdk&#xff0c;它内置的有2、eclise也不要求你jdk或者jre配置环境变量&#xff0c;毕竟友不用notepad写代码&#xff0c;dos编译执行…

JDK、JRE、JVM三者关系

jdk、jre、jvm三者有什么关系&#xff1f; JDK ☁️ JDK&#xff1a;Java开发工具包&#xff1b; ☁️ JDK中包含了以下内容&#xff1a; ⚡️ Java虚拟机&#xff1a;用于运行Java程序&#xff1b; ⚡️ 核心类库&#xff1a;核心类库中是已经编写好的Java代码&#xff0…

JRE和JDK

JRE和JDK JRE(Java运行环境)Java Runtime Environment 包括Java虚拟机(JVM Java VirtualMachine)和Java程序所需的核心类库等&#xff0c;如果想要运行一个开发好的Java程序&#xff0c;计算机中只需要安装JRE即可。 JRE 核心类库 JVM JDK(Java开发工具包)Java Development…

JDK,JRE,JVM三者间的关系,以及JDK、JRE的主要结构

一、JDK&#xff0c;JRE是什么&#xff1f; 1.JDK 是提供给 Java 开发人员使用的&#xff0c;其中包含了 java 的开发工具&#xff0c;也包括了 JRE。所以安装了JDK&#xff0c;就不用在单独安装JRE了。 2.JRE是包括 Java 虚拟机 (JVM J ava V irtual M achine) 和 Java 程…

【jdk与jre 的关系】

**jdk与jre 的关系** jdk中包含jre和核心开发工具, jre中包含jvm和核心开发类库 jdk中包含jre和核心开发工具, jre中包含jvm和核心开发类库 注: JVM是指Java虚拟机。

JDK、JRE和JVM三者之间关系

JDK、JRE和JVM三者之间关系 很多程序员已经写了很长一段时间java了&#xff0c;依然不明白JDK,JRE,JVM的区别。今天个人总结一下它们三者的关系、区别。 JDK&#xff08;Java Development Kit&#xff09;是针对Java开发员的产品&#xff0c;是整个Java的核心&#xff0c;包括了…

JDK与JRE的安装与配置

这两天为了这个JAVA的编译环境JDK和JRE的配置可花了不少心思&#xff0c;曾还一度把电脑的注册表给误删了&#xff0c;导致电脑重装了系统&#xff0c;这是血的教训。我买了一本学习JAVA的书&#xff0c;看了里面的视频终于把编译环境给配置好了&#xff0c;其实非常简单。 开始…

jdk与jre

jdk与jre jdk1.8目录jdk1.8下的bin目录jdk1.8下的jre目录jdk1.8下的lib目录 jdk1.8目录 安装好的JDK路径下目录如下&#xff1a;有bin、db、include、jre、lib、COPYRIGHT、javafx-src.zip、LICENSE、README.html、release、src.zip、THIRDPARTYLICENSEREADME.txt、THIRDPARTY…

【jdk和jre】

JRE和JDK JRE (Java Runtime Environment)\n是Java程序的运行时环境&#xff0c;包含JVM和运行时所需要的核心类库。 我们想要运行一个已有的Java程序&#xff0c; 那么只需安装JRE即可。 JDK (Java Development Kit)\n是Java程序开发工具包&#xff0c;包含JRE和开发人员使用…

jdk没有jre的解决方法

jdk11以上没有jre的解决方法 小白篇 安装的jdk没有jre(JDK11以上版本)解决方法方法一&#xff1a;步骤1&#xff1a;步骤2&#xff1a; 注意:方法二&#xff1a;步骤1&#xff1a;步骤2&#xff1a; 值得注意的是&#xff1a;1.2. 安装的jdk没有jre(JDK11以上版本) 我猜你安装…

jdk、jre、jvm分别是什么?有什么联系?

目录 介绍 JDK和JRE JRE和JVM 介绍 JDK&#xff1a;是Java Development Kit的缩写&#xff0c;是Java的开发工具包&#xff0c;JDK是整个JAVA的核心。它提供了编译、运行Java程序所需的各种工具和资源。有了它&#xff0c;Java开发者就可以编译和运行自己的Java程序。它包含…

JDK、JRE、JVM 之间的关系

总结&#xff1a; 关系&#xff1a;JDK包含JRE JRE包含JVM JDK (Java Development Kit)----Java开发工具包&#xff0c;用于Java程序的开发。 JRE (Java Runtime Environment)----Java运行时环境&#xff0c;只能运行.class文件&#xff0c;不能编译。 JVM (Java Virtual M…

JDK、JRE和JVM之间的关系

作为一个Java开发者&#xff0c;只会用Java&#xff0c;却不知什么是JDK、JRE和JVM是什么&#xff0c;以及他们之间有什么联系。本文总结了JDK&#xff0c;JRE&#xff0c;JVM三者的关系与区别。 JDK、JRE和JVM之间的关系 一、JDK二、JRE三、JVM四、三者的联系五、三者的区别六…

Java基础 — JDK和JRE的区别和环境变量配置

1、JDK和JRE区别 JDK&#xff1a;java 程序开发工具包&#xff0c;包括编译器&#xff08;javac.exe&#xff09;、开发工具&#xff08;javadoc.exe、jar.exe、keytool.exe、jconsole.exe&#xff09;和更多的类库&#xff08;如tools.jar&#xff09;等。JRE&#xff1a;jav…

linux df和du命令

df&#xff08;disk free&#xff09;命令用于显示目前在 Linux 系统上的文件系统磁盘使用情况统计。Linux du &#xff08;英文全拼&#xff1a;disk usage&#xff09;命令用于显示目录或文件的大小。 加上-h以可读性更强的方式显示文件大小 由此可见&#xff0c;一个是对于…

Linux命令详解之du命令

功能&#xff1a;可以用于查看每个文件的磁盘用量&#xff0c;目录则取总用量 格式&#xff1a;du 【选项】【文件或目录】 主要使用参数&#xff1a; -a 显示所有文件的大小 -h 以人类可读的方式查看…

十进制小数转二进制

十进制小数转换成二进制小数采用"乘2取整&#xff0c;顺序排列"法。以0.875为例&#xff0c;具体做法是&#xff1a; 一、取整运算 1、用2乘十进制小数&#xff0c;可以得到积&#xff1a;2*0.8751.75&#xff1b; 2、将积的整数部分1取出&#xff0c;再用2乘余下…

小数的二进制和十进制之间的转换

0.125(十进制) 依次 2 取小数点左边第一个数&#xff0c;将取得的数按顺序排列在小数点右侧&#xff0c;例子如下&#xff1a; 0.125 2 0.25 0.25 2 0.5 0.5 2 1.0 0.125&#xff08;十进制&#xff09;——> 0.001&#xff08;二进制&#xff09; 0.001(二进制…

二进制十进制小数转换

方法&#xff1a; 十进制的小数转为二进制&#xff0c;主要是小数部分乘以2&#xff0c;取整数部分一次从左往右放在小数点后&#xff0c;直至小数点后为0&#xff08;就是为整数时&#xff09; eg&#xff1a;0.125 二进制的小数转换为十进制主要是乘以2的负次方&#xff0…

二进制小数转换

文章转自&#xff1a; https://www.cnblogs.com/xkfz007/articles/2590472.html 一、二进制数转换成十进制数 由二进制数转换成十进制数的基本做法是&#xff0c;把二进制数首先写成加权系数展开式&#xff0c;然后按十进制加法规则求和。这种做法称为"按权相加"…