最详细易懂的CRC-16校验原理(附源程序)
crc16modbus校验例程
CRC16Modbus校验例程在现代通信领域中,数据的准确性和完整性至关重要。
为了确保数据传输过程中不会出错,校验算法成为了不可或缺的一部分。
CRC (Cyclic Redundancy Check)是一种常用的校验算法,它通过对数据进行处理,生成一段校验码,可以在接收端对数据进行验证,以判断数据是否在传输过程中发生了错误。
在工业控制和自动化领域中,Modbus通信协议是一种常用的通信协议,广泛应用于各种工业设备之间的通信。
而在Modbus协议中,CRC16Modbus校验算法就是其中的一种,它是一种针对Modbus协议设计的CRC校验算法。
下面将介绍CRC16Modbus校验算法的具体实现和例程。
一、CRC16Modbus校验算法简介CRC16Modbus是一种16位的CRC校验算法,其生成多项式为0x8005,初始值为0xFFFF。
CRC16Modbus算法的数学模型可以表示为:1. 初始化CRC寄存器为0xFFFF;2. 依次处理每个字节,按位异或并循环移位;3. 处理完所有字节后,对CRC寄存器进行一次最终的异或操作。
二、CRC16Modbus校验算法的实现在实际代码实现中,CRC16Modbus校验算法可以通过多种方式来实现,以下是一种基于C语言的实现例程:```c#include <stdint.h>uint16_t calcCrc16Modbus(uint8_t *data, uint16_t length) {uint16_t crc = 0xFFFF;for (uint16_t i = 0; i < length; i++) {crc ^= ((uint16_t)data[i]);for (uint16_t j = 0; j < 8; j++) {if ((crc 1) == 1) {crc = (crc >> 1) ^ 0xA001;} else {crc = crc >> 1;}}}return crc;}以上代码实现了一个名为calcCrc16Modbus的函数,该函数接收一个uint8_t类型的数据指针和数据长度作为参数,返回一个uint16_t 类型的CRC校验值。
最详细易懂的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信息字段校验字段接收方:使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则信息正确。
16位CRC校验码计算程序
16位CRC校验码计算程序/*************************************************************** 16位CRC计算方法1(预置1个16位的寄存器为十六进制FFFF(即全为1);称此寄存器为CRC寄存器; 2(把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器;3(把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位; 4(如果移出位为0:重复第3步(再次右移一位);如果移出位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或; 5(重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理; 6(重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;7(将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC;*****************************************************************/ /******************************************************************* *********名称: UART_CRC16_Work()说明: CRC16校验程序参数: *CRC_Buf:数据地址CRC_Leni:数据长度返回: CRC_Sumx:校验值******************************************************************** *********/unsigned int UART_CRC16_Work(unsigned char *CRC_Buf,unsigned char CRC_Leni) {unsigned char i,j;unsigned int CRC_Sumx;CRC_Sumx=0xFFFF;for(i=0;i<CRC_Leni;i++){CRC_Sumx^=*(CRC_Buf+i);//异或for(j=0;j<8;j++){if(CRC_Sumx & 0x01){CRC_Sumx>>=1;CRC_Sumx^=0xA001;}else{CRC_Sumx>>=1;}}}return (CRC_Sumx);}Crc_Length = 9;for(k=0;k<9;k++)Crc_Buf[k]=ReceiveBuf[k];Crc_Value=Crc16(Crc_Buf,Crc_Length);Crc_ReceiveValue=ReceiveBuf[9];Crc_ReceiveValue=(Crc_ReceiveValue<<8)+ReceiveBuf[10];if(Crc_Value==Crc_ReceiveValue) unsigned int Crc16(unsigned char *pBuf, unsigned char num) {unsigned char i,j;unsigned int wCrc = 0xFFFF;for(i=0; i<num; i++){wCrc ^= (uint)(pBuf[i]);for(j=0; j<8; j++){if(wCrc & 1){wCrc >>= 1; wCrc ^= 0xA001; }elsewCrc >>= 1; }}return wCrc; }。
最详细易懂的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校验算法c语言
crc16校验算法c语言crc16校验算法是一种常用的数据校验方法,它可以检测出数据传输或存储过程中的错误,并提供纠错的依据。
crc16校验算法的原理是将待校验的数据看作一个多项式,用一个固定的生成多项式对其进行除法运算,得到的余数就是crc16校验码。
生成多项式的选择会影响crc16校验算法的性能,不同的应用场景可能需要不同的生成多项式。
本文主要介绍一种常用的生成多项式,即CRC-CCITT,它的二进制表示为0x1021,十六进制表示为0x11021。
本文将介绍三种实现crc16校验算法c语言的方法,分别是按位计算、按半字节计算和按单字节计算。
这三种方法的原理都是基于生成多项式对数据进行除法运算,但是具体的实现方式有所不同,各有优缺点。
下面分别介绍这三种方法,并给出相应的c语言代码。
按位计算按位计算是最直接的实现方式,它是将待校验的数据和生成多项式按位进行异或运算,得到余数。
这种方法的优点是不需要额外的存储空间,缺点是效率较低,需要循环处理每一位数据。
按位计算的c语言代码如下:#include<stdint.h>#define CRC_CCITT 0x1021//生成多项式//函数名称:crc_cal_by_bit;按位计算CRC//函数参数:uint8_t * ptr;指向发送缓冲区的首字节// uint32_t len;要发送的总字节数//函数返回值:uint16_tuint16_t crc_cal_by_bit(uint8_t*ptr, uint32_t len) {uint32_t crc =0xffff; //初始值while (len--!=0) {for (uint8_t i =0x80; i !=0; i >>=1) { //处理每一位数据crc <<=1; //左移一位if ((crc &0x10000) !=0) //如果最高位为1,则异或生成多项式crc ^=0x11021;if ((*ptr & i) !=0) //如果当前数据位为1,则异或生成多项式crc ^= CRC_CCITT;}ptr++; //指向下一个字节}uint16_t retCrc = (uint16_t)(crc &0xffff); //取低16位作为结果return retCrc;}按半字节计算按半字节计算是对按位计算的优化,它是将待校验的数据和生成多项式按半字节(4位)进行异或运算,得到余数。
CRC16校验C语言程序源码(附完整的可执行的C语言代码)
CRC16校验C 语言程序源码 (附完整的可执行的 C 语言代码)//CRC16校验在通讯中应用广泛,这里不对其理论进行讨论,只对常见的 2种//实现方法进行测试。
方法一:查表法(256长度的校验表)速度快,准确,但是对于单片机设备存储占用大,且校验表长度大,输入时容易岀现错误 // .................. --POPULAR POLYNOMIALS ....................// CCITT: x A 16 + x A 12 + x A 5 + x A 0(0x1021) // CRC-16: x A 16 + xA15 + xA2 + xA0(0x8005)#defi neCRC_16_POLYNOMIALS0x8005const BYTE chCRCHTalbe[]=// CRC 高位字节值表{0x00, 0xC1, 0x81, 0x40, 0x01, OxCO, 0x80, 0x41, 0x01, OxCO, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1,0x81,0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1,0x81,0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41,0x00, 0xC1,0x81,0x40,0x01, 0xC0, 0x80, 0x41,0x01,0xC0, 0x80, 0x41, 0x00, 0xC1,0x81,0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1,0x81,0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01,0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01,0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1,0x81,0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01,0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40 };con st BYTE chCRCLTalbe[] = // CRC 低位字节值表 {0x00, 0xC0, 0xC1,0x01,0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1代 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, OxD1, OxDO, 0x10, OxFO, 0x30, 0x31, OxF1,0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61,0xA1,0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,0x41, 0x81, 0x80, 0x40};WORD CRC16_1(BYTE* pchMsg, WORD wDataLe n){BYTE chCRCHi = 0xFF; // 高CRC字节初始化BYTE chCRCLo = 0xFF; // 低CRC字节初始化WORD win dex; // CRC 循环中的索引while (wDataLe n--){// 计算CRCwin dex = chCRCLo A *pchMsg++ ;chCRCLo = chCRCHi A chCRCHTalbe[wl ndex]; chCRCHi =chCRCLTalbe[wi ndex];}return ((chCRCHi << 8) | chCRCLo);}方法一:列表法(简单表)con st WORD wCRCTalbeAbs[]={0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800,0xB401,0x5000, 0x9C01,0x8801,0x4400,};WORD CRC16_2(BYTE* pchMsg, WORD wDataLe n){WORD wCRC = OxFFFF;WORD i;BYTE chChar;for (i = 0; i < wDataLe n; i++){chChar = *pchMsg++;wCRC = wCRCTalbeAbs[(chChar A wCRC)& 15] A (wCRC>> 4);wCRC = wCRCTalbeAbs[((chChar >> 4) A wCRC) & 15] A (wCRC >> 4);}return wCRC;}方法二:定义法根据CRC16/MODBUS理直接计算,算法简单但对单片机计算压力大。
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]。
CRC-16
CRC-16介绍及例程循环冗余校验(英语:Cyclic redundancy check,通称“CRC”)是一种根据网络数据数据包或电脑文件等数据产生简短固定位数校验码的一种散列函數,主要用来检测或校验数据传输或者保存后可能出现的错误。
生成的数字在传输或者存储之前计算出来并且附加到数据后面,然后接收方进行检验确定数据是否发生变化。
一般来说,循环冗余校验的值都是32位的整数。
由于本函数易于用二进制的电脑硬件使用、容易进行数学分析并且尤其善于检测传输通道干扰引起的错误,因此获得广泛应用。
一、简介CRC为校验和的一种,是两个字节数据流采用二进制除法(没有进位,使用XOR来代替减法)相除所得到的余数。
其中被除数是需要计算校验和的信息数据流的二进制表示;除数是一个长度为的预定义(短)的二进制数,通常用多项式的系数来表示。
在做除法之前,要在信息数据之后先加上个0.CRCa 是基于有限域GF(2) (即除以2的同余)的多项式环。
简单的来说,就是所有系数都为0或1(又叫做二进制)的多项式系数的集合,并且集合对于所有的代数操作都是封闭的。
例如:2会变成0,因为对系数的加法运算都会再取2的模数. 乘法也是类似的:一般来说,其形式为:这里 M(x) 是原始的信息多项式。
K(x)是阶的“钥匙”多项式。
表示了将原始信息后面加上个0。
R(x)是余数多项式,即是CRC“校验和”。
在通信中,发送者在原始的信息数据M后附加上位的R(替换本来附加的0)再发送。
接收者收到M和R后,检查是否能被整除。
如果是,那么接收者认为该信息是正确的。
值得注意的是就是发送者所想要发送的数据。
这个串又叫做codeword.CRCs 经常被叫做“校验和”, 但是这样的说法严格来说并不是准确的,因为技术上来说,校验“和”是通过加法来计算的,而不是CRC这里的除法。
二、错误检测能力CRC 的错误检测能力依赖于关键多项式的阶次以及所使用的特定关键多项式。
误码多项式是接收到的消息码字与正确消息码字的异或结果。
crc16校验原理
不难看出,余式有 256 种可能的值,实际上就是 0~255 以 X16+X12+X5+1 为权得到的 CRC 码,可以通过函数 crc16l 来计算。以 1 为例。
code test[]={0x01}; crc = 0; ptr = test; crc = crc16l(ptr,1);
执行结果 crc = 1021,这就是 1 对应的余式。
图中进行 XOR 运算的位与多项式的表达相对应。 X5 代表 Bit5,X12 代表 Bit12,1 自然是代表 Bit0,X16 比较特别,是指移 位寄存器移出的数据,即图中的 DATA OUT。可以这样理解,与数据位做 XOR 运算的是上次 CRC 值的 Bit15。 根据以上说明,可以依葫芦画瓢的写出以下程序。(程序都是在 keil C 7.10 下调 试的)
typedef unsigned char uchar; typedef unsigned int uint;
code uchar crcbuff [] = { 0x00,0x00,0x00,0x00,0x06,0x0d,0xd2,0xe3};
uint crc;
// CRC 码
void main(void)
图 1,图 2 说明了 CRC 校验中 CRC 值是如何计算出来的,体现的多项式正 是 X16+X12+X5+1。 Serial Data 即是需要校验的数据。从把数据移位开始计 算,将数据位(从最低的数据位开始)逐位移入反向耦合移位寄存器(这个名词 我也不懂,觉得蛮酷的,就这样写了,嘿)。当所有数据位都这样操作后,计算 结束。此时,16 位移位寄存器中的内容就是 CRC 码。
很多资料上都写了查表法来计算,当时是怎么也没想通。其实蛮简单的。假设通 过移位处理了 8 个 bit 的数据,相当于把之前的 CRC 码的高字节(8bit)全部移 出,与一个 byte 的数据做 XOR 运算,根据运算结果来选择一个值(称为余式), 与原来的 CRC 码再做一次 XOR 运算,就可以得到新的 CRC 码。
crc16 校验码计算
crc16校验码计算CRC16校验码是一种广泛应用于数据传输、存储和校验的校验方法。
它通过给定数据计算出一个16位的校验码,以保证数据的完整性和准确性。
下面将详细介绍CRC16校验码的计算方法。
一、CRC16校验码的基本原理CRC16校验码是一种循环冗余校验算法,其基本原理是基于对数据块进行二进制除法,并取余数作为校验码。
具体来说,它将数据块看作一个二进制除数,通过对其执行模2除法运算,以预定的生成多项式为除数,得到余数作为CRC校验码。
二、CRC16校验码的计算步骤1.准备数据:将要进行CRC校验的数据存储在一个字节数组中。
2.添加校验位:在数据的末尾添加若干个0,使得数据的位数能够被生成多项式的位数整除。
这个步骤是为了使得数据能够被生成多项式整除。
3.初始化余数:将一个16位的余数初始化为0xFFFF,这个余数将用于后续的运算。
4.计算余数:将数据作为被除数,将生成多项式作为除数,对数据进行模2除法运算。
在每一步运算中,将余数右移一位,并将被除数的最低位添加到余数的最低位上。
如果余数为0,则说明数据已经被完全校验,此时校验码即为当前的余数;如果余数不为0,则继续进行下一步。
5.反转余数:将上一步得到的余数进行二进制反转,得到最终的CRC校验码。
三、CRC16校验码的生成多项式CRC16校验码通常使用一个16位的生成多项式来计算。
常用的生成多项式有CRC-16-CCITT、CRC-16-IBM等。
这些生成多项式的系数都是预先设定的,可以在相关的技术规范中查找到。
四、CRC16校验码的优点和局限性CRC16校验码具有以下优点:1.简单易用:CRC16校验码的计算方法相对简单,易于实现。
2.高效可靠:CRC16校验码具有较高的检错能力,能够有效地检测出数据传输或存储过程中产生的错误。
3.适用范围广:CRC16校验码广泛应用于各种数据传输、存储和校验的场景中。
然而,CRC16校验码也存在以下局限性:1.对于随机错误,CRC16校验码可能无法完全检测出所有的错误。
crc16 简式
crc16 简式CRC16是Cyclic Redundancy Check 16位校验码的简称。
它是一种常用的校验算法,广泛应用于通信、存储等领域中数据的完整性校验。
本文将介绍CRC16算法的原理、应用和计算方法。
一、CRC16算法原理CRC16算法是基于多项式除法的一种校验算法。
它将待校验的数据看作二进制数,通过与一个预设的生成多项式进行除法运算得到余数,该余数就是CRC16校验码。
生成多项式可以选择不同的值,一般情况下,常用的生成多项式为0x8005和0x1021。
二、CRC16算法应用1.通信中的数据校验在通信中,为了确保数据的传输准确性,常常需要使用CRC16校验码对数据进行校验。
发送方在发送数据之前,先计算数据的CRC16校验码,并将其添加到数据帧的尾部。
接收方在接收到数据之后,同样进行CRC16校验计算,并将计算出的校验码与接收到的校验码进行比较,以判断数据是否传输正确。
2.存储中的数据校验在存储介质中,为了防止数据损坏或篡改,常常需要使用CRC16校验码对数据进行校验。
在向存储介质写入数据时,可以计算数据的CRC16校验码,并将其添加到数据的尾部。
在读取数据时,同样进行CRC16校验计算,并比较计算出的校验码与读取到的校验码,以判断数据的完整性。
三、CRC16算法计算方法CRC16算法的计算方法比较简单,其具体步骤如下:1.预处理a)初始化一个16位的寄存器,初始值为0xFFFF。
b)将生成多项式的最高位移到寄存器的最低位。
2.数据处理a)从高位到低位依次处理每个数据(字节)。
b)计算数据与寄存器的异或值,并将其作为下一轮计算的新输入。
c)将寄存器向右移动一位。
3.结果反转a)反转寄存器的所有位。
4.结果异或a)将寄存器与0xFFFF做异或运算,得到最终的CRC16校验码。
四、总结CRC16是一种常用的校验算法,能够对数据进行快速有效的完整性校验。
它广泛应用于通信、存储等领域中,能够提高数据传输和存储的可靠性。
crc16校验原理
校验原理1、循环校验码(CRC 码):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。
2、生成CRC 码的基本原理:任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。
例如:代码1010111 对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1 对应的代码101111。
3、CRC 码集选择的原则:若设码字长度为N,信息字段为K 位,校验字段为R 位(N=K+R),则对于CRC 码集中的任一码字,存在且仅存在一个R 次多项式g(x),使得V(x)=A(x)g(x)=x R m(x)+r(x);其中: m(x)为K 次信息多项式,r(x)为R-1 次校验多项式,g(x)称为生成多项式:g(x)=g 0+g1x+ g2x2+...+g(R-1)x(R-1)+g R x R发送方通过指定的g(x)产生CRC 码字,接收方则通过该g(x)来验证收到的CRC 码字。
4、CRC 校验码软件生成方法:借助于多项式除法,其余数为校验字段。
例如:信息字段代码为: 1011001;对应m(x)=x6+x4+x3+1假设生成多项式为:g(x)=x4+x3+1;则对应g(x)的代码为: 11001x4m(x)=x10+x8+x7+x4对应的代码记为:10110010000;采用多项式除法: 得余数为: 1010 (即校验字段为:1010)发送方:发出的传输字段为: 1 0 1 1 0 0 1 1 0 10信息字段校验字段接收方:使用相同的生成码进行校验:接收到的字段/生成码(二进制除法)如果能够除尽,则正确,CRC校验源码分析这两天做项目,需要用到CRC校验。
以前没搞过这东东,以为挺简单的。
结果看看别人提供的汇编源程序,居然看不懂。
花了两天时间研究了一下CRC校验,希望我写的这点东西能够帮助和我有同样困惑的朋友节省点时间。
先是在网上下了一堆乱七八遭的资料下来,感觉都是一个模样,全都是从CRC 的数学原理开始,一长串的表达式看的我头晕。
typeb 卡 crc16校验算法
typeb 卡 crc16校验算法
CRC-16 (16位循环冗余校验) 是一种常用的错误检测算法,用于检测数据传输或存储中的错误。
以下是 CRC-16 (TYPEB) 的一个简单实现。
请注意,这是一个基本的实现,实际应用中可能需要调整多项式、初始值、反转输入/输出等。
```python
def crc16_typeb(data: bytes) -> int:
crc = 0xFFFF
for byte in data:
crc ^= byte
for _ in range(8):
if crc & 0x0001:
crc = (crc >> 1) ^ 0xA001
else:
crc >>= 1
return crc
```
这个函数接受一个字节序列(bytes)作为输入,并返回一个16位的CRC 值。
注意,这个函数将反转输入数据的位,因此如果输入数据的位没有被反转,那么在计算CRC之前需要先进行反转。
CRC-16 (TYPEB) 使用的多项式是 0xA001,初始值为 0xFFFF。
CRC16的生成及校验原理
CRC16的⽣成及校验原理计算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,⽽不是真正的减法。
以⼆进制这个计算过程:120 ⼆进制:1111000 、除数9 ⼆进制:1001 、商 14 ⼆进制:1110 余数6 ⼆进制:110从⾼位1111开始,每次进⾏⼀次XOR 的到的值后,去掉最⾼位加⼊下⼀位,每加⼀次进⾏⼀次XOR运算。
1111^1001--------------0110第⼀次XOR后得到0110,去掉最⾼位0,加⼊下⼀位0, 得1100 ,这样最⾼位是1,所以下个商是1 ,⽤^1001【很明显保留的位数与1001 保持⼀致】1100^1001--------------0101第⼆次XOR ,去掉最⾼位,加⼊下⼀位0,得1010 ,这样最⾼位是1,所以下个商是1 ,⽤^10011010^ 1001---------------0011第三次XOR,去掉最⾼位,加⼊下⼀位0,得0110 ,这样最⾼位是1,所以下个商是0 ,⽤^00000110^ 0000-------------0110最后⼀次XOR后得到0110,最⾼位的0可以消掉了,得到余数为110,即6注意,余数不是0110,⽽是110,因为最前⾯那个0已经被XOR后消掉了!可见,除法(XOR)的⽬的是逐步消掉最⾼位的1或0!由于过程是XOR的,所以商是没有意义的,我们不要。
CRC-16的原理和实现
CRC-16的原理和实现CRC的全称为Cyclic Redundancy Check,中⽂名称为循环冗余校验。
它是⼀类重要的线性分组码,编码和解码⽅法简单,检错和纠错能⼒强,在通信领域⼴泛地⽤于实现差错控制。
实际上,除数据通信外,CRC在其它很多领域也是⼤有⽤武之地的。
例如我们读软盘上的⽂件,以及解压⼀个ZIP⽂件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储⽅⾯的应⽤可略见⼀斑。
差错控制理论是在代数理论基础上建⽴起来的。
这⾥我们着眼于介绍CRC的算法与实现,对原理只能捎带说明⼀下。
若需要进⼀步了解线性码、分组码、循环码、纠错编码等⽅⾯的原理,可以阅读有关资料。
利⽤CRC进⾏检错的过程可简单描述为:在发送端根据要传送的k位⼆进制码序列,以⼀定的规则产⽣⼀个校验⽤的r位监督码(CRC码),附在原始信息后边,构成⼀个新的⼆进制码序列数共k+r位,然后发送出去。
在接收端,根据信息码和CRC码之间所遵循的规则进⾏检验,以确定传送中是否出错。
这个规则,在差错控制理论中称为“⽣成多项式”。
1 代数学的⼀般性算法在代数编码理论中,将⼀个码组表⽰为⼀个多项式,码组中各码元当作多项式的系数。
例如 1100101 表⽰为1·x6+1·x5+0·x4+0·x3+1·x2+0·x+1,即 x6+x5+x2+1。
设编码前的原始信息多项式为P(x),P(x)的最⾼幂次加1等于k;⽣成多项式为G(x),G(x)的最⾼幂次等于r;CRC多项式为R(x);编码后的带CRC的信息多项式为T(x)。
发送⽅编码⽅法:将P(x)乘以xr(即对应的⼆进制码序列左移r位),再除以G(x),所得余式即为R(x)。
⽤公式表⽰为T(x)=x r P(x)+R(x)接收⽅解码⽅法:将T(x)除以G(x),如果余数为0,则说明传输中⽆错误发⽣,否则说明传输有误。
举例来说,设信息码为1100,⽣成多项式为1011,即P(x)=x3+x2,G(x)=x3+x+1,计算CRC的过程为x r P(x) x3(x3+x2) x6+x5 x-------- = ---------- = -------- = (x3+x2+x) + --------G(x) x3+x+1 x3+x+1 x3+x+1即 R(x)=x。
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校验原理与算法分析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]。
crc16校验查表法原理
crc16校验查表法原理CRC(Cyclic Redundancy Check)是一种常用的数据校验方法,广泛应用于数据通信和存储中,以确保数据的完整性和准确性。
CRC校验可以通过查表法来实现,本文将介绍CRC16校验的查表法原理。
在CRC校验中,发送方和接收方通过一系列的计算操作来生成和校验校验码。
其中,CRC16是一种16位的循环冗余校验码,可以检测出多达2个比特的错误。
CRC16校验的查表法是一种基于查表的快速计算方法,通过预先构建一个256个元素的查表来加速校验码的计算。
我们需要准备一个256个元素的查表,每个元素都是一个16位的值。
这个查表可以通过生成多项式来计算得到,CRC16通常使用的是0x8005或0x1021这两个生成多项式。
通过对这两个多项式进行反转和左移操作,我们可以得到一个256个元素的查表。
接下来,我们需要将待校验的数据按照字节进行拆分,并将每个字节和当前的校验码进行异或运算。
异或运算是一种位运算,其运算规则是两个数对应位相同则结果为0,不同则结果为1。
通过不断地进行异或运算,将每个字节和当前的校验码进行异或,最终得到一个16位的校验码。
然后,我们可以通过查表的方式来加速校验码的计算。
对于每个字节,我们可以将它作为查表的索引,查表的结果就是一个16位的值。
然后,我们将这个值和当前的校验码进行异或运算,得到一个新的校验码。
通过不断地查表和异或运算,最终得到的校验码就是CRC16校验码。
CRC16校验的查表法相比于其他计算方法具有高效和简洁的特点。
通过预先构建查表,可以大大减少计算的时间和复杂度。
同时,查表法还可以方便地用于硬件电路的设计和实现,提高系统的性能和可扩展性。
需要注意的是,CRC16校验的查表法并不是唯一的实现方式,还可以使用其他方法来计算校验码。
而且,在实际应用中,不同的通信协议和设备可能会采用不同的CRC算法和生成多项式。
CRC16校验的查表法是一种基于查表的快速计算方法,通过预先构建一个256个元素的查表,可以加速CRC16校验码的计算。
16位CRC校验码计算程序
16位CRC校验码计算程序/*************************************************************** 16位CRC计算方法1(预置1个16位的寄存器为十六进制FFFF(即全为1);称此寄存器为CRC寄存器; 2(把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器;3(把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位; 4(如果移出位为0:重复第3步(再次右移一位);如果移出位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或; 5(重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理; 6(重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;7(将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC;*****************************************************************/ /******************************************************************* *********名称: UART_CRC16_Work()说明: CRC16校验程序参数: *CRC_Buf:数据地址CRC_Leni:数据长度返回: CRC_Sumx:校验值******************************************************************** *********/unsigned int UART_CRC16_Work(unsigned char *CRC_Buf,unsigned char CRC_Leni) {unsigned char i,j;unsigned int CRC_Sumx;CRC_Sumx=0xFFFF;for(i=0;i<CRC_Leni;i++){CRC_Sumx^=*(CRC_Buf+i);//异或for(j=0;j<8;j++){if(CRC_Sumx & 0x01){CRC_Sumx>>=1;CRC_Sumx^=0xA001;}else{CRC_Sumx>>=1;}}}return (CRC_Sumx);}Crc_Length = 9;for(k=0;k<9;k++)Crc_Buf[k]=ReceiveBuf[k];Crc_Value=Crc16(Crc_Buf,Crc_Length);Crc_ReceiveValue=ReceiveBuf[9];Crc_ReceiveValue=(Crc_ReceiveValue<<8)+ReceiveBuf[10];if(Crc_Value==Crc_ReceiveValue) unsigned int Crc16(unsigned char *pBuf, unsigned char num) {unsigned char i,j;unsigned int wCrc = 0xFFFF;for(i=0; i<num; i++){wCrc ^= (uint)(pBuf[i]);for(j=0; j<8; j++){if(wCrc & 1){wCrc >>= 1; wCrc ^= 0xA001; }elsewCrc >>= 1; }}return wCrc; }。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
最详细易懂的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信息字段校验字段接收方:使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则信息正确。
4、CRC-16校验码计算方法:常用查表法和计算法。
计算方法一般都是:(1)、预置1个16位的寄存器为十六进制FFFF (即全为1),称此寄存器为CRC寄存器;(2)、把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器,高八位数据不变;(3)、把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位;(4)、如果移出位为0:重复第3步(再次右移一位);如果移出位为1,CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;(5)、重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;(6)、重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;(7)、将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换;(8)、最后得到的CRC寄存器内容即为:CRC码。
以上计算步骤中的多项式A001是8005按位颠倒后的结果。
查表法是将移位异或的计算结果做成了一个表,就是将0~256放入一个长度为16位的寄存器中的低八位,高八位填充0,然后将该寄存器与多项式0XA001按照上述3、4步骤,直到八位全部移出,最后寄存器中的值就是表格中的数据,高八位、低八位分别单独一个表。
5、提供两个经典的程序示例(皆验证通过)(1) C查表法版本:特点:速度快,语句少,但表格占用一定的程序空间。
*pucFrame 为待校验数据首地址,usLen为待校验数据长度。
返回值为校验结果。
USHORT usMBCRC16( UCHAR * pucFrame, USHORT usLen ){UCHAR ucCRCHi = 0xFF;UCHAR ucCRCLo = 0xFF;int iIndex;while( usLen-- ){iIndex = ucCRCLo ^ *( pucFrame++ );ucCRCLo = ( UCHAR )( ucCRCHi ^ aucCRCHi[iIndex] );ucCRCHi = aucCRCLo[iIndex];}return ( USHORT )( ucCRCHi << 8 | ucCRCLo );}static const UCHAR aucCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};static const UCHAR aucCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,0x41, 0x81, 0x80, 0x40};(2)汇编计算法版本:特点:需要计算n*8次(n为信息字节数),运行速度慢,占用程序时间,但节省空间资源。