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

article/2025/10/31 7:31:10

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

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

不同同应用规范通过对输入数据前处理和输出数据后处理的方式不同,又产生了不同的应用规范校验函数,这里介绍CCITT格式的CRC-16校验函数。CCITT格式对输入数据,按照单个字节进行位反序。对于输出的校验码,进行整体位反序。

生成多项式为x^16 + x^12 + x^5 + 1

正向算法

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

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

#include <stdio.h>
#include <stdlib.h>
uint16_t PY_CRC_16_CCITT(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] = 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;
}

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

uint16_t PY_CRC_16_S_CCITT(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] ;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;
}

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

uint16_t PY_CRC_16_T16_CCITT(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] = 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;
}

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

uint16_t PY_CRC_16_T8_CCITT(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 = 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;
}

反向算法

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

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

uint16_t PY_CRC_16_T8_CCITT_i(uint8_t *di, uint32_t len)
{uint16_t crc_poly = 0x8408; //Bit sequence inversion of 0x1021uint16_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;
}

算法验证

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

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

–End–


http://chatgpt.dhexx.cn/article/3BiIMoP7.shtml

相关文章

LabVIEW做CRC校验CRC-16/CCITT-FALSE算法

一直以来用的CRC校验的地方就是Modbus通讯&#xff0c;这次做项目遇到一个自定义协议需要CRC校验的协议&#xff0c;直接连例程发现计算结果不对通讯不上。后来发现CRC有很多中算法&#xff0c;网上资料也不全面。以下是我收藏总结的&#xff0c;估计也不全仅供参考。 参数解释…

CRC16-ccitt-false 递归解析每一个号码段的值

CRC16-ccitt-false 解析每一个号码段的值 数据准备 加密前&#xff1a;6011qwertyuiopa62440007db2a65b0306qrcode043339912211117000000016304 CRC16-ccitt-false加密后&#xff1a;4023&#xff08;网上有加密工具类&#xff0c;也有线上计算工具&#xff0c;如下图&#xff…

文本图像(二值图像)(黑白图像)的压缩算法介绍 CCITT-4 JBIG2

CCITT group3 CCITT group4 JBIG JBIG2 参考&#xff1a; JBIG2标准在数字图书馆中的应用 https://www.docin.com/p-821587404.html

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

C语言CRC-16 CCITT-FALSE格式校验函数 CRC-16校验产生2个字节长度的数据校验码&#xff0c;通过计算得到的校验码和获得的校验码比较&#xff0c;用于验证获得的数据的正确性。基本的CRC-16校验算法实现&#xff0c;参考&#xff1a; C语言标准CRC-16校验函数。 不同应用规范…

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 以人类可读的方式查看…