您的位置:首页 > 编程语言 > C#

C#和C实现通过CRC-16 (Modbus)获取CRC值并校验数据(代码)

2016-10-21 16:13 691 查看
文章首发于浩瀚先森博客
CRC的全称为CyclicRedundancyCheck,中文名称为循环冗余校验。它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除数据通信外,CRC在其它很多领域也是大有用武之地的。例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“BadCRC”错误,由此它在数据存储方面的应用可略见一斑。

差错控制理论是在代数理论基础上建立起来的。这里我们着眼于介绍CRC的算法与实现,对原理只能捎带说明一下。若需要进一步了解线性码、分组码、循环码、纠错编码等方面的原理,可以阅读有关资料。

利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的r位监督码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。这个规则,在差错控制理论中称为“生成多项式”。

下面提供C#实现的代码:

#region计算CRC校验码 ///<summary> ///计算CRC校验码,并转换为十六进制字符串 ///CyclicRedundancyCheck循环冗余校验码 ///是数据通信领域中最常用的一种差错校验码 ///特征是信息字段和校验字段的长度可以任意选定 ///</summary> ///<paramname="data"></param> ///<returns></returns> publicstaticstringget_CRC16_C(byte[]data) { bytenum=0xff; bytenum2=0xff; bytenum3=1; bytenum4=160; byte[]buffer=data; for(inti=0;i<buffer.Length;i++) { //位异或运算 num=(byte)(num^buffer[i]); for(intj=0;j<=7;j++) { bytenum5=num2; bytenum6=num; //位右移运算 num2=(byte)(num2>>1); num=(byte)(num>>1); //位与运算 if((num5&1)==1) { //位或运算 num=(byte)(num|0x80); } if((num6&1)==1) { num2=(byte)(num2^num4); num=(byte)(num^num3); } } } returnbyteToHexStr(newbyte[]{num,num2},2); } #endregion //获取并校验两数据是否一致 publicstaticboolcheckCRC(byte[]srcData,byte[]desData) { stringcrc=get_CRC16_C(srcData); if(crc==byteToHexStr(desData,desData.Length)) returntrue; else returnfalse; } ///<summary> ///字节数组转16进制字符串 ///</summary> ///<paramname="bytes"></param> ///<returns></returns> publicstaticstringbyteToHexStr(byte[]bytes,intsize) { stringreturnStr=""; if(bytes!=null) { for(inti=0;i<size;i++) { returnStr+=bytes[i].ToString("X2"); } } returnreturnStr; }

下面提供C实现的代码:

uint16_tCalcCRC(uint8_t*u8Data,uint8_tu8Size) { uint16_tReturnData; uint8_tnum=0xff; uint8_tnum2=0xff; uint8_tnum3=1; uint8_tnum4=160; uint8_tbuffer[5]; memcpy(buffer,u8Data,u8Size); for(inti=0;i<u8Size;i++) { num=(uint8_t)(num^buffer[i]); for(intj=0;j<=7;j++) { uint8_tnum5=num2; uint8_tnum6=num; num2=(uint8_t)(num2>>1); num=(uint8_t)(num>>1); if((num5&1)==1) { num=(uint8_t)(num|0x80); } if((num6&1)==1) { num2=(uint8_t)(num2^num4); num=(uint8_t)(num^num3); } } } ReturnData=num; ReturnData=ReturnData<<8; ReturnData|=num2; returnReturnData; } ITStatuscheckCRC(uint8_t*srcData,uint8_tu8srcSize,uint8_t*desData) { uint16_treturnData=CalcCRC(srcData,u8srcSize); if(((returnData>>8)==*desData)&&((returnData&0x00ff)==*(desData+1))) returnSET; else returnRESET; }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: