CRC16、CRC32校验简单分析

合集下载

java crc3216进制数校验算法

java crc3216进制数校验算法

java crc3216进制数校验算法Java CRC32是一种校验算法,用于对数据进行校验和验证。

CRC32是循环冗余校验码的32位实现,它通过对数据进行多项式除法运算来生成一个32位的校验值。

本文将详细介绍Java CRC32算法的原理、应用及其实现方式。

一、CRC32校验算法原理CRC32算法是一种循环冗余校验码算法的32位实现。

它通过对数据进行多项式除法运算,得到一个32位的校验值。

具体的原理如下:1. 初始化CRC寄存器的值为全1(32个1)。

2. 将要校验的数据的每个字节与CRC寄存器的值进行异或运算。

3. 将CRC寄存器的值右移8位,并用一个预设的多项式(通常是0xEDB88320)进行异或运算。

4. 重复步骤2和3,直到所有的数据字节都被处理过。

5. 最终得到的CRC寄存器的值即为校验值。

二、CRC32校验算法应用CRC32校验算法在数据传输和存储中广泛应用,其中一些常见的应用包括:1. 数据完整性校验:通过计算数据的CRC32校验值,可以验证数据在传输或存储过程中是否发生了错误或损坏。

2. 文件校验:在下载文件或拷贝文件时,可以通过比较源文件和目标文件的CRC32校验值来判断文件是否完整无误。

3. 网络通信:在网络通信中,通过计算发送数据的CRC32校验值,接收方可以验证接收到的数据的完整性。

4. 数据库校验:在数据库中存储数据的同时,可以计算数据的CRC32校验值,并将其与存储的数据一起存储。

当需要读取数据时,可以通过比较计算得到的CRC32校验值和存储的校验值来验证数据的完整性。

三、Java CRC32算法实现Java提供了java.util.zip.CRC32类来实现CRC32校验算法。

下面是一个使用Java CRC32算法计算校验值的示例代码:```javaimport java.util.zip.CRC32;public class CRC32Example {public static void main(String[] args) {byte[] data = "Hello, CRC32!".getBytes();CRC32 crc32 = new CRC32();crc32.update(data);long checksum = crc32.getValue();System.out.println("CRC32 checksum: " + checksum);}}```在上述示例代码中,首先将要校验的数据转换为字节数组。

16位循环冗余校验码_CRC_的原理和性能分析

16位循环冗余校验码_CRC_的原理和性能分析

16位循环冗余校验码_CRC_的原理和性能分析16位循环冗余校验码(CRC)是一种广泛应用于数据传输中的错误检测码。

它通过使用除法运算和异或运算来生成一个冗余校验码,并将其附加到数据上。

接收方在接收到数据后,通过同样的计算方式对数据进行校验,然后与接收到的校验码进行比较,从而判断数据是否存在错误。

CRC的原理如下:1.选择一个特定的多项式作为生成器多项式G(x),通常以二进制方式表示。

2.将数据D(x)乘以x的n次方,其中n为生成器多项式的次数。

3.将上述结果除以生成器多项式G(x),并将余数作为冗余校验码。

具体的计算过程如下:1.将生成器多项式转换为二进制数,作为一个校验位模型。

2.将数据与n个0相接,使其长度与生成器多项式的次数一致。

3.将上述结果除以生成器多项式,并将余数作为冗余校验码。

性能分析:1.理论上,CRC能够探测所有偶数个错误位和绝大多数奇数个错误位。

但由于CRC运算时使用的是模2除法,因此会漏掉部分奇数个错误位。

2.CRC的检错性能与生成器多项式的选择相关。

选择一个好的生成器多项式很重要,能够提高CRC的检错能力。

3.16位的CRC校验码相对于32位或更多位的CRC校验码来说,冲突概率较高。

这意味着可能存在不同的数据产生相同的校验码。

因此,在应用中,需要根据实际情况选择合适的CRC位数。

总结:16位循环冗余校验码通过除法运算和异或运算生成一个冗余校验码,用于检测数据传输中的错误。

它的性能取决于生成器多项式的选择,能够探测大部分的错误位。

然而,由于CRC采用模2除法,可能会漏掉部分奇数个错误位。

在应用中,需要根据实际情况选择合适的CRC位数。

CRC校验解读

CRC校验解读
crc.c[0] = crc.c[1]^crctableh[t];
crc.c[1] = crctablel[t];
n--;
buf++;
}
return ( crc.x );
}
表面上看起来,函数crc1比crc0的源代码还长一些。但是编译后,函数crc1的目标代码实际为44个字节,加上表格占用的512个字节,一共使用了556个字节,比函数crc0反而节约了24个字节。这两个函数的运行对比情况见表一。
计算CRC校验时,最常用的计算方式有三种:查表、计算、查表+计算。一般来说,查表法最快,但是需要较大的空间存放表格;计算法最慢,但是代码最简洁、占用空间最小;而在既要求速度,空间又比较紧张时常用查表+计算法。
下面我们分别就这三种方法进行讨论和比较。这里以使用广泛的51单片机为例,分别用查表、计算、查表+计算三种方法计算1021多项式(CRC-ITU)校验。原始程序都是在网上或杂志上经常能见到的,相信大家也比较熟悉了,甚至就是正在使用或已经使用过的程序。
crc ^= crc_ta[da^(*ptr&0x0f)];/* CRC的高4位和本字节的后半字节相加后查表*/
/*计算CRC,然后再加上上一次CRC的余数*/
ptБайду номын сангаас++;
}
return crc;
}
程序优化策略:上面程序都只是给出了通用算法,并没有考虑到51单片机的特点。我们知道,51单片机是8位单片机,使用的变量类型也是8位的。如果在程序中使用8位的变量速度是最快的,比使用16位的变量代码短、效率高。在上面的程序中都使用了大量整型数类型(16位)的表格和整型数类型的变量,特别是关键的变量。如果我们不使用整型类型的表格和变量,而使用字节类型的表格和变量,就能够使程序的性能得到优化。基于这种思路,我们将原来整型的表格拆分为两个字节型(8位)的表格,即将原来表格的高低字节分别拆开,每个表格还是256个单元,这样表格的大小和顺序都没有变;原来使用16位变量计算的地方,改用8位变量计算。

最详细易懂的CRC-16校验原理(附源程序)

最详细易懂的CRC-16校验原理(附源程序)

最详细易懂的CRC-16校验原理(附源程序)1、循环校验码(CRC码):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。

2、生成CRC码的基本原理:任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。

例如:代码对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。

标准CRC生成多项式如下表:名称生成多项式简记式* 标准引用CRC-4 x4+x+1 3 ITU G.704CRC-8 x8+x5+x4+1 0x31CRC-8 x8+x2+x1+1 0x07CRC-8 x8+x6+x4+x3+x2+x1 0x5ECRC-12 x12+x11+x3+x+1 80FCRC-16 x16+x15+x2+1 8005 IBM SDLCCRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCSCRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCSCRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP3、CRC-16校验码的使用:现选择最常用的CRC-16校验,说明它的使用方法。

根据Modbus协议,常规485通讯的信息发送形式如下:地址功能码数据信息校验码1byte 1byte nbyte 2byteCRC校验是前面几段数据内容的校验值,为一个16位数据,发送时,低8位在前,高8为最后。

例如:信息字段代码为: 1011001,校验字段为:1010。

发送方:发出的传输字段为: 1 0 1 1 0 0 1 1 0 10信息字段校验字段接收方:使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则信息正确。

crc16 校验 查表法

crc16 校验 查表法

crc16 校验查表法CRC16校验是一种常用的校验方法,通过查表法实现。

在数据通信中,数据的完整性和准确性是非常重要的,而CRC16校验能够帮助我们检测数据是否出现错误或被篡改。

本文将详细介绍CRC16校验的原理和实现方法。

一、CRC校验简介CRC(Cyclic Redundancy Check)校验是一种基于多项式运算的校验方法,常用于数据通信中的差错检测。

它通过对待校验数据进行一系列的位运算,生成一个与数据长度无关的校验码。

接收方在接收到数据后,同样进行CRC运算,将得到的校验码与发送方发送的校验码进行比对,如果一致,则说明数据在传输过程中没有发生错误。

二、CRC16校验原理CRC16校验是CRC校验的一种,它使用16位的多项式进行计算。

CRC16校验的原理是将待校验数据和一个预设的除数(生成多项式)进行一系列的位运算,最后得到一个16位的校验码。

具体过程如下:1. 预设除数:CRC16校验使用的预设除数是一个16位的二进制数,常用的有多个不同的预设除数,如0x8005、0x1021等。

2. 数据填充:在待校验数据的末尾填充16个0,使得待校验数据的位数和预设除数的位数一致。

3. 初始值设置:将初始值设为全1的16位二进制数。

4. 逐位异或运算:从待校验数据的最高位开始,逐位与初始值进行异或运算,如果结果为1,则将初始值右移一位并与预设除数进行异或运算,如果结果为0,则直接右移一位。

5. 重复上述步骤,直到待校验数据的所有位都进行了异或运算。

6. 得到校验码:最后得到的16位二进制数即为CRC16校验码。

三、CRC16查表法实现CRC16校验的查表法实现相对于位运算的实现更加高效。

查表法的基本思想是将预设除数的所有可能取值及其对应结果存储在一个查表数组中,通过查表的方式来进行CRC16校验的计算。

1. 初始化CRC表:首先需要创建一个256个元素的CRC表,每个元素的值为该位二进制数的CRC16校验码。

C#硬件校验数据校验算法C#Crc16Crc16CCITTCRC16FORX25CRC32

C#硬件校验数据校验算法C#Crc16Crc16CCITTCRC16FORX25CRC32

C#语言CRC数据校验算法目录C#语言CRC数据校验算法 (1)前言 (1)Crc16 (2)Crc16CCITT和Crc16CCITT_False (5)Crc16FORX25 (6)Crc32 (7)赠送常用字节算法 (9)源码文件 (11)前言每个算法都经过验证的,都是在硬件采集上使用过,除了Crc32算法没验证外,其它算法请放心使用附C#源码文件。

(文档末尾有源码文件)Crc16#region crc16public static string GetCrc16(string data){byte[] bs = StrToToHexByte(data);string crc16 = Get_CRC16_C(bs);string crc16_r = string.Format("{0} {1}", crc16.Substring(2, 2),crc16.Substring(0, 2));bs = null;crc16 = null;return crc16_r;}public static string ReverseCrc16(string crc16){string crc16Reverse = string.Format("{0} {1}", crc16.Substring(2, 2), crc16.Substring(0, 2));return crc16Reverse;}///<summary>///字符串转16进制字节数组///</summary>///<param name="hexString"></param>///<returns></returns>public static byte[] StrToToHexByte(string hexString){hexString = hexString.Replace(" ", "");if ((hexString.Length % 2) != 0)hexString = string.Format("{0} ", hexString);byte[] returnBytes = new byte[hexString.Length / 2];for (int i = 0; i < returnBytes.Length; i++)returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);return returnBytes;}///<summary>///字节数组转16进制字符串///</summary>///<param name="bytes"></param>///<returns></returns>public static string ByteToHexStr(byte[] bytes){string returnStr = "";if (bytes != null){for (int i = 0; i < bytes.Length; i++){returnStr = string.Format("{0}{1}", returnStr, bytes[i].ToString("X2"));}}return returnStr;}///<summary>///计算CRC校验码,并转换为十六进制字符串/// Cyclic Redundancy Check 循环冗余校验码///是数据通信领域中最常用的一种差错校验码///特征是信息字段和校验字段的长度可以任意选定///</summary>///<param name="data"></param>///<returns></returns>public static string Get_CRC16_C(byte[] data){byte num = 0xff;byte num2 = 0xff;byte num3 = 1;byte num4 = 160;byte[] buffer = data;for (int i = 0; i < buffer.Length; i++){//位异或运算num = (byte)(num ^ buffer[i]);for (int j = 0; j <= 7; j++){byte num5 = num2;byte num6 = 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);}}}return ByteToHexStr(new byte[] { num, num2 }, 2);}///<summary>///获取并校验两数据是否一致///</summary>///<param name="srcData"></param>///<param name="desData"></param>///<returns></returns>public static bool CheckCRC(byte[] srcData, byte[] desData) {string crc = Get_CRC16_C(srcData);if (crc == ByteToHexStr(desData, desData.Length))return true;elsereturn false;}///<summary>///字节数组转16进制字符串///</summary>///<param name="bytes"></param>///<returns></returns>public static string ByteToHexStr(byte[] bytes, int size) {string returnStr = "";if (bytes != null){for (int i = 0; i < size; i++){returnStr = string.Format("{0}{1}", returnStr, bytes[i].ToString("X2"));}}return returnStr;}#endregion crc16Crc16CCITT和Crc16CCITT_False#region Crc16CCITTpublic static string ConvertToHEX(int dec){return dec.ToString("X");}public static string GetCrc16CCITT_False(string hexString){string hex = ConvertToHEX(crc16(StrToToHexByte(hexString))).PadLeft(4, '0');string crc = ReverseCrc16(hex);return crc;}public static int crc16(byte[] bytes){return crc16(bytes, bytes.Length);}public static int crc16(byte[] bytes, int len){int crc = 0xFFFF;for (int j = 0; j < len; j++){crc = ((crc >> 8) | (crc << 8)) & 0xffff;crc ^= (bytes[j] & 0xff);// byte to int, trunc signcrc ^= ((crc & 0xff) >> 4);crc ^= (crc << 12) & 0xffff;crc ^= ((crc & 0xFF) << 5) & 0xffff;}crc &= 0xffff;return crc;}public static int crc16(byte[] bytes, int start, int len){int crc = 0xFFFF;for (; start < len; start++){crc = ((crc >> 8) | (crc << 8)) & 0xffff;crc ^= (bytes[start] & 0xff);// byte to int, trunc signcrc ^= ((crc & 0xff) >> 4);crc ^= (crc << 12) & 0xffff;crc ^= ((crc & 0xFF) << 5) & 0xffff;}crc &= 0xffff;return crc;}public static short crc16_short(byte[] bytes){return crc16_short(bytes, 0, bytes.Length);}public static short crc16_short(byte[] bytes, int len){return (short)crc16(bytes, len);}public static short crc16_short(byte[] bytes, int start, int len) {return (short)crc16(bytes, start, len);}#endregion Crc16CCITTCrc16FORX25#region CRC16FORX25public static byte[] CRC_16forx25(byte[] bytes){byte[] returnVal = new byte[2];int i, j, lsb;int h = 0xffff;for (i = 0; i < bytes.Length; i++){h ^= bytes[i];for (j = 0; j < 8; j++){lsb = h & 0x0001; //取 CRC 的移出位h >>= 1;if (lsb == 1){h ^= 0x8408;}}}h ^= 0xffff;returnVal[1] = (byte)(h >> 8);//CRC高位returnVal[0] = (byte)(h & 0x00ff);//CRC低位return returnVal;}#endregion CRC16FORX25Crc32#region crc32public class CRC32{static UInt32[] crcTable = {0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535,0x9e6495a3,0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07,0x90bf1d91,0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5,0xe8b8d433,0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97,0xe6635c01,0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615,0x73dc1683,0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27,0x7d079eb1,0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713,0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21,0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,};public static byte[] GetCrc32(byte[] bytes){//e6dda9daint crc = GetCRC32(bytes);string str = Convert.ToString(crc, 16).ToUpper();byte[] b4 = new byte[4];b4[0] = Convert.ToByte(str.Substring(6), 16);b4[1] = Convert.ToByte(str.Substring(4, 2), 16);b4[2] = Convert.ToByte(str.Substring(2, 2), 16);b4[3] = Convert.ToByte(str.Substring(0, 2), 16);return b4;}public static int GetCRC32(byte[] bytes){int iCount = bytes.Length;UInt32 crc = 0xFFFFFFFF;for (int i = 0; i < iCount; i++){crc = ((crc >> 8) & 0x00FFFFFF) ^ crcTable[(crc ^ bytes[i]) & 0xFF];}UInt32 temp = crc ^ 0xFFFFFFFF;int t = (int)temp;return (t);}}#endregion赠送常用字节算法public static int LastIndexOf(byte[] data, byte[] find){if (find == null || find.Length == 0)return -1;int pos = -1;for (int i = data.Length; i >= find.Length; i--){bool isFind = true;for (int j = 0; j < find.Length; j++){if (find[j] != data[i - (find.Length - j)]){isFind = false;break;}}if (isFind){pos = i - find.Length;break;}}return pos;}public static int IndexOf(byte[] data, byte[] find){if (find == null || find.Length == 0)return -1;if (find.Length > data.Length)return -1;int pos = -1;for (int i = 0; i < data.Length; i++){if (data.Length - i >= find.Length){bool isFind = true;for (int j = 0; j < find.Length; j++){if (find[j] != data[i + j]){isFind = false;break;}}if(isFind){pos = i;break;}}}return pos;}public static int LastIndexOf(List<byte> data, byte[] find) {if (find == null || find.Length == 0)return -1;int pos = -1;for (int i = data.Count; i >= find.Length; i--){bool isFind = true;for (int j = 0; j < find.Length; j++){if (find[j] != data[i - (find.Length - j)]){isFind = false;break;}}if (isFind){pos = i - find.Length;break;}}return pos;}//是否能通过crc校验public static bool IsCrc16Pass(string fullData){if (fullData.Length >= 6){string data = fullData.Substring(0, fullData.Length - 5).Trim();string crc16 = fullData.Substring(fullData.Length - 5);string calcCrc16 = GetDefalutCrc16(data);string calcCrc16Rev = ReverseCrc16(calcCrc16);return crc16.Replace(" ", "") == calcCrc16.Replace(" ", "") || crc16.Replace(" ", "") == calcCrc16Rev.Replace(" ", "");}return false;}文件CrcHelper.cs。

CRC16和CRC32探讨

CRC16和CRC32探讨

CRC16和CRC32探讨再探CRC之前写了CRC16的程序,虽说能用,却不知其所心然,现在要用CRC32,重温一遍,一下就通了。

笔记如下CRC我没记错的话是Cyclic Redundancy Code,Cyclic 和Redundancy非常传神,所谓冗余就是附加的信息,这就是计算下面的原始数据时为什么原始数据要左移四位的原因,////// The simplest CRC implement algorithm.////*Load the register with zero bits.Augment the message by appending W zero bits to the end of it.While (more message bits)BeginShift the register left by one bit, reading the next bit of the augmented message into register bit position 0.If (a 1 bit popped out of the register during step 3)Register = Register XOR Poly.EndThe register now contains the remainder.*/#include ;#define POLY 0x13int main(){/// the dataunsigned short data = 0x035b;/// load the register with zero bitsunsigned short regi = 0x0000;/// augment the data by appending W(4) zero bits to the end of it.data ;= 0; -- cur_bit ){/// test the highest bit which will be poped later. /// in fact, the 5th bit from right is the hightest bit hereif( ( ( regi >;>; 4 ) & 0x0001 ) == 0x1 )//凑够5位数(与被除数即生成多项式的位数一样),模2除{regi = regi ^ POLY;}/// shift the register regi ;>; cur_bit ) & 0x0001; regi |= tmp;}/// and now, register contains the remainder which is also called CRC value.return 0;}以上程序就是上面照片里算法的模拟实现,步骤完全一致。

crc16校验范围

crc16校验范围

crc16校验范围摘要:1.CRC16校验简介2.CRC16校验的计算方法3.CRC16校验范围的概述4.CRC16校验在实际应用中的优势5.常见问题及解决方法正文:**CRC16校验简介**CRC16(Cyclic Redundancy Check 16)是一种循环冗余校验算法,用于检测数据传输或存储中的错误。

它通过在数据后面附加一些校验位,然后接收方在接收到数据后,通过相同的计算方法,对数据进行校验,以判断数据在传输过程中是否发生了改变或错误。

CRC16校验因其高效性和可靠性而在众多领域得到广泛应用。

**CRC16校验的计算方法**CRC16校验的计算方法主要包括以下几个步骤:1.初始化:设定初始值,通常是0。

2.按位异或:将数据位的反码与校验位进行异或操作。

3.迭代:根据预先设定的迭代次数,将校验位与生成多项式进行按位异或操作。

4.输出:得到最终的校验结果。

**CRC16校验范围的概述**CRC16校验范围是指在数据传输或存储中,能够有效检测到错误的一段数据长度。

在实际应用中,CRC16校验通常用于检测数据包或文件的正确性。

校验范围越大,检测的准确性越高,但同时也会增加数据的开销。

因此,在实际应用中,需要根据具体需求来选择合适的CRC16校验范围。

**CRC16校验在实际应用中的优势**CRC16校验在实际应用中具有以下优势:1.高效性:CRC16校验算法简单,计算速度快,适用于实时数据传输场景。

2.可靠性:CRC16校验能够检测到多种类型的错误,包括突发性错误和单个比特错误。

3.通用性:CRC16校验适用于不同类型的数据格式和传输协议。

**常见问题及解决方法**1.问题:CRC16校验出现误报怎么办?解决方法:检查生成多项式和迭代次数是否合适,适当调整以提高校验准确性。

2.问题:CRC16校验范围过大,导致数据开销增加怎么办?解决方法:可以选择更小的生成多项式和迭代次数,以减小校验范围。

最详细易懂的CRC-16校验原理(附源程序)

最详细易懂的CRC-16校验原理(附源程序)

最详细易懂的CRC-16校验原理(附源程序)1、循环校验码(CRC码):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。

2、生成CRC码的基本原理:任意一个由二进制位串组成的代码都可以和一个系数仅为‘和’取值的多项式一一对应。

例如:代码对应的多项式为X6+X4+X2+X+1,而多项式为X5+X3+X2+X+1对应的代码101111 o标准CRC生成多项式如下表:名称生成多项式简记式*标准引用CRC-4 x4+x+1 3 ITU G.704CRC-8 x8+x5+x4+1 0x31CRC-8 x8+x2+x1+1 0x07CRC-8x8+x6+x4+x3+x2+x10x5ECRC-12 x12+x11+x3+x+1 80FCRC-16 x16+x15+x2+1 8005 IBM SDLCCRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCSCRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI,IEEE 1394, PPP-FCSCRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP3、CRC-16校验码的使用:现选择最常用的CRC-16校验,说明它的使用方法。

根据Modbus协议,常规485通讯的信息发送形式如下:地址功能码数据信息校验码1byte 1byte nbyte 2byteCRC校验是前面几段数据内容的校验值,为一个16位数据,发送时,低8位在前,高8为最后。

例如:信息字段代码为:1011001,校验字段为:1010。

发送方:发出的传输字段为:1 0 1 1 0 0 1 1 0 10信息字段校验字段接收方:使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,贝y 信息正确。

crc校验 -循环冗余校验 原理和方法 -回复

crc校验 -循环冗余校验 原理和方法 -回复

crc校验-循环冗余校验原理和方法-回复CRC校验(Cyclic Redundancy Check)是一种在数据传输过程中常用的错误检测技术。

它通过对数据进行计算并生成一组校验码,用于检测数据是否在传输过程中发生了错误。

CRC校验算法广泛应用于计算机网络、通信系统以及存储设备等领域。

一、原理:CRC校验是基于二进制的模2除法实现的。

它可以用来检测数据传输过程中是否出现了错误,但不能纠正错误。

CRC校验使用一个固定的生成多项式(通常是16位或32位),该多项式作为校验算法的一部分。

生成多项式被称为“生成多项式”或“CRC多项式”。

在进行CRC校验时,发送方和接收方都需要使用相同的生成多项式。

CRC校验的基本原理是在发送数据之前,发送方计算数据和生成多项式的除法,并将得到的余数(或称为校验码)追加到待发送的数据之后。

接收方在接收到数据后,同样计算数据和生成多项式的除法,并将得到的余数与接收到的校验码进行比较。

如果余数为0,说明数据传输过程中没有发生错误;如果余数不为0,说明数据传输过程中出现了错误。

二、方法:1. 选择生成多项式:在进行CRC校验时,首先需要选择一个适当的生成多项式。

常用的生成多项式有CRC-16、CRC-32等。

这些多项式都是经过严格计算和测试的,可以提供较高的校验能力。

2. 划定消息的边界:在进行CRC校验之前,需要将待发送的数据划分为消息和一些冗余位。

通常,消息包括需要传输的原始数据,而冗余位则由生成多项式的系数决定。

3. 数据和生成多项式的除法:使用生成多项式对消息和冗余位进行除法。

具体操作可以采用多种方法实现,例如位操作、字节操作以及表格查找等。

根据除法运算的性质,进行进位运算、模2求和等,最终得到一个余数。

4. 拼接校验码:将得到的余数追加到消息的末尾,得到一个完整的数据帧。

这个余数被称为校验码,它包含了数据中可能出现的错误的信息。

5. 数据传输:将带有校验码的数据帧发送给接收方。

CRC16、CRC32校验简单分析

CRC16、CRC32校验简单分析

CRC16校验分析工业通讯中传输的数据一般是先传数据字节的低位,如:实际DATA 0x38 (0011 1000) 接收端收到为0001 1100 (0x1C),所以大部分CRC校验是处理颠倒的字节数据。

有的多项式简式为0x1021(本文以0x8005为主),目前主要的CRC算法有查表法和直接计算:1.直接计算由于数据是颠倒的所以生成项亦要倒置:0xa001(原生成多项式CRC码为0x18005,最高位始终为1故简写为0x8005,反置得到0xa001。

计算CRC时也要从其低位开始运算,且计算中数据右移(移出高位)。

异或运算满足交换律:(A^B)^C=A^(B^C),下面分析其中一种简单算法:C语言计算:计算时一次计算8bits,数据与CRC生成多项式(简式)相除,除不尽的余数与下8bits数据再异或(相减),接着进入下一8bits计算。

直到len长的数据全部计算完。

2.查表法:通过分别计算8bits(查表得到其余式)来实现逐个字节数据的CRC计算,直到全部字节数据计算完最后的余式就是CRC。

下面全是8bits查询表(256个余式的表),不过也可以4bits查询一次的计算(这样表里只需16个余式).先看程序的算法:r=0; //r是寄存器,先初始化为0//p0),t是查询表字节数据查询r高8位对应的余式,再与新得到的式子异或数据计算示意图:,之后再重复上面的步骤……若待测数据未扩展0,则此时还要计算4字节扩展0的CRC:构造CRC32查询表:一般来说,计算CRC是用“直驱表法”算法计算的,它与上面的算法非常相似,下面分析它的计算:计算步骤为(摘自文献):1. Shift the register left by one byte2. XOR the top byte just rotated out of the register with the next message byteto yield an index into the table ([0,255]).3. XOR the table value into the register.4. Goto 1 iff more augmented message bytes.C语言算法为:r=0; //r是寄存器,先初始化为0while (len--) //len是待测数据(不用扩展0)的字节长度r = (r<<8) ^ t[(r >> 24) ^ *p++]; //p是指向待测数据的指针,t是查询表相当于通过移位处理了8 个bit 的数据,相当于把之前的CRC 码的高字节(8bit)全部移出,与一个byte 的数据做XOR 运算,根据运算结果来选择一个值(称为余式),与原来的CRC 码再做一次XOR 运算,就可以得到新的CRC 码。

CRC校验算法的分析及C语言实现

CRC校验算法的分析及C语言实现

CRC校验算法的分析及C语言实现CRC(循环冗余校验)是一种常见的校验算法,用于检测和纠正数据传输中的错误。

CRC校验算法通过生成多项式对发送的数据进行计算,并将校验结果附加到数据中进行传输。

接收方可以使用相同的多项式进行计算,并将结果与接收到的数据进行比较,以检查是否存在传输错误。

1.选择一个生成多项式,通常用一个16位或32位的二进制数表示。

2.将原始数据与补充的0进行异或操作,并左移一个单位。

3.重复上述步骤,直到向左移位的次数等于生成多项式的位数。

4.将得到的余数作为校验位,将其附加到原始数据后面。

5.接收方使用相同的生成多项式进行计算,并将计算得到的余数与接收到的数据进行比较。

如果两者不相等,则说明数据存在错误。

接下来,我们将使用C语言实现一个简单的CRC校验算法。

```c#include <stdio.h>#include <stdbool.h>unsigned long crc_table[256];//初始化CRC表void init_crc_tablunsigned long crc;int i, j;for (i = 0; i < 256; i++)crc = i;for (j = 8; j > 0; j--)if (crc & 1)crc = (crc >> 1) ^ POLYNOMIAL;elsecrc >>= 1;}crc_table[i] = crc;}//计算CRC值unsigned long crc32(unsigned char *message, int length) unsigned long crc = 0xfffffffful;int i;for (i = 0; i < length; i++)crc = (crc >> 8) ^ crc_table[(crc & 0xff) ^ message[i]]; return crc ^ 0xfffffffful;int maiint length = sizeof(message) - 1;init_crc_table(;unsigned long crc = crc32(message, length);printf("CRC32: %lx\n", crc);return 0;```上述代码中,我们首先定义了一个生成多项式POLYNOMIAL,并定义了一个包含256个元素的CRC表crc_table。

如何更有效破解CRC16校验

如何更有效破解CRC16校验

如何更有效破解CRC16校验CRC16校验是一种常见的错误检测技术,它通过计算数据的循环冗余校验值来验证数据的完整性。

然而,有时候我们需要破解CRC16校验,以恢复被校验的数据。

在下面的文章中,我将介绍一些方法来更有效地破解CRC16校验。

1.CRC16算法的理解:要想更有效地破解CRC16校验,首先我们需要对CRC16算法有一定的了解。

CRC16算法是利用多项式除法来计算校验值的,它通过对数据进行位补齐、除法运算和异或运算来生成校验值。

因此,我们需要了解CRC16算法的多项式和计算过程,以便更好地破解校验值。

2.分析CRC16多项式:CRC16多项式是CRC算法的关键部分,它决定了生成的校验值的位数和校验能力。

常见的CRC16多项式包括CCITT、IBM等,不同的CRC16多项式有不同的特性。

我们需要了解特定CRC16多项式的结构和特点,以便在破解校验值时能够更有针对性地进行操作。

3.构造CRC校验表:CRC校验表是一种预先计算好的数据表,其中包含了所有可能的输入值对应的CRC校验值。

构造CRC校验表是一种常见的破解CRC校验的方法,通过事先计算好并保存CRC校验表,我们可以通过查表的方式来快速地破解数据的校验值。

5.寻找校验值的相关特征:有时候,CRC校验值可能会具有一些特定的数学特征,例如与校验值进行异或运算后得到一定的结果。

在破解CRC校验时,我们可以尝试寻找这些数学特征,并应用逆向运算来还原数据。

6.利用已知校验数据:如果我们有一些已知的数据和其对应的校验值,可以利用这些数据来破解CRC校验。

通过对已知数据和校验值进行分析,我们可以探索数据与校验值之间的关系,以便进一步破解其他未知数据的校验值。

7.利用CRC16弱点和缺陷:虽然CRC16算法在大多数情况下是相对安全的,但它也存在一些弱点和缺陷。

例如,CRC16算法对于输入数据长度较短的情况下,可能会存在冲突,即不同的数据生成相同的校验值。

16位CRC校验原理与算法分析

16位CRC校验原理与算法分析

16位CRC校验原理与算法分析2007-12-14 09:37这里,不讨论CRC的纠错原理以及为什么要选下面提及的生成多项式,只是针对以下的生成多项式,如何获得CRC校验码,作一个比较详细的说明。

标准CRC生成多项式如下表:名称生成多项式简记式* 标准引用CRC-4 x4+x+1 3ITU G.704CRC-8 x8+x5+x4+1 0x31CRC-8 x8+x2+x1+1 0x07CRC-8 x8+x6+x4+x3+x2+x1 0x5ECRC-12 x12+x11+x3+x+1 80FCRC-16 x16+x15+x2+1 8005 IBM SDLCCRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCSCRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCSCRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP生成多项式的最高位固定的1,故在简记式中忽略最高位1了,如0x1021实际是0x11021。

I、基本算法(人工笔算):以CRC16-CCITT为例进行说明,CRC校验码为16位,生成多项式17位。

假如数据流为4字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0];数据流左移16位,相当于扩大256×256倍,再除以生成多项式0x11021,做不借位的除法运算(相当于按位异或),所得的余数就是CRC校验码。

发送时的数据流为6字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0]、CRC[1]、CRC[0];II、计算机算法1(比特型算法):1)将扩大后的数据流(6字节)高16位(BYTE[3]、BYTE[2])放入一个长度为16的寄存器;2)如果寄存器的首位为1,将寄存器左移1位(寄存器的最低位从下一个字节获得),再与生成多项式的简记式异或;否则仅将寄存器左移1位(寄存器的最低位从下一个字节获得);3)重复第2步,直到数据流(6字节)全部移入寄存器;4)寄存器中的值则为CRC校验码CRC[1]、CRC[0]。

16位循环冗余校验码_CRC_的原理和性能分析

16位循环冗余校验码_CRC_的原理和性能分析

16位循环冗余校验码_CRC_的原理和性能分析CRC(Cyclic Redundancy Check)是一种循环冗余校验码,常用来对数据进行校验,判断数据在传输过程中是否发生了错误。

原理:CRC是通过生成一个固定长度的校验码来判断数据是否出现错误。

它使用一个预定的生成多项式进行计算,并且利用位运算来对数据进行处理。

具体过程如下:1.选择一个合适的生成多项式,该多项式的位数决定了CRC的位数。

常见的生成多项式有CRC-8、CRC-16和CRC-32等。

2.将需要进行校验的数据以二进制形式表示,并在末尾添加相应个数的零。

添加的零的个数与生成多项式的位数相同。

3.将数据与生成多项式进行除法运算,得到的余数即为CRC校验码。

4.将CRC校验码附加在原始数据后面,形成带有校验码的数据。

接收方在接收到数据后,利用相同的生成多项式对数据进行除法运算,如果余数为零,则说明数据没有发生错误,否则说明数据出现了错误。

性能分析:1.安全性:CRC校验码主要用于检测数据在传输过程中是否出现了错误,能够有效检测大部分错误,但并不能保证100%的安全性。

如果数据发生错误,但计算出的CRC校验码与接收方计算出的不一致,此时无法判断数据是否真的发生了错误。

2.效率:CRC计算比较高效简单,可以实现硬件加速,其计算速度快。

3.适用范围:CRC适用于对数据进行简单校验的场景,例如网络传输、存储校验等。

但对于对数据完整性要求较高的场合,如加密算法等,CRC校验不够安全。

总结:CRC校验码是一种简单且高效的校验方法,适用于在数据传输中快速检测错误。

它的计算速度快、实现简单,但对于安全性要求较高的场合,CRC校验码不够安全可靠。

因此,根据实际需求,在选择校验方法时要综合考虑安全性和效率。

CRC16算法分析(资料)

CRC16算法分析(资料)

CRC16算法分析一、概述数据校验:通俗的说,就是为保证数据的完整性,用一种指定的算法对原始数据计算出的一个校验值。

接收方用同样的算法计算一次校验值,如果和随数据提供的校验值一样,就说明数据是完整的。

关于比较流行的数据校验算法有很多,如奇偶校验、BCC异或校验法、CRC循环冗余校验、MD5校验等,各个算法的适用范围不同,前两种适用于要求不太高的数据通信,CRC则可用于硬盘数据和网络传输,而MD5则适用于数据比较大或要求比较高的场合。

奇偶校验(Parity Check):在数据存储和传输中,字节中额外增加一个比特位,用来检验错误,其中校验位可以通过数据位异或计算出来。

普通的RS232串口通讯就可另加一位用于放奇偶校验值。

BCC异或校验法(Block Check Character):把所有数据都和一个指定的初始值(通常是0)异或一次,最后的结果就是校验值,通常把它附在通讯数据的最后一起发送出去。

接收方收到数据后自己也计算一次异或和校验值,如果和收到的校验值一致就说明收到的数据是完整的。

此法适用于大多数要求不高的数据通讯,在IC卡接口通讯、很多单片机系统的串口通讯都使用。

CRC循环冗余校验(Cyclic Redundancy Check):利用除法及余数的原理来进行错误检测的,将接收到的码组进行除法运算,如果除尽,则说明传输无误;如果未除尽,则表明传输出现差错。

CRC校验具还有自动纠错能力。

CRC-12码通常用来传送6-bit字符串;CRC-16及CRC-CCITT码则用是来传送8-bit字符;CRC-32码用于硬盘数据,网络传输等。

CRC校验在WinRAR、以太网卡芯片、MPEG解码芯片中有着广泛的应用。

MD5校验(Message Digest Algorithm 5):对输入消息按512-bit分组,要填充成为512位的整数倍,且最后一组的后64位用来填充消息长度,然后算法产生128位散列值就是校验码。

关于CRC8CRC16CRC32,你要找的全部在这

关于CRC8CRC16CRC32,你要找的全部在这

关于CRC8CRC16CRC32,你要找的全部在这循环冗余校验(英语:Cyclic redundancy check,通称“CRC”)是⼀种根据⽹络数据包或电脑⽂件等数据产⽣简短固定位数校验码的⼀种散列函数,主要⽤来检测或校验数据传输或者保存后可能出现的错误。

循环冗余校验Wikipedia⼀句话:CRC是将数据计算出散列的⽅式,⼀般⽤于校验数据的完整性。

它具有简单、执⾏效率⾼等特点。

当然,你可以类⽐于Checksum,但⽐Checksum复杂些,防碰撞性更好些。

▍CRC的原理除法的。

实际的输⼊数据会被解释为⼀个长⼆进制位流(除数),再将其除以另⼀个固定⼆进制数(除数,即多项式)。

该除法的其余部分就是校验值。

CRC是基于除法但是,现实要复杂⼀些。

⼆进制数(除数和除数)不被视为普通整数值,⽽是被视为⼆进制多项式,其中实际位⽤作系数。

输⼊数据,看做⼀串⼆进制流,⽤多项式的⽅式表⽰为g(x),⽽除数是国际标准上的多项式,⽤h(x)表⽰。

通过g(x)和h(x)做除法,即两者的异或运算,得出的结果,就是我们所说的CRC运算检验结果。

那么,这⾥有两个疑问:问题1:多项式和⼆进制是什么关系?例如,1x3 + 0x2 + 1x + 1可以表⽰为1011b,或者1011b表⽰为1x3 + 0x2 + 1x + 1,其中是0的位,即以0为系数乘以该项。

问题2:除法怎么做?本质就是在做异或运算我们来看看⼀个数据串11010011101100除以x3 + x + 1是怎样进⾏的?注意,根据CRC长度,需要将这个数据串补0整个运算过程是这样的:实际上就是逐个bit移位做异或。

详见:https:///wiki/Cyclic_redundancy_check▍CRC的概念实际上,⼈们根据不同的需要,做了很多种计算⽅式,主要差别在于CRC长度、多项式、初始值、结果是否需要异或、是否需要翻转等等。

⾸先,来看看⼏个概念:Length: CRC的长度(按bit算,如8,16,32)Name: CRC的名字,让⼈⼀看就知道这是哪种CRCPolinomial: 多项式,通过该多项式来计算CRCInitialValue: CRC的初始值FinalXorValue: CRC结果做异或运算的值InputReflected: 指⽰输出是否需要翻转OutputReflected: 指⽰输出是否需要翻转我将⽹上搜到的所有的CRC标准分类做了个汇总:从上⾯的CRC名称可以看出,不同的算法是有不同⽤途的,这是国际常规的⽤法定义,其实如果是⽤户⾃⼰⽤也没特别要求,可以⾃由点。

crc校验详解

crc校验详解

CRC校验专题以CRC-16为例,说明CRC的计算过程:1.设置CRC寄存器,并给其赋值FFFF(hex)。

2.将数据的第一个8-bit字符与16位CRC寄存器的低8位进行异或,并把结果存入CRC寄存器。

3.CRC寄存器向右移一位,MSB补零,移出并检查LSB。

4.如果LSB为0,重复第三步;若LSB为1,CRC寄存器与多项式码相异或。

5.重复第3与第4步直到8次移位全部完成。

此时一个8-bit数据处理完毕。

6.重复第2至第5步直到所有数据全部处理完成。

7.最终CRC寄存器的内容即为CRC值。

翻译:1.意思是首先寄存器中的值是11111111111111112.数据第一个字节一个字节=8位用二进制表示就是【00000000-11111111】之间用这个数值跟寄存器中的16个1中的后8位进行异或(异或不知道什么意思的自己查简单理解就是同为0 异为1)然后把这个数值保存到寄存器中3.判断最后一位是否为0 如果为0寄存器中的值向右移动一位前面补零如果为1 拿寄存器中的值与多项式进行异或。

4.检查当前寄存器中的最后一位如果是0 重复第三步;如果是寄存器中的值与多项式进行异或5.重复3与4直到8此移位完成。

6.重复第2到第五步知道正规数组的数据验证完成7.最终计算出的就是CRC的值实例:实例byte[] bufs=new byte[]{0x2f,0x12,0x31} crc16 多项式码假设是0x8408 二进制形式就是10000100000010001crc=0xffff; 用二进制表示就是11111111111111112拿出bufs中第一个字节0x2f 二进制表示00101111 跟寄存器中的后8位进行异或得到11111111110100003判断CRC寄存器中最后一位当前为0 寄存器右移一位得到0111111111101000 (如果为1就与多项式进行异或)4判断当前寄存器中的值当前最后一位为0 所以重复第三步继续右移得到0011111111110100 最后还是0 在重复第三步0001111111111010 最后还是0 继续第三步0000111111111101 这时最后一位为1了这时与多项式进行异或得到10111011111110015重复判断知道判断完8次6然后再重复第2到第5步直到上面数组中的bufs中三个字节验证完7最终寄存器中的值就是crc值下面进行实战C# code 分析const uint PRESET_VALUE = 0xFFFF; 初始化寄存器的值const uint POLYNOMIAL = 0x8408; 多项式码三个参数 1char数组 byte一样 2.数组长度uint uiCrc16Cal(char[] pucY, int ucX){uint ucI, ucJ;uint uiCrcValue = PRESET_VALUE; 赋除值for(ucI = 0; ucI < ucX; ucI++){uiCrcValue = uiCrcValue ^ pucY[ucI]; 进行异或for(ucJ = 0; ucJ < 8; ucJ++) 由于一个字节 8位所以判段8次{if((uiCrcValue & 0x0001) != 0) (*1下面解释){uiCrcValue = (uiCrcValue >> 1) ^ POLYNOMIAL;} (*2下面解释)else{uiCrcValue = (uiCrcValue >> 1);} (*3下面解释)}}return uiCrcValue;}*1 “&”这个符号在C 、C#等语言上是按位与即按二进制比对1与1 得1 0与1得0 0与0得0 例如:比如:10010001(二进制)&11110000等于10010000(二进制)。

常见几种校验方法(CS和校验、CRC16、CRC32、BCC异或校验)

常见几种校验方法(CS和校验、CRC16、CRC32、BCC异或校验)

常见⼏种校验⽅法(CS和校验、CRC16、CRC32、BCC异或校验)总结⼀些通讯协议中常⽤到的⼏种校验⽅法:1.CS和校验(如:标准188协议校验⽅式)///<summary>/// CS和校验///</summary>///<param name="Abyte"></param>///<returns></returns>public static byte Check_CS(byte[] Abyte){byte result = new byte();try{int num = 0;for (int i = 0; i < Abyte.Length; i++){num = (num + Abyte[i]) % 256;}result = (byte)num;}catch{result = 0;}return result;}2.CRC16校验CRC16校验的⽅式⽐较多(如下图)我这⾥⽤到了2种,具体对应那个闹不清了【捂脸】,下⽅附上CRC校验⼯具有需要的可以⾃⼰尝试下。

CRC校验⼯具:///<summary>/// CRC16校验函数 (⼀)///</summary>///<param name="x"></param>///<returns></returns>private static byte[] CRC16(byte[] x){byte[] temdata = new byte[2];int len = x.Length;UInt16 crc = 0;byte da;int i = 0;UInt16[] yu = { 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef };while (len-- != 0){da = (byte)(((byte)(crc / 256)) / 16);crc <<= 4;crc ^= yu[da ^ x[i] / 16];da = (byte)(((byte)(crc / 256)) / 16);crc <<= 4;crc ^= yu[da ^ x[i] & 0x0f];i++;}temdata[1] = (byte)(crc & 0xFF);temdata[0] = (byte)(crc >> 8);return temdata;}///<summary>/// CRC16校验类 (⼆)///</summary>public static class Crc16{const ushort polynomial = 0xA001;static readonly ushort[] table = new ushort[256];///<summary>///获得校验字符串///</summary>///<param name="bytes"></param>///<returns></returns>public static string ComputeChecksum(byte[] bytes){ushort crc = 0;for (int i = 0; i < bytes.Length; ++i){byte index = (byte)(crc ^ bytes[i]);crc = (ushort)((crc >> 8) ^ table[index]);}return crc.ToString("X4");}static Crc16(){ushort value;ushort temp;for (ushort i = 0; i < table.Length; ++i){value = 0;temp = i;for (byte j = 0; j < 8; ++j){if (((value ^ temp) & 0x0001) != 0){value = (ushort)((value >> 1) ^ polynomial);}else{value >>= 1;}temp >>= 1;}table[i] = value;}}}3.CRC32校验private static UInt32[] crcTable = {0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433,0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01,0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683,0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1,0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713,0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21,0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, };///<summary>///获取CRC32校验字符串///</summary>///<param name="bytes"></param>///<returns>4字节16进制码</returns>public static string GetCRC32(byte[] bytes){int iCount = bytes.Length;UInt32 crc = 0xFFFFFFFF;for (int i = 0; i < iCount; i++){crc = ((crc >> 8) & 0x00FFFFFF) ^ crcTable[(crc ^ bytes[i]) & 0xFF];}UInt32 temp = crc ^ 0xFFFFFFFF;return temp.ToString("X8");}4.BCC异或校验///<summary>/// BCC异或取反校验///</summary>///<param name="data"></param>///<returns></returns>public static string getBCC(byte[] data){String ret = "";byte[] BCC = new byte[1];for (int i = 0; i < data.Length; i++){BCC[0] = (byte)(BCC[0] ^ data[i]);}String hex = ((~ BCC[0]) & 0xFF).ToString("X");//取反操作if (hex.Length == 1){hex = '0' + hex;}ret += hex.ToUpper();return ret;}。

我学习CRC32、CRC16、CRC原理和算法的总结(与WINRAR结果一致)

我学习CRC32、CRC16、CRC原理和算法的总结(与WINRAR结果一致)

我学习CRC32、CRC16、CRC原理和算法的总结(与WINRAR结果一致)wxleasyland(wxlwww@)2010年9月2日比较愚钝,学了CRC校验好几天,很痛苦的过程,现终于有眉目了,总结一下。

国外版的“轻松无痛苦学习CRC指南”,在/filipg/LINK/F_crc_v31.html(为什么好的资料都是老外写的?)我的英文有限,这种专业性太强的文章,很多都看不太明白,所以没办法翻译,靠参考国内的翻译和自己瞎琢磨的。

国内的翻译比较不全,而且有点误导,能看英文的还是看英文吧,国内版资料比较零散,可参考:/2001/12/08/10190.html/content/10/0703/12/1317564_36621098.shtml/data/2006/1010/article_1637.htm我结合国内资料和英文原版进行总结,达到和WINRAR一样的CRC32计算结果。

一、CRC原理可参考/articles/show_article.asp?Article_ID=15计算CRC的过程,就是用一个特殊的“除法”,来得到余数,这个余数就是CRC。

它不是真正的算术上的除法!过程和算术除法过程一样,只是加减运算变成了XOR(异或)运算!算术上的除法:120÷9=13 余 3,120是被除数,9是除数,13是商,3是余数。

念作120除以9,或者9除120,或者9去除120!(除法的过程就不写了)这个除法计算机当然会做,但是做起来很麻烦,因为减法有借位,很耗时间和指令!所以,计算CRC也是除法,但是用XOR来代替减法,这就简单多了!CRC的除法:120÷9=14 余 6,商、余数和算术除法不一定相同!!因为除法用的是XOR,而不是真正的减法。

以二进制模拟这个计算过程:1110 商为1110,即14,商有4位,表示进行了4次XOR________1001/1111000 被除数120是1111000,除数9是10011001 ^----1100 第一次XOR后得到011,加入下一位0。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

CRC16校验分析
工业通讯中传输的数据一般是先传数据字节的低位,如:实际DATA 0x38 (0011 1000) 接收端收到为0001 1100 (0x1C),所以大部分CRC校验是处理颠倒的字节数据。

有的多项式简式为0x1021(本文以0x8005为主),目前主要的CRC算法有查表法和直接计算:
1.直接计算
由于数据是颠倒的所以生成项亦要倒置:0xa001(原生成多项式CRC码为0x18005,最高位始终为1故简写为0x8005,反置得到0xa001。

计算CRC时也要从其低位开始运算,且计算中数据右移(移出高位)。

异或运算满足交换律:(A^B)^C=A^(B^C),下面分析其中一种简单算法:
C语言计算:
计算时一次计算8bits,数据与CRC生成多项式(简式)相除,除不尽的余数与下8bits数据再异或(相减),接着进入下一8bits计算。

直到len长的数据全部计算完。

2.查表法:
通过分别计算8bits(查表得到其余式)来实现逐个字节数据的
CRC
计算,直到全部字节数据计算完最后的余式就是CRC。

下面全是8bits查询表(256个余式的表)
,不过也可以4bits查询一次的计算(这样表里只需16个余式).先看程序的算法:
r=0; //r是寄存器,先初始化为0
//p0),t是查询表
字节数据
查询r高8位对应的余式,再
与新得到的式子异或
数据计算示意图:

之后再重复上面的步骤
……若待测数据未扩展0,则此时还要计算4字节扩展0的CRC:
构造CRC32查询表:
一般来说,计算CRC是用“直驱表法”算法计算的,它与上面的算法非常相似,下面分析它的计算:计算步骤为(摘自文献):
1. Shift the register left by one byte
2. XOR the top byte just rotated out of the register with the next message byte
to yield an index into the table ([0,255]).
3. XOR the table value into the register.
4. Goto 1 iff more augmented message bytes.
C语言算法为:
r=0; //r是寄存器,先初始化为0
while (len--) //len是待测数据(不用扩展0)的字节长度
r = (r<<8) ^ t[(r >> 24) ^ *p++]; //p是指向待测数据的指针,t是查询表
相当于通过移位处理了8 个bit 的数据,相当于把之前的CRC 码的高字节(8bit)全部移出,与一个byte 的数据做XOR 运算,根据运算结果来选择一个值(称为余式),与原来的CRC 码再做一次XOR 运算,就可以得到新的CRC 码。

p指向Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ、Ⅵ……字节数据,r为CRC32余式值,t为查询表。

实际上收到的数据一般是先收数据的低位,最后收到字节数据的高位,这样将数据反置了,于是算法只需稍作更改也可算出:
1. 将寄存器向右移动一个字节。

2. 将刚移出的那个字节与待测数据中的新字节做XOR运算,得到一个指向查询表的索引值。

3. 将索引所指的表值与寄存器做XOR运算。

4. 如数据没有全部处理完,则跳到步骤1。

算法为:
r=0; //r是寄存器,先初始化为0
for(i=0; i <len; i++) //len是待测数据(不用扩展0)的字节长度
{
r = t[( r^(*(p+i)) ) & 0xff] ^ (r >> 8); //p是指向待测数据的指针,t是查询表
}
注意此时的查询表不再是前文那个查询表了,它也是一个颠倒的查询表:。

相关文档
最新文档