C/C++如何实现crc码计算和校验

免费教程   2024年05月10日 6:00  

这篇文章主要讲解了“C/C++如何实现crc码计算和校验”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C/C++如何实现crc码计算和校验”吧!

算法介绍

循环冗余校验(Cyclic Redundancy Check, )是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。

CRC校验计算速度快,检错能力强,易于用编码器等硬件电路实现。从检错的正确率与速度、成本等方面,都比奇偶校验等校验方式具有优势。因而,CRC 成为计算机信息通信领域最为普遍的校验方式。常见应用有以太网/USB通信,压缩解压,视频编码,图像存储,磁盘读写等

参数模型

CRC参数模型

不知道你是否遇到过这种情况,同样的CRC多项式,调用不同的CRC计算函数,得到的结果却不一样,而且和手算的结果也不一样,这就涉及到CRC的参数模型了。计算一个正确的CRC值,需要知道CRC的参数模型。

一个完整的CRC参数模型应该包含以下信息:WIDTH,POLY,INIT,REFIN,REFOUT,XOROUT。

NAME:参数模型名称。

WIDTH:宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位

POLY:十六进制多项式,省略最高位1,如 x8 + x2 + x + 1,二进制为1 0000 0111,省略最高位1,转换为十六进制为0x07。

INIT:CRC初始值,和WIDTH位宽一致。

REFIN:true或false,在进行计算之前,原始数据是否翻转,如原始数据:0x34 = 0011 0100,如果REFIN为true,进行翻转之后为0010 1100 = 0x2c

REFOUT:true或false,运算完成之后,得到的CRC值是否进行翻转,如计算得到的CRC值:0x97 = 1001 0111,如果REFOUT为true,进行翻转之后为11101001 = 0xE9。

XOROUT:计算结果与此参数进行异或运算后得到最终的CRC值,和WIDTH位宽一致。

接收端的校验有两种方式:

一种是和CRC计算一样,在本地把接收到的数据和CRC分离,然后在本地对数据进行CRC运算,得到的CRC值和接收到的CRC进行比较,如果一致,说明数据接收正确,如果不一致,说明数据有错误。

另一种方法是把整个数据帧进行CRC运算,因为是数据帧相当于把原始数据左移8位,然后加上余数,如果直接对整个数据帧进行CRC运算(除以多项式),那么余数应该为0,如果不为0说明数据出错

代码计算#include<stdio.h>#include<stdlib.h>#include<string.h>//求数的二进制最高位的幂指数,即MSBstaticintgetMinPolynomialBits(uint64_tn){intr=0;while(n>>=1)r++;returnr;}//append>0表示计算crc校验码,赋值到crcRemainder//append=0,表示校验输入bit流是否正确;0表示正确,-1表示错误//此处的多项式默认为0x96(高位补1后的结果),默认crc位数为7,可根据代码自行修改staticintcrcCheck(constchar*msg,intappend,char*crcRemainder){if(msg==NULL||crcRemainder==NULL||strlen(msg)==0){printf("inputparameterisunvalid!\n");return-1;}//hex:0x96=b'10010110'=DEC:150uint64_tpoly=0x96;intpolyLen=getMinPolynomialBits(poly+1);//=7intmsgLen=strlen(msg);//printf("%d\n",msgLen);//计算crc校验码if(append){unsignedchar*pBufCrc=(unsignedchar*)calloc(msgLen+polyLen,sizeof(unsignedchar));memset(pBufCrc,0,msgLen+polyLen);for(intj=0;j<msgLen;j++){pBufCrc[j]=msg[j]-'0';}uint8_t*p=NULL;for(inti=0;i<msgLen;i++){if(pBufCrc[i]){p=pBufCrc+i+polyLen;uint64_tt=poly;do{*(p--)^=t&1;}while(t>>=1);}}p=NULL;size_tk;for(k=0;k<polyLen;k++){crcRemainder[k]=pBufCrc[k+msgLen]+48;}if(pBufCrc){free(pBufCrc);pBufCrc=NULL;}}else{//校验接受端的比特流unsignedchar*pBuffer=(unsignedchar*)calloc(msgLen,sizeof(unsignedchar));memset(pBuffer,0,msgLen);intinforLen=msgLen-polyLen;//提取出信息流部分,然后计算当前信息对应crc校验码for(intj=0;j<inforLen;j++){pBuffer[j]=msg[j]-'0';}uint8_t*p=NULL;for(inti=0;i<inforLen;i++){if(pBuffer[i]){p=pBuffer+i+polyLen;uint64_tt=poly;do{*(p--)^=t&1;}while(t>>=1);}}p=NULL;//计算得到的crc码和输入的crc码进行对比验证,若每一位都相同,则校验成功for(size_tk=inforLen;k<msgLen;k++){if(msg[k]!=pBuffer[k]+48){if(pBuffer){free(pBuffer);pBuffer=NULL;}return-1;}}if(pBuffer){free(pBuffer);pBuffer=NULL;}}return0;}

感谢各位的阅读,以上就是“C/C++如何实现crc码计算和校验”的内容了,经过本文的学习后,相信大家对C/C++如何实现crc码计算和校验这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

域名注册
购买VPS主机

您或许对下面这些文章有兴趣:                    本月吐槽辛苦排行榜

看贴要回贴有N种理由!看帖不回贴的后果你懂得的!


评论内容 (*必填):
(Ctrl + Enter提交)   

部落快速搜索栏

各类专题梳理

网站导航栏

X
返回顶部