CRC循环冗余校验(CCITT-16)

合集下载

CRC

CRC

L a b e l CRC基本释义CRC (Class,Responsibility,and Collaboration)[1]类,责任和交互,简称CRC卡片。

在面向对象程序设计中,用来阐述类、类的行为和类的责任的一个非常好的途径。

循环冗余码校验英文名称为Cyclical Redundancy Check,简称CRC 它是利用除法及余数的原理来作错误侦测(Error Detecting)的。

实际应用时,发送装置计算出CRC值并随数据一同发送给接收装置,接收装置对收到的数据重新计算CRC并与收到的CRC相比较,若两个CRC值不同,则说明数据通讯出现错误。

标准根据应用环境与习惯的不同,CRC 又可分为以下几种标准:①CRC-12码;②CRC-16码;③CRC-CCITT码;④CRC-32码。

CRC-12码通常用来传送6-bit字符串。

CRC-16及CRC-CCITT码则是用来传送8-bit字符串,其中CRC-16为美国采用,而CRC-CCITT为欧洲国家所采用。

CRC-32码大都被采用在一种称为Point-to-Point的同步传输中。

生成过程下面以最常用的CRC-16为例来说明其生成过程。

CRC-16码由两个字节构成,在开始时CRC寄存器的每一位都预置为1,然后把CRC寄存器与8-bit的数据进行异或(异或:二进制运算相同为0,不同为1;0^0=0;0^1=1;1^0=1;1^1=0),之后对CRC寄存器从高到低进行移位,在最高位(MSB)的位置补零,而最低位(LSB,移位后已经被移出CRC 寄存器)如果为1,则把寄存器与预定义的多项式码进行异或,否则如果LSB为零,则无需进行异或。

重复上述的由高至低的移位8次,第一个8-bit数据处理完毕,用此时CRC寄存器的值与下一个8-bit数据异或并进行如前一个数据似的8次移位。

所有的字符处理完成后CRC 寄存器内的值即为最终的CRC值。

计算过程1.设置CRC寄存器,并给其赋值FFFF(hex)。

C#,Java,C-循环冗余检验:CRC-16-CCITT查表法

C#,Java,C-循环冗余检验:CRC-16-CCITT查表法

C#,Java,C-循环冗余检验:CRC-16-CCITT查表法C#代码1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;56namespace TestCRC7 {8///<summary>9///循环冗余检验:CRC-16-CCITT查表法10///</summary>11public static partial class CRCITU12 {13///<summary>14///计算给定长度数据的16位CRC15///</summary>16///<param name="data">要计算CRC的字节数组</param>17///<returns>CRC值</returns>18public static UInt16 GetCrc16(Byte[] data)19 { // 初始化20 Int32 High = 0xFF; // ⾼字节21 Int32 Low = 0xFF; // 低字节22if (data != null)23 {24foreach (Byte b in data)25 {26 Int32 Index = Low ^ b;27 Low = High ^ CRC16TABLE_LO[Index];28 High = CRC16TABLE_HI[Index];29 }30 }31return (UInt16)(~((High << 8) + Low)); // 取反32 }3334///<summary>35///检查给定长度数据的16位CRC是否正确36///</summary>37///<param name="data">要校验的字节数组</param>38///<returns>39/// true:正确40/// false:错误41///</returns>42///<reamrks>43///字节数组最后2个字节为校验码,且低字节在前⾯,⾼字节在后⾯44///</reamrks>45public static Boolean IsCrc16Good(Byte[] data)46 {47// 初始化48 Int32 High = 0xFF;49 Int32 Low = 0xFF;50if (data != null)51 {52foreach (Byte b in data)53 {54 Int32 Index = Low ^ b;55 Low = High ^ CRC16TABLE_LO[Index];56 High = CRC16TABLE_HI[Index];57 }58 }5960return (High == 0xF0 && Low == 0xB8);61 }6263///<summary>64/// CRC16查找表⾼字节65///</summary>66private static readonly Byte[] CRC16TABLE_HI =67 {680x00, 0x11, 0x23, 0x32, 0x46, 0x57, 0x65, 0x74, 0x8C, 0x9D, 0xAF, 0xBE, 0xCA, 0xDB, 0xE9, 0xF8, 690x10, 0x01, 0x33, 0x22, 0x56, 0x47, 0x75, 0x64, 0x9C, 0x8D, 0xBF, 0xAE, 0xDA, 0xCB, 0xF9, 0xE8, 700x21, 0x30, 0x02, 0x13, 0x67, 0x76, 0x44, 0x55, 0xAD, 0xBC, 0x8E, 0x9F, 0xEB, 0xFA, 0xC8, 0xD9, 710x31, 0x20, 0x12, 0x03, 0x77, 0x66, 0x54, 0x45, 0xBD, 0xAC, 0x9E, 0x8F, 0xFB, 0xEA, 0xD8, 0xC9, 720x42, 0x53, 0x61, 0x70, 0x04, 0x15, 0x27, 0x36, 0xCE, 0xDF, 0xED, 0xFC, 0x88, 0x99, 0xAB, 0xBA, 730x52, 0x43, 0x71, 0x60, 0x14, 0x05, 0x37, 0x26, 0xDE, 0xCF, 0xFD, 0xEC, 0x98, 0x89, 0xBB, 0xAA, 740x63, 0x72, 0x40, 0x51, 0x25, 0x34, 0x06, 0x17, 0xEF, 0xFE, 0xCC, 0xDD, 0xA9, 0xB8, 0x8A, 0x9B, 750x73, 0x62, 0x50, 0x41, 0x35, 0x24, 0x16, 0x07, 0xFF, 0xEE, 0xDC, 0xCD, 0xB9, 0xA8, 0x9A, 0x8B, 760x84, 0x95, 0xA7, 0xB6, 0xC2, 0xD3, 0xE1, 0xF0, 0x08, 0x19, 0x2B, 0x3A, 0x4E, 0x5F, 0x6D, 0x7C, 770x94, 0x85, 0xB7, 0xA6, 0xD2, 0xC3, 0xF1, 0xE0, 0x18, 0x09, 0x3B, 0x2A, 0x5E, 0x4F, 0x7D, 0x6C, 780xA5, 0xB4, 0x86, 0x97, 0xE3, 0xF2, 0xC0, 0xD1, 0x29, 0x38, 0x0A, 0x1B, 0x6F, 0x7E, 0x4C, 0x5D, 790xB5, 0xA4, 0x96, 0x87, 0xF3, 0xE2, 0xD0, 0xC1, 0x39, 0x28, 0x1A, 0x0B, 0x7F, 0x6E, 0x5C, 0x4D, 800xC6, 0xD7, 0xE5, 0xF4, 0x80, 0x91, 0xA3, 0xB2, 0x4A, 0x5B, 0x69, 0x78, 0x0C, 0x1D, 0x2F, 0x3E, 810xD6, 0xC7, 0xF5, 0xE4, 0x90, 0x81, 0xB3, 0xA2, 0x5A, 0x4B, 0x79, 0x68, 0x1C, 0x0D, 0x3F, 0x2E, 820xE7, 0xF6, 0xC4, 0xD5, 0xA1, 0xB0, 0x82, 0x93, 0x6B, 0x7A, 0x48, 0x59, 0x2D, 0x3C, 0x0E, 0x1F, 830xF7, 0xE6, 0xD4, 0xC5, 0xB1, 0xA0, 0x92, 0x83, 0x7B, 0x6A, 0x58, 0x49, 0x3D, 0x2C, 0x1E, 0x0F 84 };8586///<summary>87/// CRC16查找表低字节88///</summary>89private static readonly Byte[] CRC16TABLE_LO =90 {910x00, 0x89, 0x12, 0x9B, 0x24, 0xAD, 0x36, 0xBF, 0x48, 0xC1, 0x5A, 0xD3, 0x6C, 0xE5, 0x7E, 0xF7, 920x81, 0x08, 0x93, 0x1A, 0xA5, 0x2C, 0xB7, 0x3E, 0xC9, 0x40, 0xDB, 0x52, 0xED, 0x64, 0xFF, 0x76, 930x02, 0x8B, 0x10, 0x99, 0x26, 0xAF, 0x34, 0xBD, 0x4A, 0xC3, 0x58, 0xD1, 0x6E, 0xE7, 0x7C, 0xF5, 940x83, 0x0A, 0x91, 0x18, 0xA7, 0x2E, 0xB5, 0x3C, 0xCB, 0x42, 0xD9, 0x50, 0xEF, 0x66, 0xFD, 0x74, 950x04, 0x8D, 0x16, 0x9F, 0x20, 0xA9, 0x32, 0xBB, 0x4C, 0xC5, 0x5E, 0xD7, 0x68, 0xE1, 0x7A, 0xF3, 960x85, 0x0C, 0x97, 0x1E, 0xA1, 0x28, 0xB3, 0x3A, 0xCD, 0x44, 0xDF, 0x56, 0xE9, 0x60, 0xFB, 0x72, 970x06, 0x8F, 0x14, 0x9D, 0x22, 0xAB, 0x30, 0xB9, 0x4E, 0xC7, 0x5C, 0xD5, 0x6A, 0xE3, 0x78, 0xF1, 980x87, 0x0E, 0x95, 0x1C, 0xA3, 0x2A, 0xB1, 0x38, 0xCF, 0x46, 0xDD, 0x54, 0xEB, 0x62, 0xF9, 0x70, 990x08, 0x81, 0x1A, 0x93, 0x2C, 0xA5, 0x3E, 0xB7, 0x40, 0xC9, 0x52, 0xDB, 0x64, 0xED, 0x76, 0xFF, 1000x89, 0x00, 0x9B, 0x12, 0xAD, 0x24, 0xBF, 0x36, 0xC1, 0x48, 0xD3, 0x5A, 0xE5, 0x6C, 0xF7, 0x7E, 1010x0A, 0x83, 0x18, 0x91, 0x2E, 0xA7, 0x3C, 0xB5, 0x42, 0xCB, 0x50, 0xD9, 0x66, 0xEF, 0x74, 0xFD, 1020x8B, 0x02, 0x99, 0x10, 0xAF, 0x26, 0xBD, 0x34, 0xC3, 0x4A, 0xD1, 0x58, 0xE7, 0x6E, 0xF5, 0x7C, 1030x0C, 0x85, 0x1E, 0x97, 0x28, 0xA1, 0x3A, 0xB3, 0x44, 0xCD, 0x56, 0xDF, 0x60, 0xE9, 0x72, 0xFB, 1040x8D, 0x04, 0x9F, 0x16, 0xA9, 0x20, 0xBB, 0x32, 0xC5, 0x4C, 0xD7, 0x5E, 0xE1, 0x68, 0xF3, 0x7A, 1050x0E, 0x87, 0x1C, 0x95, 0x2A, 0xA3, 0x38, 0xB1, 0x46, 0xCF, 0x54, 0xDD, 0x62, 0xEB, 0x70, 0xF9, 1060x8F, 0x06, 0x9D, 0x14, 0xAB, 0x22, 0xB9, 0x30, 0xC7, 0x4E, 0xD5, 0x5C, 0xE3, 0x6A, 0xF1, 0x78 107 };108 }109 }C# CRC16代码Java代码1import com.example.utils.BitConverter;2345/**6 * 循环冗余检验:CRC-16-CCITT查表法7*/8public final class CRC16 {910public static void main(String[] args) {11short result=CRC16.GetCrc16(new byte[]{1,2,3});12 System.out.println(Integer.toHexString(result));13 }14/**15 * 计算给定长度数据的16位CRC16 *17 * @param data18 * 要计算CRC的字节数组19 * @return CRC值20*/21public static short GetCrc16(byte[] data) { // 初始化22int High = 0xFF; // ⾼字节23int Low = 0xFF; // 低字节24if (data != null) {25for (byte b : data) {26int Index = Low ^ b;27 Low = High ^ CRC16TABLE_LO[Index];28 High = CRC16TABLE_HI[Index];29 }30 }31return (short) (~((High << 8) + Low)); // 取反32 }3334/**35 * 检查给定长度数据的16位CRC是否正确36 *37 * @param data38 * 要校验的字节数组39 * @return true:正确 false:错误40 *41 * <reamrks> 字节数组最后2个字节为校验码,且低字节在前⾯,⾼字节在后⾯ </reamrks> 42*/43public static boolean IsCrc16Good(byte[] data) {44// 初始化45int High = 0xFF;46int Low = 0xFF;47if (data != null) {48for (byte b : data) {49int Index = Low ^ b;50 Low = High ^ CRC16TABLE_LO[Index];51 High = CRC16TABLE_HI[Index];52 }53 }5455return (High == 0xF0 && Low == 0xB8);56 }5758/**59 * CRC16查找表⾼字节60*/61private static final int[] CRC16TABLE_HI = { 0x00, 0x11, 0x23, 0x32, 0x46,62 0x57, 0x65, 0x74, 0x8C, 0x9D, 0xAF, 0xBE, 0xCA, 0xDB, 0xE9, 0xF8,63 0x10, 0x01, 0x33, 0x22, 0x56, 0x47, 0x75, 0x64, 0x9C, 0x8D, 0xBF,64 0xAE, 0xDA, 0xCB, 0xF9, 0xE8, 0x21, 0x30, 0x02, 0x13, 0x67, 0x76,65 0x44, 0x55, 0xAD, 0xBC, 0x8E, 0x9F, 0xEB, 0xFA, 0xC8, 0xD9, 0x31,66 0x20, 0x12, 0x03, 0x77, 0x66, 0x54, 0x45, 0xBD, 0xAC, 0x9E, 0x8F,67 0xFB, 0xEA, 0xD8, 0xC9, 0x42, 0x53, 0x61, 0x70, 0x04, 0x15, 0x27,68 0x36, 0xCE, 0xDF, 0xED, 0xFC, 0x88, 0x99, 0xAB, 0xBA, 0x52, 0x43,69 0x71, 0x60, 0x14, 0x05, 0x37, 0x26, 0xDE, 0xCF, 0xFD, 0xEC, 0x98,70 0x89, 0xBB, 0xAA, 0x63, 0x72, 0x40, 0x51, 0x25, 0x34, 0x06, 0x17,71 0xEF, 0xFE, 0xCC, 0xDD, 0xA9, 0xB8, 0x8A, 0x9B, 0x73, 0x62, 0x50,72 0x41, 0x35, 0x24, 0x16, 0x07, 0xFF, 0xEE, 0xDC, 0xCD, 0xB9, 0xA8,73 0x9A, 0x8B, 0x84, 0x95, 0xA7, 0xB6, 0xC2, 0xD3, 0xE1, 0xF0, 0x08,74 0x19, 0x2B, 0x3A, 0x4E, 0x5F, 0x6D, 0x7C, 0x94, 0x85, 0xB7, 0xA6,75 0xD2, 0xC3, 0xF1, 0xE0, 0x18, 0x09, 0x3B, 0x2A, 0x5E, 0x4F, 0x7D,76 0x6C, 0xA5, 0xB4, 0x86, 0x97, 0xE3, 0xF2, 0xC0, 0xD1, 0x29, 0x38,77 0x0A, 0x1B, 0x6F, 0x7E, 0x4C, 0x5D, 0xB5, 0xA4, 0x96, 0x87, 0xF3,78 0xE2, 0xD0, 0xC1, 0x39, 0x28, 0x1A, 0x0B, 0x7F, 0x6E, 0x5C, 0x4D,79 0xC6, 0xD7, 0xE5, 0xF4, 0x80, 0x91, 0xA3, 0xB2, 0x4A, 0x5B, 0x69,80 0x78, 0x0C, 0x1D, 0x2F, 0x3E, 0xD6, 0xC7, 0xF5, 0xE4, 0x90, 0x81,81 0xB3, 0xA2, 0x5A, 0x4B, 0x79, 0x68, 0x1C, 0x0D, 0x3F, 0x2E, 0xE7,82 0xF6, 0xC4, 0xD5, 0xA1, 0xB0, 0x82, 0x93, 0x6B, 0x7A, 0x48, 0x59,83 0x2D, 0x3C, 0x0E, 0x1F, 0xF7, 0xE6, 0xD4, 0xC5, 0xB1, 0xA0, 0x92,84 0x83, 0x7B, 0x6A, 0x58, 0x49, 0x3D, 0x2C, 0x1E, 0x0F };8586/**87 * CRC16查找表低字节88*/89private static final int[] CRC16TABLE_LO = { 0x00, 0x89, 0x12, 0x9B, 0x24,90 0xAD, 0x36, 0xBF, 0x48, 0xC1, 0x5A, 0xD3, 0x6C, 0xE5, 0x7E, 0xF7,91 0x81, 0x08, 0x93, 0x1A, 0xA5, 0x2C, 0xB7, 0x3E, 0xC9, 0x40, 0xDB,92 0x52, 0xED, 0x64, 0xFF, 0x76, 0x02, 0x8B, 0x10, 0x99, 0x26, 0xAF,93 0x34, 0xBD, 0x4A, 0xC3, 0x58, 0xD1, 0x6E, 0xE7, 0x7C, 0xF5, 0x83,94 0x0A, 0x91, 0x18, 0xA7, 0x2E, 0xB5, 0x3C, 0xCB, 0x42, 0xD9, 0x50,95 0xEF, 0x66, 0xFD, 0x74, 0x04, 0x8D, 0x16, 0x9F, 0x20, 0xA9, 0x32,96 0xBB, 0x4C, 0xC5, 0x5E, 0xD7, 0x68, 0xE1, 0x7A, 0xF3, 0x85, 0x0C,97 0x97, 0x1E, 0xA1, 0x28, 0xB3, 0x3A, 0xCD, 0x44, 0xDF, 0x56, 0xE9,98 0x60, 0xFB, 0x72, 0x06, 0x8F, 0x14, 0x9D, 0x22, 0xAB, 0x30, 0xB9,99 0x4E, 0xC7, 0x5C, 0xD5, 0x6A, 0xE3, 0x78, 0xF1, 0x87, 0x0E, 0x95, 100 0x1C, 0xA3, 0x2A, 0xB1, 0x38, 0xCF, 0x46, 0xDD, 0x54, 0xEB, 0x62, 101 0xF9, 0x70, 0x08, 0x81, 0x1A, 0x93, 0x2C, 0xA5, 0x3E, 0xB7, 0x40, 102 0xC9, 0x52, 0xDB, 0x64, 0xED, 0x76, 0xFF, 0x89, 0x00, 0x9B, 0x12, 103 0xAD, 0x24, 0xBF, 0x36, 0xC1, 0x48, 0xD3, 0x5A, 0xE5, 0x6C, 0xF7, 104 0x7E, 0x0A, 0x83, 0x18, 0x91, 0x2E, 0xA7, 0x3C, 0xB5, 0x42, 0xCB, 105 0x50, 0xD9, 0x66, 0xEF, 0x74, 0xFD, 0x8B, 0x02, 0x99, 0x10, 0xAF, 106 0x26, 0xBD, 0x34, 0xC3, 0x4A, 0xD1, 0x58, 0xE7, 0x6E, 0xF5, 0x7C, 107 0x0C, 0x85, 0x1E, 0x97, 0x28, 0xA1, 0x3A, 0xB3, 0x44, 0xCD, 0x56, 108 0xDF, 0x60, 0xE9, 0x72, 0xFB, 0x8D, 0x04, 0x9F, 0x16, 0xA9, 0x20, 109 0xBB, 0x32, 0xC5, 0x4C, 0xD7, 0x5E, 0xE1, 0x68, 0xF3, 0x7A, 0x0E, 110 0x87, 0x1C, 0x95, 0x2A, 0xA3, 0x38, 0xB1, 0x46, 0xCF, 0x54, 0xDD, 111 0x62, 0xEB, 0x70, 0xF9, 0x8F, 0x06, 0x9D, 0x14, 0xAB, 0x22, 0xB9, 112 0x30, 0xC7, 0x4E, 0xD5, 0x5C, 0xE3, 0x6A, 0xF1, 0x78 };113 }Java CRC16代码C代码1 using System;2 using System.Collections.Generic;3 using System.Linq;4 using System.Text;56 namespace mon7 {8/// <summary>9/// 循环冗余检验:CRC-16-CCITT查表法10/// </summary>11public static partial class CRCITU12 {13/// <summary>14/// 计算给定长度数据的16位CRC15/// </summary>16/// <param name="data">要计算CRC的字节数组</param>17/// <returns>CRC值</returns>18public static byte[] GetCrc16(Byte[] buffer)19 {20int crc = 0;21int l = buffer.Length;22for (int i = 0; i < l; i++)23 {24int by = (crc >> 8) & 0xff;25 crc = (crc & 0xffff) << 8;26 crc = (crc ^ table[(buffer[i] ^ by) & 0xff]) & 0xffff;27 }2829return GetCRCBytes(crc);3031 }32/// <summary>33/// 获取CRC字节数组34/// </summary>35/// <param name="crc">整形的CRC</param>36/// <returns>两字节的CRC字节数组</returns>37private static byte[] GetCRCBytes(int crc)38 {39byte[] result = BitConverter.GetBytes(crc);40 Array.Resize(ref result, 2); //只截取前⾯两个byte字节4142return result;43 }4445464748static int[] table = {49 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a,50 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,51 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6,52 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672,53 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d,54 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af,55 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd,56 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03,57 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5,58 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,59 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004,60 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290,61 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c,62 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,63 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c,64 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1,65 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37,66 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,67 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b,68 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef069 };7071/// <summary>72/// 检查给定长度数据的16位CRC是否正确73/// </summary>74/// <param name="FromHeadToVaild">要校验的字节数组</param>75/// <returns>76/// true:正确77/// false:错误78/// </returns>79/// <reamrks>80/// 字节数组最后2个字节为校验码81/// </reamrks>82public static Boolean IsCrc16Good(Byte[] FromHeadToCRC)83 {84byte[] FromHeadToVaild = GetHeadToVaildData(FromHeadToCRC); //头到验证域85byte[] CRCFromPackage = GetCRCFromPackage(FromHeadToCRC); //获取客户端传来的包中的CRC数组 86byte[] TrueCRCValue = GetCrc16(FromHeadToVaild); //获取客户端传来的包应该的CRC数组87return BytesEquals(CRCFromPackage, TrueCRCValue);88 }89/// <summary>90/// ⽐较两个字节数组是否相等91/// </summary>92/// <param name="b1">byte数组1</param>93/// <param name="b2">byte数组2</param>94/// <returns>是否相等</returns>95private static bool BytesEquals(byte[] b1, byte[] b2)96 {97if (b1.Length != b2.Length) return false;98if (b1 == null || b2 == null) return false;99for (int i = 0; i < b1.Length; i++)100if (b1[i] != b2[i])101return false;102return true;103 }104105106/// <summary>107/// 获取客户端传来的包中的CRC数组108/// </summary>109/// <param name="FromHeadToCRC">从头到CRC校验域</param>110/// <returns>CRC数组</returns>111private static byte[] GetCRCFromPackage(byte[] FromHeadToCRC)112 {113int iCRCLen = 2; //因为CRC占两个字节114byte[] CRCValue = new byte[iCRCLen]; //⽤于存储包中CRC的值115int i;116for (i = 0; i < iCRCLen; i++) //得到⼀个临时字节数组117 {118 CRCValue[i] = FromHeadToCRC[FromHeadToCRC.Length - iCRCLen + i];119 }120return CRCValue;121 }122/// <summary>123/// 得到从头到有效数据的数据(不包含CRC验证域)124/// </summary>125/// <param name="FromHeadToCRC"></param>126/// <returns></returns>127private static byte[] GetHeadToVaildData(byte[] FromHeadToCRC)128 {129int iLengh = FromHeadToCRC.Length - 2; //因为CRC占两个字节130byte[] FromHeadToVaild = new byte[iLengh]; //⽤于存储包头到有效数据域的bytes 131int i;132for (i = 0; i < iLengh; i++) //得到⼀个临时字节数组133 {134 FromHeadToVaild[i] = FromHeadToCRC[i];135 }136return FromHeadToVaild;137138 }139140 }141142 }C语⾔ CRC16代码。

CRC循环冗余校验码总结(转)

CRC循环冗余校验码总结(转)

CRC循环冗余校验码总结(转)⼀、CRC简介先在此说明下什么是CRC:循环冗余码校验英⽂名称为Cyclical Redundancy Check,简称CRC,它是利⽤除法及余数的原理来作错误侦测(Error Detecting)的。

实际应⽤时,发送装置计算出CRC值并随数据⼀同发送给接收装置,接收装置对收到的数据重新计算CRC并与收到的CRC相⽐较,若两个CRC值不同,则说明数据通讯出现错误那么其实CRC有⽐较多种,⽐如CRC16、CRC32 ,为什么叫16、32呢。

在这⾥并⾮与位有和关系。

⽽是由所确定的多项式最⾼次幂确定的。

如下所⽰。

理论上讲幂次越⾼校验效果越好。

CRC(12位) =X12+X11+X3+X2+X+1 CRC(16位) = X16+X15+X2+1 CRC(CCITT) = X16+X12 +X5+1 CRC(32位) = X32+X26+X23+X16+X12+X11+X10+ X8+X7+X5+X4+X2+X+1⼆、循环冗余校验码(CRC)的基本原理:在K位信息码后再拼接R位的校验码,整个编码长度为N位,因此,这种编码⼜叫(N,K)码。

对于⼀个给定的(N,K)码,可以证明存在⼀个最⾼次幂为N-K=R的多项式G(x)。

根据G(x)可以⽣成K 位信息的校验码,⽽G(x)叫做这个CRC码的⽣成多项式。

校验码的具体⽣成过程为:假设发送信息⽤信息多项式C(X)表⽰,将C(x)左移R位,则可表⽰成C(x)*2R,这样C(x)的右边就会空出R位,这就是校验码的位置。

通过C(x)*2R除以⽣成多项式G(x)得到的余数就是校验码。

原理思维导图总结:三、通信与⽹络中常⽤的CRC在数据通信与⽹络中,通常k相当⼤,由⼀千甚⾄数千数据位构成⼀帧,⽽后采⽤CRC码产⽣r位的校验位。

它只能检测出错误,⽽不能纠正错误。

⼀般取r=16,标准的16位⽣成多项式有CRC-16=x16+x15+x2+1 和CRC-CCITT=x16+x15+x2+1。

很多讲的都是CRC16-CCITT标准-一直想弄明白CRC-16标(汇编)

很多讲的都是CRC16-CCITT标准-一直想弄明白CRC-16标(汇编)

最近在搞CRC校验,用的是CRC16标准,查看了很多资料发现很多讲的都是CRC16-CCITT标准,一直想弄明白CRC-16标准中的采用查表法的方式中那两个表格中的数是如何求出来的。

可惜没有一个文章仔细的讲,更没有文章给出实例来算一算。

一切只能靠自己了,谁让我喜欢寻根摸底呢。

研究了一下本站会员玉丫子的文章,自己琢磨了琢磨,终于知道是怎么算出来的了。

CRC16算法的生成多项式x^16 + x^15 + x^2 + 1,十六进制表示为0x8005。

CRC16常见的表格中的数据是按照先传输LSB,消息右移进寄存器来计算的。

因此需要判断寄存器的最低位LSB,同时要将0x8005按位颠倒后(0xA001)根据LSB的情况决定是否与寄存器异或即可。

CRC16的表格中对应的数依次为0~255计算出来的CRC值,因此,此处只选取其中一两个数作为实例计算CRC值。

具体步骤如下所示:1)从0~255中选取需要计算的数,将其对应的十六进制数放入一个长度为16的寄存器的低八位,高八位填充0;2)如果寄存器的末位LSB为1,将寄存器的数值右移1位,再与0xA001位异或,否则仅将寄存器右移1位;3)重复第2步,直到低八位全部右移出寄存器;4)寄存器中的值则为校验码。

从0~255中挑选2(对应0x02)计算其CRC值:0x02的CRC-16的表格计算(反向)00000000 00000010 <- 最低位LSB = 0,高八位填充000000000 000000010 右移,高位填充0,并舍弃最后一位----------------- 第一次计算00000000 00000001 <- LSB = 100000000 000000001 右移,舍弃最后一位^10100000 00000001 <-与0xA001异或----------------- 第二次10100000 00000001 <- LSB = 101010000 000000001右移,舍弃最后一位^10100000 00000001 <-与0xA001异或----------------- 第三次11110000 00000001 <- LSB = 101111000 000000001右移,舍弃最后一位^10100000 00000001 <-与0xA001异或----------------- 第四次11011000 00000001 <- LSB = 101101100 000000001右移,舍弃最后一位^10100000 00000001 <-与0xA001异或----------------- 第五次11001100 00000001 <- LSB = 101100110 000000001右移,舍弃最后一位^10100000 00000001 <-与0xA001异或----------------- 第六次11000110 00000001 <- LSB = 101100011 000000001右移,舍弃最后一位^10100000 00000001 <-与0xA001异或----------------- 第七次11000011 00000001 <- LSB = 101100001 100000001右移,舍弃最后一位^10100000 00000001 <-与0xA001异或----------------- 一共右移了八次,得到的结果为CRC11000001 10000001 <- CRC: 0xC1 81从本文最后的附表中可以看出auchCRCHi[]的第三个值就是0x 81,auchCRCLo[]的第三个值就是0xC1,可见计算无误。

最详细易懂的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 信息正确。

crc16-ccitt标准

crc16-ccitt标准

crc16 ccitt标准CRC16 CCITT(循环冗余校验16位CCITT标准)是一种广泛用于通信和数据传输中的错误检测技术。

在本文中,我们将一步一步回答关于CRC16 CCITT标准的问题,并对其原理和应用进行详细解释。

第一步:CRC是什么意思?CRC代表循环冗余校验(Cyclic Redundancy Check),是一种通过计算和比较校验码来检测和纠正数据传输中的错误的技术。

校验码是在发送数据之前添加到数据中的,接收端使用相同的算法重新计算校验码,然后将其与接收到的校验码进行比较,以检测任何错误。

第二步:CRC16 CCITT是什么?CRC16 CCITT是使用16位宽度进行计算的CRC校验算法,其标准由国际电报电话咨询委员会(Consultative Committee for International Telegraphy and Telephony,简称CCITT)制定。

CRC16 CCITT使用的多项式是x^16 + x^12 + x^5 + 1。

第三步:CRC16 CCITT的工作原理是什么?CRC16 CCITT的工作原理基于多项式除法。

它将数据和一个预设的16位初始值一起输入算法。

算法按位将数据与多项式进行按位异或运算。

然后,算法将结果进行移位,直到所有的数据位都被处理完毕。

最后,算法得到一个16位的校验码,该码附加在数据中发送给接收端。

第四步:CRC16 CCITT的校验方法是什么?接收端使用相同的多项式和初始值将接收到的数据进行计算,得到一个校验码。

然后,接收端将该校验码与发送端附加的校验码进行比较。

如果两个校验码一致,表明数据在传输过程中没有错误。

如果两个校验码不一致,则表明数据传输过程中存在错误。

第五步:CRC16 CCITT的应用领域有哪些?CRC16 CCITT广泛应用于通信和数据传输领域。

它在串行通信中的应用非常常见,可以用于检测串行数据传输中的位错误、丢失、重复或颠倒。

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

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

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

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

例如:代码1010111对应的多项式为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信息字段校验字段接收方:使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则信息正确。

C语言实现CRC16校验

C语言实现CRC16校验

C语言实现CRC16校验第一步,了解CRC16算法的原理。

CRC(Cyclic Redundancy Check)是一种常用的数据校验方法,CRC16是其中一种具体实现。

CRC16算法首先将待校验的数据按照特定的规则进行处理,得到一个CRC值,然后将这个CRC值附加到待校验数据的末尾。

接收方收到数据后,同样按照相同的规则计算校验值,并与接收数据中附带的CRC值进行比较,如果两个值相同,则数据传输无误,否则说明数据出错。

第二步,确定CRC16算法使用的多项式。

CRC16算法可以使用不同的多项式,常见的有CCITT标准的多项式(0x1021)和IBM标准的多项式(0x8005)。

在实现CRC16校验时,需要确定使用哪个多项式。

第三步,编写CRC16校验函数。

在C语言中,可以通过位运算和异或运算来实现CRC16校验算法。

下面是一个简单的CRC16校验函数的示例代码:```c#include <stdint.h>#define CRC16_POLYNOMIAL_CCITT 0x1021uint16_t crc16_ccitt(uint8_t *data, uint16_t length)uint16_t crc = 0xFFFF;for (uint16_t i = 0; i < length; i++)crc ^= (uint16_t)data[i] << 8;for (uint8_t j = 0; j < 8; j++)if (crc & 0x8000)crc = (crc << 1) ^ CRC16_POLYNOMIAL_CCITT;}elsecrc <<= 1;}}}return crc;```在这个示例代码中,`data`是待校验数据的指针,`length`是待校验数据的长度。

函数使用CCITT标准的多项式(0x1021),首先将CRC初始化为0xFFFF,然后按照数据的每个字节进行迭代运算。

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

CRC 循环冗余校验(CCITT-16)
START
MOVLW
DATAe
MOVWF ADDR
;将[e 00]余式表首地址DATAe 存入ADDR SWAPF BYTEa ,0ANDLW 0FH ;求e 和e 指定的[e 00]余式高字节的相对地址ADDWF
ADDR ,1
;取其绝对地址,存入ADDR MOVF
ADDR ,0
;把这一绝对地址再存入W
CALL TABLE ;查表,返回时h e 00放
W 中
MOVWF RESULTh ;把
h e 00

RESULTh
MOVLW 16ADDWF ADDR ,0;求e 指定的[e 00]
式低字节的绝对地址CALL TABLE ;查表,返回时l e 00放W 中
MOVWF RESULTl ;把l e 00存入RESUL MOVLW DATAf MOVWF ADDR ;将[f 00]余式表首
址DATAf 存入ADDR
MOVF BYTEa ,0ANDLW
0FH
;求f 和f 指定的[f 0
余式高字节的相对址
ADDWF ADDR ,1;取其绝对地址,存ADDR
MOVF ADDR ,0;把这一绝对地址再存W
CALL TABLE ;查表,返回时h f 00放
W 中
XORWF RESULTh ,0;h e
00与h f
00异或,
h a 00,存入W XORWF BYTEb ,0;h a 00与b 异或,h abc ,存入W
MOVF BYTEa ;h abc 存入BYTEa
MOVLW 16ADDWF ADDR ,0;求f 指定的[f 00]式低字节的绝对地址CALL
TABLE
;查表,返回时l f 00放W 中。

相关文档
最新文档