zoukankan      html  css  js  c++  java
  • 【IT】CRC校验码是怎么回事呢?

    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 <stdio.h>
     2 #include <stdint.h>
     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
    ", 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 <stdio.h>
     2 
     3 #include <stdint.h>
     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
    ", crc16(data, 2, 0xFFFF));
    74 
    75     crc_init();
    76     printf("%04X
    ", 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

  • 相关阅读:
    (转)TweenMax动画库学习(三)
    (转)TweenMax动画库学习(二)
    (转)TweenMax动画库学习(一)
    深入剖析Java中的装箱与拆箱(转)
    Spring MVC 和 Spring 总结(转)
    react native for android(ajax)
    React Native HelloWorld
    C# JMAIL发送邮件
    C# 接收邮件
    Spring Mvc Mybatis(初次学习)
  • 原文地址:https://www.cnblogs.com/YBhello/p/11518196.html
Copyright © 2011-2022 走看看