CRC校验8
什么是CRC校验?
CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。
CRC校验原理:
其根本思想就是先在要发送的帧后面附加一个数。(这个就是用来校验的校验码,但要注意,这里的数也是二进制序列的,下同),生成一个新帧发送给接收端。
当然,这个附加的数不是随意的,它要使所生成的新帧能与发送端和接收端共同选定的某个特定数整除(注意,这里不是直接采用二进制除法,而是采用一种称之为“模2除法”)。
到达接收端后,再把接收到的新帧除以(同样采用“模2除法”)这个选定的除数。因为在发送端发送数据帧之前就已通过附加一个数,做了“去余”处理(也就已经能整除了),所以结果应该是没有余数。如果有余数,则表明该帧在传输过程中出现了差错。
模2除法:
模2除法与算术除法类似,但每一位除的结果不影响其它位,即不向上一位借位,所以实际上就是异或。在循环冗余校验码(CRC)的计算中有应用到模2除法。
例:

CRC8算法:
需求数据:
多项式:x8+x5+x4+1(二进制为:100110001) 0x31(0x131)
计算一个字节:0x11 (二进制为:00010001)
计算步骤:
A、 因为采用顺序异或,所以需要计算的数据左移8位, 移位后数据为:0001 0001 0000 0000
B、 先进行高9bit异或(多项式为9bit),0001 0001 0000 0000,因为高9bit的 最高bit为0,不需要进行异或,同理,接下来的两bit也是0,也不需要进行进行异或。 这样处理后数据为:1 0001 0000 0000;
C、 接下来最高位为1,需要进行异或操作了

从上面的计算过程可以看到,多项式最高位为1,遇到需要异或数据最高位为1时, 才进行异或计算,并且异或后,最高位就为0了,最高位为0,下次也不需要异或了, 这样需要采用代码计算的方式,就可以把最高位去掉,不需要异或,最后结果也是一样的。
代码实现:
a、是计算一个字节数据的crc结果,如果是计算多个字节的crc结果,也是比较简单
unsigned char cal_table_high_first(unsigned char value)
{
unsigned char i, crc; crc = value; //0001 0001
/* 数据往左移了8位,需要计算8次 */
for (i=; i>; --i)
{
if (crc & 0x80) /* 判断最高位是否为1 */
{
/* 最高位为1,不需要异或,往左移一位,然后与0x31异或 */
/* 0x31(多项式:x8+x5+x4+1,100110001),最高位不需要异或,直接去掉 */
/*参见C步骤*/
crc = (crc << ) ^ 0x31; }
else
{
/* 最高位为0时,不需要异或,整体数据往左移一位 */
crc = (crc << );
}
} return crc;
}
的,先计算第一个字节的crc结果,然后把第一个字节的crc结果与第二个字节进行异或, 异或后的值再进行一次crc计算就可以了,多个字节也是反复这过程就好,如下为多个字节 的crc校验代码:
unsigned char crc_high_first(unsigned char *ptr, unsigned char len)
{
unsigned char i;
unsigned char crc=0x00; /* 计算的初始crc值 */ while(len--)
{
crc ^= *ptr++; /* 每次先与需要计算的数据异或,计算完指向下一数据 */
/ptr应为需要计算的数据的每个字节的指针*/
for (i=; i>; --i) /* 下面这段计算过程与计算一个字节crc一样 */
{
if (crc & 0x80)
crc = (crc << ) ^ 0x31;
else
crc = (crc << );
}
} return (crc);
}
上面的crc计算是纯采用逻辑运行的方式,可以看到,需要的运行量也是不少的,每一个字节都需要进行8次判断、移位、或异或操作。可以采用查表法,大大减少计算量,先计算出 0x00~0xFF每一个字节的crc校验结果,后面就可以通过表来查出每个字节的crc结果,大大 减少计算量。
下面是一个表生成程序: (生成表对应多项式:0x31(多项式:x8+x5+x4+1,100110001))
void create_crc_table(void)
{
unsigned short i;
unsigned char j; for (i=; i<=0xFF; i++)
{
if ( == (i%))
printf("\n"); j = i&0xFF;
printf("0x%.2x, ", cal_table_high_first (j)); /*依次计算每个字节的crc校验值*/
}
}
得到的表整理后如下:
static const unsigned char crc_table[] =
{
0x00,0x31,0x62,0x53,0xc4,0xf5,0xa6,0x97,0xb9,0x88,0xdb,0xea,0x7d,0x4c,0x1f,0x2e,
0x43,0x72,0x21,0x10,0x87,0xb6,0xe5,0xd4,0xfa,0xcb,0x98,0xa9,0x3e,0x0f,0x5c,0x6d,
0x86,0xb7,0xe4,0xd5,0x42,0x73,0x20,0x11,0x3f,0x0e,0x5d,0x6c,0xfb,0xca,0x99,0xa8,
0xc5,0xf4,0xa7,0x96,0x01,0x30,0x63,0x52,0x7c,0x4d,0x1e,0x2f,0xb8,0x89,0xda,0xeb,
0x3d,0x0c,0x5f,0x6e,0xf9,0xc8,0x9b,0xaa,0x84,0xb5,0xe6,0xd7,0x40,0x71,0x22,0x13,
0x7e,0x4f,0x1c,0x2d,0xba,0x8b,0xd8,0xe9,0xc7,0xf6,0xa5,0x94,0x03,0x32,0x61,0x50,
0xbb,0x8a,0xd9,0xe8,0x7f,0x4e,0x1d,0x2c,0x02,0x33,0x60,0x51,0xc6,0xf7,0xa4,0x95,
0xf8,0xc9,0x9a,0xab,0x3c,0x0d,0x5e,0x6f,0x41,0x70,0x23,0x12,0x85,0xb4,0xe7,0xd6,
0x7a,0x4b,0x18,0x29,0xbe,0x8f,0xdc,0xed,0xc3,0xf2,0xa1,0x90,0x07,0x36,0x65,0x54,
0x39,0x08,0x5b,0x6a,0xfd,0xcc,0x9f,0xae,0x80,0xb1,0xe2,0xd3,0x44,0x75,0x26,0x17,
0xfc,0xcd,0x9e,0xaf,0x38,0x09,0x5a,0x6b,0x45,0x74,0x27,0x16,0x81,0xb0,0xe3,0xd2,
0xbf,0x8e,0xdd,0xec,0x7b,0x4a,0x19,0x28,0x06,0x37,0x64,0x55,0xc2,0xf3,0xa0,0x91,
0x47,0x76,0x25,0x14,0x83,0xb2,0xe1,0xd0,0xfe,0xcf,0x9c,0xad,0x3a,0x0b,0x58,0x69,
0x04,0x35,0x66,0x57,0xc0,0xf1,0xa2,0x93,0xbd,0x8c,0xdf,0xee,0x79,0x48,0x1b,0x2a,
0xc1,0xf0,0xa3,0x92,0x05,0x34,0x67,0x56,0x78,0x49,0x1a,0x2b,0xbc,0x8d,0xde,0xef,
0x82,0xb3,0xe0,0xd1,0x46,0x77,0x24,0x15,0x3b,0x0a,0x59,0x68,0xff,0xce,0x9d,0xac
};
采用查表法计算crc代码如下:
unsigned char cal_crc_table(unsigned char *ptr, unsigned char len)
{
unsigned char crc = 0x00; while (len--)
{
crc = crc_table[crc ^ *ptr++];
}
return (crc);
}
反序异或的计算
反序异或与顺序异或差异在数据先判断最低位,并且数据是向右移 的,并且多项式数据位需要高低位反转一下。 还是以多项式:x8+x5+x4+1(二进制为:100110001)为例:则计算一个字节的crc校验代码如下:
unsigned char cal_table_low_first(unsigned char value)
{
unsigned char i, crc; crc = value;
/* 同样需要计算8次 */
for (i=; i>; --i)
{
if (crc & 0x01) /* 反序异或变成判断最低位是否为1 */
/* 数据变成往右移位了 */
/* 计算的多项式从0x31(0011 0001)变成了0x8C (1000 1100) */
/* 多项式值,原来的最高位变成了最低位,原来的最低位变成最高位,8位数据高低位交换一下位置 */
crc = (crc >> ) ^ 0x8C;
else
crc = (crc >> );
} return crc;
}
至于多个字节的crc校验及crc数据表的生成,只要把单个字节的计算方式替换一下顺序的 计算方式即可,这里就不再列出。所以,只要明确了crc校验使用的多项式,高位先校验 还是低位先校验,计算crc的初始值是什么,那crc的计算就变得很简单了。
***********************************************************************************************************************
待更新,添加CRC32代码和运行结果
参考:https://blog.csdn.net/d_leo/article/details/73572373 https://blog.csdn.net/zjli321/article/details/52998468
CRC校验8的更多相关文章
- 文档:网络通讯包结构(crc校验,加解密)
一直想把这个流程整理一下. 包结构: 包 对(datacrc+protoID+dataSize)组成的byte[] 进行crc计算而得到 对(数据内容)进行crc计算而得到 协议号 数据内容的字节长度 ...
- CRC校验码原理、实例、手动计算
目录一.CRC16实现代码二.CRC32编码字符表三.CRC校验码的手动计算示例四.CRC校验原理五.CRC的生成多项式参考 一.CRC16实现代码 思路:取一个字符(8bit),逐位检查该字符,如果 ...
- 物联网平台设计心得:你所不知道的CRC校验
在物联网平台设计过程中,我的中间件一方面需要处理来自于硬件端的包,另一方面需要处理来自于用户端的包,用户端包括web端和手机端等等.所以编写一个统一的CRC认证是非常必须要. 那么,在设计开始,CRC ...
- CRC校验代码实现
1.CRC校验简介 CRC就是块数据的计算值,它的全称是“Cyclic Redundancy Check”,中文名是“循环冗余码”.CRC校验是数据通讯中最常采用的校验方式.在嵌入式软件开发中,经常要 ...
- CRC校验码
循环冗余校验码(CRC)的基本原理是:在K位信息码后再拼接R位的校验码,整个编码长度为N位,因此,这种编码也叫(N,K)码.对于一个给定的(N,K)码,可以证明存在一个最高次幂为R的多项式G(x)(R ...
- C# CRC校验的一点感悟
今天在鼓捣一个手持操作器的时候,遇到一点问题,记录一下今天的经验包 由于之前公司产品在校验时基本上都是和校验,今天在准备用C#模拟一个古董操作器的时候,却遇到一个问题,模拟器发出的数据,主板一律不回复 ...
- CRC校验源码分析
这两天做项目,需要用到 CRC 校验.以前没搞过这东东,以为挺简单的.结果看看别人提供的汇编源程序,居然看不懂.花了两天时间研究了一下 CRC 校验,希望我写的这点东西能够帮助和我有同样困惑的朋友节省 ...
- 在线CRC校验
在线CRC校验: http://www.lammertbies.nl/comm/info/crc-calculation.html
- CRC校验
小试一下CRC校验的verilog实现,采用最stupid的直接法. /* date : 2014/06/06 designer : pengxiaoen virsion : Altera-Model ...
- 网络通信 --> CRC校验
CRC校验 一.什么是CRC校验 循环校验码(Jyclic Redundancy Check,简称CRC码): 是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意 ...
随机推荐
- 我的书单mybooklist
首先自我介绍一下,我是一名程序员. 计算机的世界太浩瀚,而我太过渺小. 比计算机的世界更为广大的是,书籍的海洋.学海无涯. 无论是计算机的世界,还是其他类书的世界,人一辈子要看的书看也看不完. 于是我 ...
- matlab练习程序(Bresenham画线)
Bresenham画线算图形学中最基础的知识了,可惜我并没有选修过图形学,所有还是有必要熟悉一下. 上一篇用到的画线函数应该算是数值微分法,也是我最常用的一种方法,不过这种方法似乎并不是很好. 这里的 ...
- 关于String s = new String("xyz");创建了几个字符串对象?的问题
引用自这位朋友:http://blog.sina.com.cn/s/blog_6a6b14100100zn6r.html 首先让我们了解几个概念: 栈:由JVM分配区域,用于保存线程执行的动作和数据引 ...
- Select selectedIndex 属性
定义和用法 selectedIndex 属性可设置或返回下拉列表中被选选项的索引号. 注意: 若允许多重选择,则仅会返回第一个被选选项的索引号. 语法 设置 selectedIndex 属性: sel ...
- Laravel SMS 短信发送包
Laravel Sms Laravel 贴合实际需求同时满足多种通道的短信发送组件 我们基于业务需求在 overtrue/easy-sms 基础进行扩展开发,主要实现如下目标: 支持短信验证码直接在 ...
- Do the Untwist
Do the Untwist Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- ubuntu安装google test
google test 简称gtest,是一个C/C++的单元测试框架,它的代码在github仓库,使用起来还是挺方便的. 安装 先确保PC上有安装cmake: sudo cmake --versio ...
- Linux 网卡的解决方法
1. 编辑70-persistent-net配置文件: # vi /etc/udev/rules.d/70-persistent-net.rules 如果没有就新建一个,添加如下内容: # PCI d ...
- TCP的建立和关闭
一.TCP头信息 简单的至少应该知道,源端口,目的端口,序号,确认号,标志位,校验和 二.TCP的建立 1.客户端将SYN标志位置1,同时生成随机的序号,确认号是0. 2.服务器接收到SYN,知道有人 ...
- MySQL联合索引最左匹配范例
MySQL联合索引最左匹配范例 参考文章:http://blog.jobbole.com/24006/ 创建示例表. 示例表来自MySQL官方文档: https://dev.mysql.com/doc ...