C语言实现CRC16校验 详解
CRC16校验算法实现
CRC16校验算法实现CRC16算法基于二进制位的异或和移位操作,它将数据按照二进制形式进行处理。
CRC16算法采用了多项式除法的思想,通过对数据进行除法运算并计算余数,生成一定长度的冗余校验码,用于检测数据是否出现错误。
1.首先,需要选择一个CRC-16生成多项式。
常用的生成多项式有多个,常见的有CRC-CCITT(0x1021)、CRC-IBM(0x8005)等。
生成多项式决定了CRC-16算法的性能和效果。
2.将待校验的数据按照二进制形式进行处理。
如果数据是字符串,则需要将字符串转换为二进制形式。
可以使用ASCII码表将每个字符转换为对应的二进制形式。
3.初始化CRC寄存器为一个指定的值(通常为0xFFFF)。
4.对数据进行逐位处理。
从高位到低位,逐位将数据与CRC寄存器进行异或操作。
如果结果为1,则进行一次右移操作。
如果结果为0,则直接进行一次右移操作。
重复该操作直到处理完所有的位。
5.当所有的位处理完成后,将CRC寄存器的当前值作为校验码。
下面是一个简单的CRC16算法实现的示例代码(基于CRC-CCITT生成多项式,0x1021):```pythondef crc16(data):crc = 0xFFFF # 初始化CRC寄存器为0xFFFF#CRC-CCITT生成多项式polynomial = 0x1021for byte in data:crc ^= (byte << 8) # 将数据与CRC寄存器进行异或操作for _ in range(8):if crc & 0x8000:crc = (crc << 1) ^ polynomialelse:crc <<= 1return crc & 0xFFFF#示例用法data = "hello world"data_bytes = [ord(c) for c in data] # 将字符串转换为对应的ASCII码列表checksum = crc16(data_bytes)print("CRC16校验码:", checksum)```在上述示例代码中,crc16函数接收一个数据参数,该数据参数可以是字符串、字节数组等形式。
MODBUS-CRC16的原理及C语言的实现
//异或多项式
}
*ptr++;
} V = ((CRC16 & 0x00FF) << 8) | ((CRC16 & 0xFF00) >> 8) ;//高低字节转换
return V;
}
最后给大家提供若干数据做参考(经过程序验证):
例如:“01”的校验码为“7E 80” “02”的校验码为“3E 81”
“01 03”的校验码为“40 21” “01 05”的校验码为“C0 23”
MODBUS 是 MODICON 公司最先倡导的一种通讯协议,经过大多数公司 的实际应用,逐 渐被认可,成为一种标准的通讯协议。 常用的 MODBUS 通讯协议有两种,一种是 MODBUS ASCII,一种是 MODBUS RTU。下面 以使用比较广泛的 MODBUS RTU 通讯协议作介绍。 Modbus RTU 通讯采用主-从方式。主设备与一个或多个从设备进行通讯。比较典型的主设备 是 PLC、PC、DCS(集散控制系统)或者 RTU(远程终端单元)。Modbus RTU 的从设备一般是 现场设备。当 Modbus RTU 主设备想要从一台从设备得到数据的时候,主设备发送一条包含 该从设备站地址、所需要的数据以及一个用于检测错误的 CRC 校验码。网络上所有其它设 备都可以接收到这条信息,但是只有地址被指定的从设备才会作出反应。 Modbus RTU 协议桢定义可概括如下:
的高、低字节进行交换。(由于发送时低字节在前) • 完成步骤 1~7 最后得到的 CRC 寄存器内容即为:CRC 校验码
◊ 计算法的 C 语言程序实现如下:
unsigned short ModBusCRC (unsigned char *ptr,unsigned char size) {
C语言实现CRC16校验
C语言实现CRC16校验1.定义CRC16多项式和初始化值:CRC16校验使用的多项式可以是多种不同的值,常用的是0x8005、此外,需要定义一个初始值,初值可为0xFFFF。
```c#define CRC16_POLY 0x8005#define CRC16_INIT 0xFFFF```2.实现CRC16计算函数:根据CRC16校验算法,需要对输入数据的每个字节进行计算,不断更新CRC16值,最终得到校验结果。
```cunsigned short crc16(unsigned char *data, int length)unsigned short crc = CRC16_INIT;int i, j;for (i = 0; i < length; i++)crc ^= (unsigned short) data[i] << 8;for (j = 0; j < 8; j++)if (crc & 0x8000)crc = (crc << 1) ^ CRC16_POLY;} elsecrc = crc << 1;}}}return crc;```3.调用CRC16计算函数:将需要校验的数据传递给CRC16计算函数,并得到校验结果。
```cint mai//示例数据unsigned char data[] = {0x01, 0x02, 0x03, 0x04, 0x05};int length = sizeof(data) / sizeof(data[0]);//计算CRC16校验值unsigned short crc = crc16(data, length);//打印结果printf("CRC16校验值为:%04X\n", crc);return 0;```以上就是一个简单的C语言实现CRC16校验的代码。
请注意,这只是一个实现的简化版本,对于更复杂的数据校验场景,可能需要更多的处理。
最详细易懂的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 citt false c语言
crc16 citt false c语言CRC16是一种常用的循环冗余校验算法,它可以用于检测和纠正数据传输中的错误。
在C语言中,我们可以使用CRC16算法来计算校验和,并判断数据的完整性。
CRC16算法采用的是多项式除法,具体的计算过程如下:1. 首先,我们需要定义一个16位的CRC寄存器,初始值为0xFFFF。
2. 然后,我们将待校验的数据按位进行处理,从高位到低位逐个与CRC寄存器进行异或运算。
3. 接着,我们将CRC寄存器的值右移一位,如果最低位是1,则将寄存器与一个预设的固定值(0xA001)进行异或运算。
4. 重复上述步骤,直到所有的数据位都被处理完毕。
5. 最后,CRC寄存器的值就是计算得到的校验和。
在C语言中,我们可以通过编写一个函数来实现CRC16的计算。
下面是一个示例代码:```c#include <stdio.h>#include <stdint.h>uint16_t crc16(uint8_t *data, int length){uint16_t crc = 0xFFFF;for (int i = 0; i < length; i++) {crc ^= (uint16_t)data[i];for (int j = 0; j < 8; j++) {if (crc & 0x0001) {crc = (crc >> 1) ^ 0xA001;} else {crc >>= 1;}}}return crc;}int main(){uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x05}; int length = sizeof(data) / sizeof(data[0]);uint16_t checksum = crc16(data, length);printf("CRC16 checksum: 0x%04X\n", checksum);return 0;}```在上述代码中,我们首先定义了一个crc16函数,它接受一个指向数据数组的指针和数据的长度作为输入,返回一个16位的校验和。
crc16 citt false c语言
CRC16(循环冗余校验码)是一种通过对数据进行多项式除法来生成校验码的方法。
它通常用于数据传输过程中的错误检测和校验,以确保数据的完整性和准确性。
CITT False CRC16 是其中一种常见的CRC16 校验码算法,它采用了 CITT 标准的多项式生成 16 位的校验码。
在 C 语言中,我们可以通过编写相应的函数来实现 CITT False CRC16 校验码的生成和验证。
本文将对 CITT False CRC16 算法进行介绍,并提供一个基于 C 语言的实现示例。
一、CITT False CRC16 算法介绍CITT False CRC16 算法采用了多项式 0x1021(x^16 + x^12 + x^5 + 1)来生成 16 位的校验码。
该算法将数据与 0x8005 进行按位异或运算,然后将结果与 0x8408 进行按位取反操作。
最终得到的余数就是 16 位的 CRC16 校验码。
该算法在数据通信领域得到了广泛的应用,因其计算速度快、效果稳定而备受青睐。
二、CITT False CRC16 算法实现在 C 语言中实现 CITT False CRC16 算法并不复杂,我们可以编写一个函数来完成 CRC16 校验码的生成和验证。
以下是一个基于 C 语言的示例代码:```c#include <stdio.h>#include <stdint.h>// 定义 CITT False CRC16 多项式#define POLY 0x1021// 计算 CRC16 校验码uint16_t crc16(uint8_t *data, uint32_t len) {uint16_t crc = 0;for (uint32_t i = 0; i < len; i++) {crc = crc ^ (data[i] << 8);for (int j = 0; j < 8; j++) {if (crc 0x8000) {crc = (crc << 1) ^ POLY;} else {crc = crc << 1;}}}return crc;}int m本人n() {// 测试数据uint8_t test_data[] = {0x01, 0x02, 0x03, 0x04, 0x05};uint32_t data_len = sizeof(test_data) / sizeof(test_data[0]);// 计算 CRC16 校验码uint16_t crc_code = crc16(test_data, data_len);printf("CRC16 校验码为:04X\n", crc_code);return 0;}```以上示例代码中,我们定义了一个 crc16 函数来计算 CITT False CRC16 校验码,同时编写了一个 m本人n 函数来调用 crc16 函数并打印结果。
c#CRC-16MODBUS校验计算方法及异或校验算法
c#CRC-16MODBUS校验计算⽅法及异或校验算法⼗年河东,⼗年河西,莫欺少年穷学⽆⽌境,精益求精只要是代码,如下:///<summary>///低字节在前///</summary>///<param name="pDataBytes"></param>///<returns></returns>static byte[] CRC16LH(byte[] pDataBytes){ushort crc = 0xffff;ushort polynom = 0xA001;for (int i = 0; i < pDataBytes.Length; i++){crc ^= pDataBytes[i];for (int j = 0; j < 8; j++){if ((crc & 0x01) == 0x01){crc >>= 1;crc ^= polynom;}else{crc >>= 1;}}}byte[] result = BitConverter.GetBytes(crc);return result;}///<summary>///⾼字节在前///</summary>///<param name="pDataBytes"></param>///<returns></returns>static byte[] CRC16HL(byte[] pDataBytes){ushort crc = 0xffff;ushort polynom = 0xA001;for (int i = 0; i < pDataBytes.Length; i++){crc ^= pDataBytes[i];for (int j = 0; j < 8; j++){if ((crc & 0x01) == 0x01){crc >>= 1;crc ^= polynom;}else{crc >>= 1;}}}byte[] result = BitConverter.GetBytes(crc).Reverse().ToArray() ;return result;}还有两个供⼤家验证的byte数组,如下:List<byte> llsst = new List<byte>() {0x79,0x79,0x01,0x01,0x00,0x1C,0x01,0x90,0x00,0x01,0x28,0xC3,0xC1,0x00,0xE9,0x9E,0x00,0x00,0x00,0x00,0x52,0x85,0x00,0x01,0x11,0x8E,0x15,0x02,0xD0,0x41,0x3E,0x02,0x0B var CrcLs3t22 = CRC16LH(llsst.ToArray());var CrcLs2t25 = CRC16HL(llsst.ToArray());低字节在前的结果为:83 9A⾼字节在前的结果为:9A 83异或校验算法:public static byte XOR_Check(List<byte> pbuf){int res = 0;int len = pbuf.Count;for (int i = 0; i < len; i++){res ^= pbuf[i];}return BitConverter.GetBytes(res)[0];}@天才卧龙的博客。
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位)进行异或运算,得到余数。
CRC16C语言实现
CRC16C语⾔实现最近看到⼀个实现crc16的⼩程序,刚开始,不明觉厉,于是花了⼀个周末去know how。
CRC(Cyclic Redundancy Check)循环冗余校验是常⽤的数据校验⽅法。
先说说什么是数据校验。
数据在传输过程(⽐如通过⽹线在两台计算机间传⽂件)中,由于传输信道的原因,可能会有误码现象(⽐如说发送数字5但接收⽅收到的却是6),如何发现误码呢?⽅法是发送额外的数据让接收⽅校验是否正确,这就是数据校验。
最容易想到的校验⽅法是和校验,就是将传送的数据(按字节⽅式)加起来计算出数据的总和,并将总和传给接收⽅,接收⽅收到数据后也计算总和,并与收到的总和⽐较看是否相同。
如果传输中出现误码,那么总和⼀般不会相同,从⽽知道有误码产⽣,可以让发送⽅再发送⼀遍数据。
CRC校验也是添加额外数据做为校验码,这就是CRC校验码,那么CRC校验码是如何得到的呢? ⾮常简单,CRC校验码就是将数据除以某个固定的数(⽐如ANSI-CRC16中,这个数是0x18005),所得到的余数就是CRC校验码。
那这⾥就有⼀个问题,我们传送的是⼀串字节数据,⽽不是⼀个数据,怎么将⼀串数字变成⼀个数据呢?这也很简单,⽐如说2个字节B1,B2,那么对应的数就是(B1<<8)+B2;如果是3个字节B1,B2,B3,那么对应的数就是((B1<<16)+(B2<<8)+B3),⽐如数字是0x01,0x02,0x03,那么对应的数字就是0x10203;依次类推。
如果字节数很多,那么对应的数就⾮常⾮常⼤,不过幸好CRC只需要得到余数,⽽不需要得到商。
从上⾯介绍的原理我们可以⼤致知道CRC校验的准确率,在CRC8中出现了误码但没发现的概率是1/256,CRC16的概率是1/65536,⽽CRC32的概率则是1/2^32,那已经是⾮常⼩了,所以⼀般在数据不多的情况下⽤CRC16校验就可以了,⽽在整个⽂件的校验中⼀般⽤CRC32校验。
C语言实现CRC16校验
CRC校验C语言实现,转载请注明出处,谢谢CRC(Cyclic Redundancy Check)校验应用较为广泛,以前为了处理简单,在程序中大多数采用LRC(Longitudinal Redundancy Check)校验,LRC校验很好理解,编程实现简单。
用了一天时间研究了CRC的C语言实现,理解和掌握了基本原理和C语言编程。
结合自己的理解简单写下来。
1、CRC简介CRC检验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个检验码r位(就是CRC码),附在信息后面,构成一个新的二进制码序列数共(k+r)位,最后发送出去。
接收端根据同样的规则校验,以确定传送中是否出错。
接收端有两种处理方式:1、计算k位序列的CRC码,与接收到的CRC比较,一致则接收正确。
2、计算整个k+r位的CRC码,若为0,则接收正确。
CRC码有多种检验位数,8位、16位、32位等,原理相同。
16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(即乘以2的16次方后),除以一个多项式,最后所得到的余数就是CRC码。
求CRC码所采用的是模2运算法则,即多项式除法中采用不带借位的减法运算,运算等同于异或运算。
这一点要仔细理解,是编程的基础。
CRC-16: (美国二进制同步系统中采用) G(X) = X16 + X15 + X2 + 1CRC-CCITT: (由欧洲CCITT推荐) G(X) = X16 + X12 + X5 + 1CRC-32: G(X) = X32 + X26 + X23 + X22 + X16 +X12 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + 12、按位计算CRC采用CRC-CCITT多项式,多项式为0x11021,C语言编程时,参与计算为0x1021,这个地方得深入思考才能体会其中的奥妙,分享一下我的思路:当按位计算CRC时,例如计算二进制序列为1001 1010 1010 1111时,将二进制序列数左移16位,即为1001 1010 1010 1111 (0000 0000 0000 0000),实际上该二进制序列可拆分为1000 0000 0000 0000 (0000 0000 0000 0000) + 000 0000 0000 0000 (0000 0000 0000 0000) + 00 0000 0000 0000 (0000 0000 0000 0000) + 1 0000 0000 0000 (0000 0000 0000 0000) + ……现在开始分析运算:<1>对第一个二进制分序列求余数,竖式除法即为0x10000 ^ 0x11021运算,后面的0位保留;<2>接着对第二个二进制分序列求余数,将第一步运算的余数*2后再和第二个二进制分序列一起对0x11021求余,这一步理解应该没什么问题。
crc16 citt false c语言 -回复
crc16 citt false c语言-回复"crc16 citt false c语言"主题下的文章- 在C语言中实现CRC16算法引言:在计算机科学中,循环冗余校验(CRC)是一种常用的差错检测技术。
CRC16是其中一种常用的CRC算法之一,它使用16位的二进制整数作为检验码。
本文将介绍如何在C语言中实现CRC16算法,并给出一个使用CRC16算法的示例。
第一步:理解CRC16算法CRC16是通过对时间序列的数据进行多项式计算得到的。
这个多项式是一个特定的16位二进制整数。
CRC算法涉及到数据的移位与异或操作,并且需要预先定义一个固定的生成多项式。
每个输入都会在进行计算之前补上特定的补位,以确保生成的余数具有相应的长度。
第二步:选择一个合适的生成多项式在实现CRC16算法之前,我们需要选择一个合适的生成多项式。
这个生成多项式决定了CRC算法的性能。
一个常用的CRC16生成多项式是0x8005(二进制形式为1000000000000101)。
选择好生成多项式后,我们将继续实现CRC16算法。
第三步:编写CRC16算法的函数在C语言中,实现CRC16算法非常简单。
我们可以编写一个函数来计算CRC16校验码。
#include <stdio.h>unsigned short crc16(unsigned char *data, unsigned int length) { unsigned int i;unsigned short crc = 0xFFFF; 初始值为0xFFFFwhile (length) {crc ^= *data++; 将当前数据字节异或到CRC中for (i = 0; i < 8; ++i) {if (crc & 1) {crc >>= 1;crc ^= 0xA001; 生成多项式0x8005的二进制补码} else {crc >>= 1;}}}return crc;}int main() {unsigned char data[] = "Hello, CRC16!";unsigned short checksum = crc16(data, sizeof(data) - 1); 减去终止符'\0'printf("CRC16 checksum: 0x04X\n", checksum);return 0;}(以上代码已经考虑了`crc16 citt false c语言`)第四步:运行并验证CRC16算法当我们编写完成CRC16算法的函数后,我们可以运行程序并测试其效果。
【转】crc16几种标准校验算法及c语言代码
【转】crc16⼏种标准校验算法及c语⾔代码⼀、CRC16校验码的使⽤ 现选择最常⽤的CRC-16校验,说明它的使⽤⽅法。
根据Modbus协议,常规485通讯的信息发送形式如下: 地址功能码数据信息校验码 1byte 1byte nbyte 2byte CRC校验是前⾯⼏段数据内容的校验值,为⼀个16位数据,发送时,低8位在前,⾼8为最后。
例如:信息字段代码为: 1011001,校验字段为:1010。
发送⽅:发出的传输字段为: 1 0 1 1 0 0 1 1 0 10 信息字段校验字段 接收⽅:使⽤相同的计算⽅法计算出信息字段的校验码,对⽐接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则信息正确。
⼆、CRC16校验码计算⽅法 常⽤查表法和计算法。
计算⽅法⼀般都是: (1)、预置1个16位的寄存器值0xFFFF,称此寄存器为CRC寄存器; (2)、把第⼀个8位⼆进制数据(既通讯信息帧的第⼀个字节)与16位的CRC寄存器的低 8位相异或,把结果放于CRC寄存器,⾼⼋位数据不变; (3)、把CRC寄存器的内容右移⼀位(朝⾼位)⽤0填补最⾼位,并检查右移后的移出位; (4)、如果移出位为0:重复第3步(再次右移⼀位);如果移出位为1,CRC寄存器与⼀多 项式(A001)进⾏异或; (5)、重复步骤3和4,直到右移8次,这样整个8位数据全部进⾏了处理; (6)、重复步骤2到步骤5,进⾏通讯信息帧下⼀个字节的处理; (7)、将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的⾼、低 字节进⾏交换; (8)、最后得到的CRC寄存器内容即为:CRC码。
以上计算步骤中的多项式A001是8005按位颠倒后的结果。
查表法是将移位异或的计算结果做成了⼀个表,就是将0~256放⼊⼀个长度为16位的寄存器中的低⼋位,⾼⼋位填充0,然后将该寄存器与多项式0XA001按照上述3、4步骤,直到⼋位全部移出,最后寄存器中的值就是表格中的数据,⾼⼋位、低⼋位分别单独⼀个表。
C语言实现的CRC16CCITT-FALSE校验码函数
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
CRC16 c语言
下面我们以CRC-16为例来说明任意长度数据流的CRC校验码生成过程。
我们采用将数据流分成若干个8bit 字符,并由低字节到高字节传送的并行方法来求CRC校验码。
具体计算过程为:用一个16bit的寄存器来存放CRC校验值,且设定其初值为0x0000;将数据流的第一个8bit与16bit的CRC寄存器的高字节相异或,并将结果存入CRC寄存器高字节;CRC寄存器左移一位,最低1bit补零,同时检查移出的最高1bit,若移出的最高1bit为0,则继续按上述过程左移,若最高1bit为1,则将CRC寄存器中的值与生成多项式码相异或,结果存入CRC寄存器值;继续左移并重复上述处理方法,直到将8bit数据处理完为止,则此时CRC寄存器中的值就是第一个8bit数据对应的CRC校验码;然后将此时CRC寄存器的值作为初值,用同样的处理方法重复上述步骤来处理下一个8bit数据流,直到将所有的8bit字符都处理完后,此刻CRC寄存器中的值即为整个数据流对应的CRC校验码。
下面示出了其计算过程的流程图:在用C语言编写CRC校验码的实现程序时我们应该注意,生成多项式对应的十六进制数为0x18005,由于CRC寄存器左移过程中,移出的最高位为1时与相异或,所以与16bit的CRC寄存器对应的生成多项式的十六进制数可用0x8005表示。
下面给出并行处理8bit数据流的C源程序:unsigned short crc_dsp(unsigned short reg, unsigned char data_crc)//reg为crc寄存器,data_crc为将要处理的8bit数据流{unsigned short msb; //crc寄存器将移出的最高1bitunsigned short data;unsigned short gx = 0x8005, i = 0; //i为左移次数,gx为生成多项式data = (unsigned short)data_crc;data = data << 8;reg = reg ^ data;do{msb = reg & 0x8000;reg = reg << 1;if(msb == 0x8000){reg = reg ^ gx;}i++;}while(i < 8);return (reg);}以上为处理每一个8bit数据流的子程序,在计算整个数据流的CRC校验码时,我们只需将CRC_reg的初值置为0x0000,求第一个8bit的CRC值,之后,即可将上次求得的CRC值和本次将要处理的8bit数据作为函数实参传递给上述子程序的形参进行处理即可,最终返回的reg值便是我们所想得到的整个数据流的CRC校验值。
CRC16校验C语言程序源码-(附完整的可执行的C语言代码)
CRC16校验C语⾔程序源码-(附完整的可执⾏的C语⾔代码)CRC16校验C语⾔程序源码-(附完整的可执⾏的C语⾔代码)CRC16校验C语⾔程序源码(附完整的可执⾏的C语⾔代码)//CRC16校验在通讯中应⽤⼴泛,这⾥不对其理论进⾏讨论,只对常见的2种//实现⽅法进⾏测试。
⽅法⼀:查表法(256长度的校验表)速度快,准确,但是对于单⽚机设备存储占⽤⼤,且校验表长度⼤,输⼊时容易出现错误。
// ---------------- POPULAR POLYNOMIALS ----------------// CCITT: x^16 + x^12 + x^5 + x^0 (0x1021) // CRC-16: x^16 + x^15 + x^2 + x^0 (0x8005) #define CRC_16_POLYNOMIALS 0x8005const BYTE chCRCHTalbe[] = // CRC ⾼位字节值表{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};const 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, 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};WORD CRC16_1(BYTE* pchMsg, WORD wDataLen){BYTE chCRCHi = 0xFF; // ⾼CRC字节初始化BYTE chCRCLo = 0xFF; // 低CRC字节初始化WORD wIndex; // CRC循环中的索引while (wDataLen--){// 计算CRCwIndex = chCRCLo ^ *pchMsg++ ;chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];chCRCHi = chCRCLTalbe[wIndex] ;}return ((chCRCHi << 8) | chCRCLo) ;}⽅法⼀:列表法(简单表)const WORD wCRCTalbeAbs[] ={0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,};WORD CRC16_2(BYTE* pchMsg, WORD wDataLen){WORD wCRC = 0xFFFF;WORD i;BYTE chChar;for (i = 0; i < wDataLen; i++){chChar = *pchMsg++;wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4); wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4); }return wCRC;}⽅法⼆:定义法根据CRC16/MODBUS原理直接计算,算法简单但对单⽚机计算压⼒⼤。
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 码。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
;tset = rtp* rahc dengisnu ;i rahc dengisnu ;0 = crc tni dengisnu { ) diov (nia m diov ;61 = nel rahc dengisnu ;}ffx0,eex0,ddx0,ccx0,bbx0,aax0,99x0,88x0,77x0,66x0,55x0,44x0,33x0,22x0,11x0,00x0{= ]61[tset rahc dengisnu 。现实言 语 C 的后化简出给面下。白明要家大点这�的除被以可是也位一后最的列序到算直一�以所�的算运与参后位 61 移 左是列序制进二为因�点一调强还后最。或异即�算运法加的位进带不是也和之数余。了道知就下一算手动己自个这 。1201x0 是而,00001x0 为非并数余 �除 12011x0 被以可也 00001x0 以所 �算运法减的位借带不用采中法除式项多为因 �是的同不法除通普和点一有。余求数除除去再就�数除被当以可大较比果如�后 2 以乘数余的时位一上算计�法除 的单简作看它把�方比个打�说是就也�解理好很个这。数余得所算计位本上加再后然,算运余求作 12011x0 对可后 2 * 数余位一上�时位本算计�0 = ! )0008x0 & 数余的算计位一上 (即�时 1 为位 tib51 第数余的算计位一上中列序制 进二当�知可析分。化简的步一进作序程对们我�间空存内约节了为。解理易容很�来而析分算运据根序程的面上 } ;)crc," x%x0"(ftnirp ;pmet = crc } ;++rtp }
} ;)12011x0 ^ 00001x0( ^ pmet = p met { )0 =! )i & rtp*((fi } ;12011x0 ^ pmet = p met {
3
,4a44x0 ,7c47x0 ,6e46x0 ,1041x0 ,0240x0 ,3443x0 ,2642x0 ,ed3ex0 ,ff3fx0 ,c93cx0 ,db3dx0 ,a53ax0 ,b73bx0 ,8138x0 ,9339x0 ,6d26x0 ,7f27x0 ,4924x0 ,5b25x0 ,2522x0 ,3723 x0 ,0120x0 ,1321x0 ,fe1fx0 ,ec1ex0 ,da1dx0 ,c81cx0 ,b61bx0 ,a41ax0 ,9219x0 ,8018x0 ,7e07x0 ,6c06x0 ,5a05x0 ,4804x0 ,3603x0 ,2402x0 ,1201x0 ,0000x0 �下如表的成生。替代�)crc," ,x%x0"(ftnirp 用接直可�谓所无果如�齐整较比表的成生使 制控了为句语 ftnirp 个几的面后 。了以可就的他其成换 1201x0 中序程把需只 �式项多 12011x0 的用使是不你果如 )0 =! )i & j((fi } } } ;1 << crc = crc { esle } ;1201x0 ^ crc = crc ;1 << crc = crc { )0 = ! )0008x0 & crc((fi { )1 >> i = i ;0 =! i ;08x0 = i(rof ;0 = crc { )++j ;652 < j ;0 = j(rof ;)crc," ,x%"(ftnirp } ;)"0"(ftnirp { )0001x0 < crc(fi esle } ;)"00"(ftnirp { )001x0 < crc(fi esle } ;)"000"(ftnirp { )01x0 < crc(fi ;)"x0"c = crc { )0 =! )i & rtp*((fi } ;1 << crc = crc { esle } ;1201x0 ^ crc = crc ;1 << crc = crc { )0 = ! )0008x0 & crc((fi { )1 >> i = i ;0 =! i ;08x0 = i(rof { ) --nel (elihw
;1201x0 ^ crc = crc
;j tni dengisnu ;i rahc dengisnu ;0 = crc tni dengisnu { ) diov (niam diov
。序程算计的 12011x0 是式项多了出给序程的面下�的来出算计是然当�呢的到得么怎是表 。度速算计高提大大可法表查用采�中表个一在放�来出算计部全 CRC 的数列序制进二位 8 把们我�度速算计高提了 为。加相数余的得算计和数余为作后方次八的 2 以乘值的位八低�余求加相值位本与接直值的位八高�式形的位八低 和位八高成拆 CRC 的中算计将�程编化简了为。撒解理好该应个这�算运的步一下与参方次八的 2 以乘要 CRC 数 余的步一上中算计是的同不一唯�样一骤步的面上和时算计析分�)0 0 0 0(f900x0 + )0 0 0 0(00a9x0 为分拆可列序制 进二该上际实�)0 0 0 0(f9a9x0 为即�位 61 移左数列序制进二将�时 f9a9x0 即�时 1111 0101 0101 1001 为列序 制进二算计如例�时 CRC 算计节字当�子例的面前举是还。了 esac 小是就个这解理�识知的算计位按面上了有 CRC 算计节字按、3 。法方 的 CRC 算计速快表查节字按种一绍介再面下�算计去位一位一要但�少存内占所�单简较比码代 CRC 算计位按 。。。。。吗易容字 多么这码我�下看再头从是还�了不解理还是要。的解理易容较比是还�哈一味品细细�序程的前之化简没下一比对 以可�难困有还解理序程段此对果如�析分细详的面上我过通。释解的细详得冇但�见常为较上网序程段这面上 } ;)crc," x%x0"(ftnirp } ;++rtp }
4
;8H_crc rahc dengisnu ;0 = crc tni dengisnu { )diov(nia m diov ;}0fe1x0 ,1de0x0 ,2be3x0 ,39e2x0 ,47e5x0 ,55e4x0 ,63e7x0 ,71e6x0 ,8ff9x0 ,9df8x0 ,abfbx0 ,b9fax0 ,c7fdx0 ,d5fcx0 ,e3ffx0 ,f1fex0 ,1cc0x0 ,0ec1x0 ,38c2x0 ,2ac3x0 ,54c4x0 ,46c5x0 ,70c6x0 ,62c7x0 ,9cd8x0 ,8ed9x0 ,b8dax0 ,aadbx0 ,d4dcx0 ,c6ddx0 ,f0dex0 ,e2dfx0 ,29a3x0 ,3ba2x0 ,0da1x0 ,1fa0x0 ,61a7x0 ,73a6x0 ,45a5x0 ,57a4x0 ,a9bbx0 ,bbbax0 ,8db9x0 ,9fb8x0 ,e1bfx0 ,f3bex0 ,c5bdx0 ,d7bcx0 ,3a82x0 ,2883x0 ,1e80x0 ,0c81x0 ,7286x0 ,6087x0 ,5684x0 ,4485x0 ,ba9ax0 ,a89bx0 ,9e98x0 ,8c99x0 ,f29ex0 ,e09fx0 ,d69cx0 ,c49dx0 ,4365x0 ,5164x0 ,6767x0 ,7566x0 ,0b61x0 ,1960x0 ,2f63x0 ,3d62x0 ,c37dx0 ,d17cx0 ,e77fx0 ,f57ex0 ,8b79x0 ,9978x0 ,af7bx0 ,bd7ax0 ,5044x0 ,4245x0 ,7446x0 ,6647x0 ,1840x0 ,0a41x0 ,3c42x0 ,2e43x0 ,d05cx0 ,c25dx0 ,f45ex0 ,e65fx0 ,9858x0 ,8a59x0 ,bc5ax0 ,ae5bx0 ,6527x0 ,7726x0 ,4125x0 ,5324x0 ,2d23x0 ,3f22x0 ,0921x0 ,1b20x0 ,e53fx0 ,f73ex0 ,c13dx0 ,d33cx0 ,ad3bx0 ,bf3ax0 ,8939x0 ,9b38x0 ,7606x0 ,6407x0 ,5204x0 ,4005x0 ,3e02x0 ,2c03x0 ,1a00x0 ,0801x0 ,f61ex0 ,e41fx0 ,d21cx0 ,c01dx0 ,be1ax0 ,ac1bx0 ,9a18x0 ,8819x0 ,87f8x0 ,95f9x0 ,a3fax0 ,b1fbx0 ,cffcx0 ,ddfdx0 ,ebfex0 ,f9ffx0 ,07e0x0 ,15e1x0 ,23e2x0 ,31e3x0 ,4fe4x0 ,5de5x0 ,6be6x0 ,79e7x0 ,94d9x0 ,86d8x0 ,b0dbx0 ,a2dax0 ,dcddx0 ,cedcx0 ,f8dfx0 ,eadex0 ,14c1x0 ,06c0x0 ,30c3x0 ,22c2x0 ,5cc5x0 ,4ec4x0 ,78c7x0 ,6ac6x0 ,a1bax0 ,b3bbx0 ,85b8x0 ,97b9x0 ,e9bex0 ,fbbfx0 ,cdbcx0 ,dfbdx0 ,21a2x0 ,33a3x0 ,05a0x0 ,17a1x0 ,69a6x0 ,7ba7x0 ,4da4x0 ,5fa5x0 ,b29bx0 ,a09ax0 ,9699x0 ,8498x0 ,fa9fx0 ,e89ex0 ,de9dx0 ,cc9cx0 ,3283x0 ,2082x0 ,1681x0 ,0480x0 ,7a87x0 ,6886x0 ,5e85x0 ,4c84x0 ,cb7cx0 ,d97dx0 ,ef7ex0 ,fd7fx0 ,8378x0 ,9179x0 ,a77ax0 ,b57bx0 ,4b64x0 ,5965x0 ,6f66x0 ,7d67x0 ,0360x0 ,1161x0 ,2762x0 ,3563x0 ,d85dx0 ,ca5cx0 ,fc5fx0 ,ee5ex0 ,9059x0 ,8258x0 ,b45bx0 ,a65ax0 ,5845x0 ,4a44x0 ,7c47x0 ,6e46x0 ,1041x0 ,0240x0 ,3443x0 ,2642x0 ,ed3ex0 ,ff3fx0 ,c93cx0 ,db3dx0 ,a53ax0 ,b73bx0 ,8138x0 ,9339x0 ,6d26x0 ,7f27x0 ,4924x0 ,5b25x0 ,2522x0 ,3723x0 ,0120x0 ,1321x0 ,fe1fx0 ,ec1ex0 ,da1dx0 ,c81cx0 ,b61bx0 ,a41ax0 ,9219x0 ,8018x0 ,7e07x0 ,6c06x0 ,5a05x0 ,4804x0 ,3603x0 ,2402x0 ,1201x0 ,0000x0 {= ]652[elbat_crc tni dengisnu ;61 = nel rahc dengisnu ;}ffx0,eex0,ddx0,ccx0,bbx0,aax0,99x0,88x0,77x0,66x0,55x0,44x0,33x0,22x0,11x0,00x0{= ]61[tset rahc dengisnu �序程源的算计节字按写来们我�了好 ,0fe1x0 ,1de0x0 ,2be3x0 ,39e2x0 ,47e5x0 ,55e4x0 ,63e7x0 ,71e6x0 ,8ff9x0 ,9df8x0 ,abfbx0 ,b9fax0 ,c7fdx0 ,d5fc x0 ,e3ffx0 ,f1fex0 ,1cc0x0 ,0ec1x0 ,38c2x0 ,2ac3x0 ,54c4x0 ,46c5x0 ,70c6x0 ,62c7x0 ,9cd8x0 ,8ed9x0 ,b8dax0 ,aadbx0 ,d4dcx0 ,c6ddx0 ,f0dex0 ,e2dfx0 ,29a3x0 ,3ba2x0 ,0da1x0 ,1fa0x0 ,61a7x0 ,73a6x0 ,45a5x0 ,57a4x0 ,a9bbx0 ,bbbax0 ,8db9x0 ,9fb8x0 ,e1bfx0 ,f3bex0 ,c5bdx0 ,d7bcx0 ,3a82x0 ,2883x0 ,1e80x0 ,0c81x0 ,7286x0 ,6087x0 ,5684x0 ,4485x0 ,ba9ax0 ,a89bx0 ,9e98x0 ,8c99x0 ,f29ex0 ,e09fx0 ,d69cx0 ,c49dx0 ,4365x0 ,5164x0 ,6767x0 ,7566x0 ,0b61x0 ,1960x0 ,2f63x0 ,3d62x0 ,c37dx0 ,d17cx0 ,e77fx0 ,f57ex0 ,8b79x0 ,9978 x0 ,af7bx0 ,bd7ax0 ,5044x0 ,4245x0 ,7446x0 ,6647x0 ,1840x0 ,0a41x0 ,3c42x0 ,2e43x0 ,d05cx0 ,c25dx0 ,f45ex0 ,e65fx0 ,9858x0 ,8a59x0 ,bc5ax0 ,ae5bx0 ,6527x0 ,7726x0 ,4125x0 ,5324x0 ,2d23x0 ,3f22x0 ,0921x0 ,1b20x0 ,e53fx0 ,f73ex0 ,c13dx0 ,d33cx0 ,ad3bx0 ,bf3ax0 ,8939x0 ,9b38x0 ,7606x0 ,6407x0 ,5204x0 ,4005x0 ,3e02x0 ,2c03x0 ,1a00x0 ,0801x0 ,f61ex0 ,e41fx0 ,d21cx0 ,c01dx0 ,be1ax0 ,ac1bx0 ,9a18x0 ,8819x0 ,87f8x0 ,95f9x0 ,a3fax0 ,b1fbx0 ,cffcx0 ,ddfdx0 ,ebfex0 ,f9ffx0 ,07e0x0 ,15e1x0 ,23e2x0 ,31e3x0 ,4fe4x0 ,5de5 x0 ,6be6x0 ,79e7x0 ,94d9x0 ,86d8x0 ,b0dbx0 ,a2dax0 ,dcddx0 ,cedcx0 ,f8dfx0 ,eadex0 ,14c1x0 ,06c0x0 ,30c3x0 ,22c2x0 ,5cc5x0 ,4ec4x0 ,78c7x0 ,6ac6x0 ,a1bax0 ,b3bbx0 ,85b8x0 ,97b9x0 ,e9bex0 ,fbbfx0 ,cdbcx0 ,dfbdx0 ,21a2x0 ,33a3x0 ,05a0x0 ,17a1x0 ,69a6x0 ,7ba7 x0 ,4da4x0 ,5fa5x0 ,b29bx0 ,a09ax0 ,9699x0 ,8498x0 ,fa9fx0 ,e89ex0 ,de9dx0 ,cc9cx0 ,3283x0 ,2082x0 ,1681x0 ,0480x0 ,7a87x0 ,6886x0 ,5e85x0 ,4c84x0 ,cb7cx0 ,d97dx0 ,ef7ex0 ,fd7fx0 ,8378x0 ,9179x0 ,a77ax0 ,b57bx0 ,4b64x0 ,5965x0 ,6f66x0 ,7d67x0 ,0360x0 ,1161 x0 ,2762x0 ,3563x0 ,d85dx0 ,ca5cx0 ,fc5fx0 ,ee5ex0 ,9059x0 ,8258x0 ,b45bx0 ,a65ax0 ,5845x0