博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【IT】CRC校验码是怎么回事呢?
阅读量:4510 次
发布时间:2019-06-08

本文共 3623 字,大约阅读时间需要 12 分钟。

 

1. 为什么会有 CRC 校验码?

答:

数据有可能被更改,需要确认是否被更改,且不能占用太多字节,于是有了校验码。

而对一个字节(8位)一个字节的进行循环计算,从而核对数据是否被更改。

 

2. 修改了一定能被 CRC 校验出来吗?

答:

不是,而是一定概率可以校验出来。

奇偶校验就是属于 CRC 校验一种特例。

所以,为了更好的校验,就有了多项式。

更优的多项式,更高概率检查数据被更改。

经常提到的进行二进制触发计算 CRC,被除数,就是多项式(polynomial)。

  CCITT CRC16 CRC32
校验和位宽W 16 16 32
生成多项式 x16+x12+x5+1 x16+x15+x2+1 x32+x26+x23+x22+x16+ x12+x11+x10+x8+x7+x5+ x4+x2+x1+1
除数(多项式) 0x1021 0x8005 0x04C11DB7
余数初始值 0xFFFF 0x0000 0xFFFFFFFF
结果异或值 0x0000 0x0000 0xFFFFFFFF

 

 

3. crc16 算法代码范 表查询法,是怎样的?

 

1 #include 
2 #include
3 4 #define POLY 0x1021 5 6 uint16_t crc16(unsigned char *addr, int num, uint16_t crc) 7 { 8 int i; 9 10 while (num--) {11 crc = crc ^ (*addr++ << 8);12 for (i = 0; i < 8; i++) {13 if (crc & 0x8000) {14 crc = (crc << 1) ^ POLY;15 } else {16 crc <<= 1;17 }18 }19 crc &= 0xFFFF;20 }21 return crc;22 }23 24 int main(void)25 {26 uint8_t data[] = {
0x02, 0x05};27 28 printf("%04X\n", crc16(data, 2, 0xFFFF));29 30 return 0;31 }

 

4. crc16 是处理部分的逻辑是怎样的?

    a、11 行操作,crc 的低 8 位不变,仅仅是 crc 的高 8 位被修改了

    b、12 行到 18 行:高 8 位决定了会进行多少次与固定数字 POLY(多项式) 的异或操作。

 

5. 表查询法,是怎么回事呢?

    问:为什么会有表查询法?

    答:因为上面是一个一个 bit 位进行操作。所以在要计算的数据比较多的时候,就很影响效率。

 

    问:表查询法是如何做到优化的?

    答:

        a、异或操作满足结合律、交换律。与+操作类似。

        b、假设一个8位的数字,分别以 H1、 H2、 H3、 H4、  L1、 L2、 L3、 L4来表示。

              V1、 V2、 V3、 V4、 V5、 V6、 V7、V8 表示 POLY(多项式)的二进制。

                

 

 

               上下进行异或操作,高4位决定了低4位会和 POLY 进行多少次异或。

               因异或操作满足结合律、交换律。上面的异或操作与下面的异或操作等价。

               所以,当重复计算比较多的时候,下面的  H1 与 Vx 之间的计算结果可以保存到一个表中,后续直接查询来使用。

               因 CRC 校验是一次处理一字节(8位),所以表格就有 2 的 8 次方 = 256 个。

 

6、查表法的范例:

 

1 #include 
2 3 #include
4 5 #define POLY 0x1021 6 #define INIT 0xFFFF 7 #define FINAL 0x0000 8 9 typedef uint16_t width_t;10 11 #define WIDTH (8 * sizeof(width_t))12 #define TOPBIT (1 << (WIDTH - 1))13 14 uint16_t crc16(unsigned char *addr, int num, uint16_t crc)15 {16 int i;17 18 while (num--) {19 crc = crc ^ (*addr++ << 8);20 for (i = 0; i < 8; i++) {21 if (crc & 0x8000) {22 crc = (crc << 1) ^ POLY;23 } else {24 crc <<= 1;25 }26 }27 crc &= 0xFFFF;28 }29 return crc;30 }31 32 33 34 static width_t crc_table[256];35 36 void crc_init(void)37 {38 width_t reg;39 width_t i, j;40 41 for (i = 0; i < 256; i++) {42 reg = i << (WIDTH - 8);43 for(j = 0; j < 8; j++) {44 if(reg & TOPBIT) {45 reg = (reg << 1) ^ POLY;46 } else {47 reg = reg << 1;48 }49 }50 crc_table[i] = reg;51 }52 }53 54 width_t crc_compute(unsigned char *addr, unsigned int num)55 {56 unsigned int i;57 unsigned int high; 58 width_t reg = INIT;59 60 for (i = 0; i < num; i++) {61 high = (reg >> (WIDTH - 8)) ^ addr[i];62 reg = crc_table[high] ^ (reg << 8);63 }64 65 return (reg ^ FINAL);66 }67 68 69 int main(void)70 {71 uint8_t data[] = {
0x02, 0x05};72 73 printf("%04X\n", crc16(data, 2, 0xFFFF));74 75 crc_init();76 printf("%04X\n", crc_compute(data, 2));77 78 return 0;79 }

 

 

参考:

【循环冗余校验(CRC)算法入门引导】https://blog.csdn.net/liyuanbhu/article/details/7882789

【CRC查找表法推导及代码实现比较】https://blog.csdn.net/huang_shiyang/article/details/50881305

【A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS】https://wenku.baidu.com/view/6e700a3b31126edb6f1a1084.html

 【On-line CRC calculation and free library】https://www.lammertbies.nl/comm/info/crc-calculation.html

转载于:https://www.cnblogs.com/YBhello/p/11518196.html

你可能感兴趣的文章
Java-循环语句和条件语句
查看>>
mysql数据库和禅道安装
查看>>
一、python特性+python安装测试
查看>>
Windows下安装Ubuntu16.04双系统
查看>>
Windows文件操作基础代码
查看>>
1-8
查看>>
任务17:从UML角度来理解依赖
查看>>
阶段1 语言基础+高级_1-3-Java语言高级_04-集合_04 数据结构_2_数据结构_队列
查看>>
Entity Framework操作Oracle数据库实现主键自增问题
查看>>
Leetcode WC-108-03 931-下降路径最小和
查看>>
从“智猪博弈”看所谓“大国责任”
查看>>
Day3:Spring-JDBC、事务管理
查看>>
模块的四种形式
查看>>
教你如何培养幽默感
查看>>
asp.net的一个简单简历缓存方法
查看>>
loj 1185(bfs)
查看>>
HTML5 (三)本地存储
查看>>
全排列-按从大到小-time limited
查看>>
nginx https使用
查看>>
task_13
查看>>