CRC16校验-C语言代码

合集下载

C语言实现CRC16校验

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 c语言代码

crc16 c语言代码
} else {
crc >>= 1; //如果为0,则只将CRC寄存器右移一位
}
}
}
return crc;
}
int main() {
unsigned char data[] = {0x01, 0x02, 0x03, 0x04, 0x05}; //要计算CRC16校验码的数据
unsigned short crc = crc16(data, sizeof(data)); //计算CRC16校验码
#include <stdio.h>
#define POLY 0x8005 // CRC-16-CCITT多项式
unsigned shoБайду номын сангаасt crc16(unsigned char *data, int length) {
unsigned short crc = 0xFFFF; //初始值为0xFFFF
printf("CRC16校验码为:%04X\n", crc); //输出CRC16校验码
return 0;
}
这个代码使用了一个简单的算法来计算CRC16校验码。它首先将初始值设置为0xFFFF,然后将数据位逐个异或到CRC寄存器中。接下来,它检查最低有效位是否为1,如果是,则将CRC寄存器右移一位并异或多项式;否则,只将CRC寄存器右移一位。最后,返回计算得到的CRC16校验码。
int i, j;
for (i = 0; i < length; i++) {
crc ^= (unsigned short)(data[i]); //将数据位异或到CRC寄存器中
for (j = 0; j < 8; j++) {

c#实现16位crc校验源代码

c#实现16位crc校验源代码

void Crc(byte[] buffer);
void Crc(byte[] buf, int off, int len);
}
}
namespace CRC
{
/// <summary>
/// CRC16 的摘要说明。
/// </summary>
public class p
{
public static void Main()
{
}
public class CRC16 : ICRC
{
#region CRC 16 位校验表
/// </summary>
public void Reset()
{
crc = 0;
}
/// <summary>
/// Crc16
Crc(buffer, 0, buffer.Length);
}
/// <summary>
/// Crc16
/// </summary>
/// <param name="buf"></param>
Crc(buf[i]);
}
}
}
}
}
/// <param name="bval"></param>
public void Crc(int bval)
{
ushort h = (ushort)((crc >> 12) & 0x0f);
/// Crc16

C语言实现CRC校验

C语言实现CRC校验

C语言实现CRC校验1.按位计算法:按位计算是一种基本的CRC校验方法。

实现步骤如下:1)定义一个用于存储CRC校验结果的变量(通常是一个无符号整数)并初始化为零。

2)将待校验的数据按位划分。

3)逐位处理每个划分的数据,以异或运算(^)与之前计算得到的CRC结果进行计算,直到处理完所有数据。

4)最终得到的CRC校验结果即为校验码。

示例代码如下:```c#include <stdio.h>unsigned int calculateCRC(unsigned char *data, int size)unsigned int crc = 0;for (int i = 0; i < size; i++)crc ^= data[i] << 8;for (int bit = 0; bit < 8; bit++)if ((crc & 0x8000) != 0)crc = (crc << 1) ^ 0x1021;} elsecrc <<= 1;}}}return crc;int maiunsigned char data[] = {0x01, 0x02, 0x03, 0x04, 0x05};int size = sizeof(data) / sizeof(data[0]);unsigned int crc = calculateCRC(data, size);printf("CRC: 0x%04X\n", crc);return 0;```上述代码中,`calculateCRC`函数用于计算CRC校验结果,接受一个指向待校验数据的指针和数据长度作为参数。

`main`函数通过调用`calculateCRC`函数计算CRC校验结果,并使用`printf`函数打印结果。

2.查表法:查表法是另一种常用的CRC校验算法,通过建立一个查找表来提高计算效率。

CRC-16校验C#代码

CRC-16校验C#代码

CRC-16校验C#代码[csharp]01. using System;02. using System.Collections.Generic;03. using System.Text;04. using System.Runtime.Serialization.Formatters.Binary;05. using System.IO;06.07. namespace smsForCsharp.CRC08. {09. /// <summary>10. /// 消息CRC校验算法11. /// </summary>12. public class CRC13. {14.15. public static String getCrc16Code(String crcString)16. {17.18. // 转换成字节数组19. byte[] creBytes = HexString2Bytes(crcString);20.21. // 开始crc16校验码计算22. CRC16Util crc16 = new CRC16Util();23. crc16.reset();24. crc16.update(creBytes);25. int crc = crc16.getCrcValue();26. // 16进制的CRC码27. String crcCode = Convert.ToString(crc, 16).ToUpper();28. // 补⾜到4位29. if (crcCode.Length < 4)30. {31. // crcCode = StringUtil.lefgPadding(crcCode, '0', 4);32. crcCode = crcCode.PadLeft(4, '0');33. }34. return crcCode;35. }36.37.38. public static String RealHexToStr(String str)39. {40. String hText = "0123456789ABCDEF";41. StringBuilder bin = new StringBuilder();42. for (int i = 0; i < str.Length; i++)43. {44. bin.Append(hText[str[i] / 16]).Append(hText[str[i] % 16]).Append(' ');45. }46. return bin.ToString();47. }48. /**49. * ⼗六进制字符串转换成字节数组50. *51. * @param hexstr52. * @return53. */54. public static byte[] HexString2Bytes(String hexstr)55. {56. byte[] b = new byte[hexstr.Length / 2];57. int j = 0;58. for (int i = 0; i < b.Length; i++)59. {60. char c0 = hexstr[j++];61. char c1 = hexstr[j++];62. b[i] = (byte)((parse(c0) << 4) | parse(c1));63. }64. return b;65. }66.67.68. /**69. * 16进制char转换成整型70. *71. * @param c72. * @return73. */74. public static int parse(char c)77. return (c - 'a' + 10) & 0x0f;78. if (c >= 'A')79. return (c - 'A' + 10) & 0x0f;80. return (c - '0') & 0x0f;81. }82.83.84.85.86. public static string ByteArrayToHexString(byte[] data)//字节数组转为⼗六进制字符串87. {88. StringBuilder sb = new StringBuilder(data.Length * 3);89. foreach (byte b in data)90. sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));91. return sb.ToString().ToUpper();92. }93.94. }95.96.97.98.99. public class CRC16Util100. {101.102. /**CRC值*/103. private int value = 0xffff;104.105. private static int[] CRC16_TABLE = {106. 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,107. 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,108. 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,109. 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,110. 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,111. 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,112. 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,113. 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,114. 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,115. 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,116. 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,117. 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,118. 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,119. 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,120. 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,121. 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,122. 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,123. 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,124. 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,125. 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,126. 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,127. 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,128. 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,129. 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,130. 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,131. 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,132. 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,133. 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,134. 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,135. 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,136. 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,137. 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78138. };139.140. /**141. * 计算⼀个字节数组的CRC值142. * @param data143. */144. public void update(byte[] data)145. {146. //int fcs = 0xffff;147. for (int i = 0; i < data.Length; i++)148. {149. // 1.value 右移8位(相当于除以256)150. // 2.value与进来的数据进⾏异或运算后再与0xFF进⾏与运算151. // 得到⼀个索引index,然后查找CRC16_TABLE表相应索引的数据152. // 1和2得到的数据再进⾏异或运算。

crc16校验算法c语言

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语言实现

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校验。

CRC16校验-C语言代码

CRC16校验-C语言代码

CRC16校验-C语⾔代码//CRC16校验在通讯中应⽤⼴泛,这⾥不对其理论进⾏讨论,只对常见的3种//实现⽅法进⾏测试。

⽅法1选⽤了⼀种常见的查表⽅法,类似的还有512字//节、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 0x8005// --------------------------------------------------------------// CRC16计算⽅法1:使⽤2个256长度的校验表// --------------------------------------------------------------const 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) ;}// --------------------------------------------------------------// CRC16计算⽅法2:使⽤简单的校验表// --------------------------------------------------------------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计算⽅法3:使⽤直接结算的⽅法// -----------------------------------------------------------------WORD CRC16_3(BYTE* pchMsg, WORD wDataLen){BYTE i, chChar;WORD wCRC = 0xFFFF;while (wDataLen--){chChar = *pchMsg++;chChar = ByteInvert(chChar);wCRC ^= (((WORD) chChar) << 8);for (i = 0; i < 8; i++){if (wCRC & 0x8000)wCRC = (wCRC << 1) ^ CRC_16_POLYNOMIALS;elsewCRC <<= 1;}}wCRC = WordInvert(wCRC);return wCRC;}//试验数据:// 采⽤Metrowerks CodeWarrior在DSP56F80x平台上,对这3种⽅法//进⾏了性能测试。

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

//CRC16校验在通讯中应用广泛,这里不对其理论进行讨论,只对常见的3种//实现方法进行测试。

方法1选用了一种常见的查表方法,类似的还有512字//节、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 0x8005// --------------------------------------------------------------// CRC16计算方法1:使用2个256长度的校验表// --------------------------------------------------------------const 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) ;}// --------------------------------------------------------------// CRC16计算方法2:使用简单的校验表// --------------------------------------------------------------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计算方法3:使用直接结算的方法// -----------------------------------------------------------------WORD CRC16_3(BYTE* pchMsg, WORD wDataLen){BYTE i, chChar;WORD wCRC = 0xFFFF;while (wDataLen--){chChar = *pchMsg++;chChar = ByteInvert(chChar);wCRC ^= (((WORD) chChar) << 8);for (i = 0; i < 8; i++){if (wCRC & 0x8000)wCRC = (wCRC << 1) ^ CRC_16_POLYNOMIALS;elsewCRC <<= 1;}}wCRC = WordInvert(wCRC);return wCRC;}//试验数据:// 采用Metrowerks CodeWarrior在DSP56F80x平台上,对这3种方法//进行了性能测试。

相关文档
最新文档