CRC查表法——表的由来及Java实现CRC8校验算法

转载请标明出处: http://blog.csdn.net/xx326664162/article/details/51718857 文章出自:薛瑄的博客

你也可以查看我的其他同类文章,也会让你有一定的收货!

大概思路

我先说一下查表法,表的计算方法,以CRC4为例:

  • 生成多项式:B = 10011B

  • 测试数据:A = 0011 1110B

1、查表法实际上是利用XOR的交换律和结合律:(A XOR B)XOR C=A XOR (B XOR C)

2、将测试数据A 每4bit分为一组,0011 0000B 和 1110B

  • 先计算出0011 0000B的CRC4值
  • 然后XOR下个4bit 1110B,再计算CRC4的值。

分组举例:
C1=00110000B,C2=1110B,C3=0011B.
A = C1 XOR C2
则 A XOR B = (C1 XOR C2) XOR B =(C1 XOR B )XOR C2

可能你会产生几个问题:

1、为什么要每4bit分为一组?

注意: 由于每次处理多bit(假设是N),那么数据长度必须是N的倍数。

  • 以半字节为例,由于每次处理4bit,所以数据长度必须为4的倍数。
  • 如果非4的倍数,需要特殊处理(驱动表法和直接计算法混用)。

例如,数据长度是74bit,前面72bit可以按照查表法,后面2bit则只能是直接计算法。

每4bit一组,完全是为了方便计算

2、就算分组,还不一样是要计算,那和直接计算有什么区别?

可以事先计算出,0000B - 1111B所有数据,对应CRC的值,保存在程序中。这样将数据划分后,计算时遇到数据,直接查表得到对应CRC的值,省去了计算的过程。

计算表:

  • 生成多项式:B = 10011B
  • 测试数据:A = 0011 1110B

1、A对B的CRC 过程可以表示为:A XOR B1 XOR B

   ——————————————
A  0 0 1 1 1 1 1 0 
       1 0 0 1 1 0  B1
       ——————————
         1 1 0 0 0
         1 0 0 1 1  B
         ————————
           1 0 1 1

2、

  • 将测试数据A每4bit分组C1=00110000B,C2=1110B。A = C1 XOR C2

  • A XOR B1 XOR B = (C1 XOR C2)XOR B1 XOR B = (C1 XOR B1 XOR B XOR )C2

       ——————————————
    C1 0 0 1 1 0 0 0 0 
           1 0 0 1 1 0  B1
           ——————————
             1 0 1 1 0
             1 0 0 1 1  B
             ————————
               0 1 0 1
    C2         1 1 1 0
               ——————           
               1 0 1 1
    这样就可以把数据CRC的计算,分为每4bit一组来计算CRC的值,因为4bit可表示16中情况,所以可以分别列出这些4bit数据对应的CRC值,以后直接拿来用,于是有了下表。

3、多项式crc4的表格

索引数据表值
000000000
100010011
200100110
300110101
401001100
501011111
601101010
701111001
810001011
910011000
1010101101
1110111110
1211000111
1311010100
1411100001
1511110010

用查表法计算之前的例子:
   ——————————————
A  0 0 1 1 1 1 1 0 
           0 1 0 1 表中查找数据0011对应的表值为0101
           ——————           
           1 0 1 1

Java实现CRC8校验——查表法

http://blog.csdn.net/trbbadboy/article/details/16859937
http://www.javacui.com/Theory/218.html

/** 
 * CRC8相关计算  

 * encode: utf-8 
 *  
 * @author trb 
 * @date 2013-11-21 
 */  
public class CRC8 {  
    static byte[] crc8_tab = { (byte) 0, (byte) 94, (byte) 188, (byte) 226, (byte) 97, (byte) 63, (byte) 221, (byte) 131, (byte) 194, (byte) 156, (byte) 126, (byte) 32, (byte) 163, (byte) 253, (byte) 31, (byte) 65, (byte) 157, (byte) 195, (byte) 33, (byte) 127, (byte) 252, (byte) 162, (byte) 64, (byte) 30, (byte) 95, (byte) 1, (byte) 227, (byte) 189, (byte) 62, (byte) 96, (byte) 130, (byte) 220, (byte) 35, (byte) 125, (byte) 159, (byte) 193, (byte) 66, (byte) 28, (byte) 254, (byte) 160, (byte) 225, (byte) 191, (byte) 93, (byte) 3, (byte) 128, (byte) 222, (byte) 60, (byte) 98, (byte) 190, (byte) 224, (byte) 2, (byte) 92, (byte) 223, (byte) 129, (byte) 99, (byte) 61, (byte) 124, (byte) 34, (byte) 192, (byte) 158, (byte) 29, (byte) 67, (byte) 161, (byte) 255, (byte) 70, (byte) 24,  
            (byte) 250, (byte) 164, (byte) 39, (byte) 121, (byte) 155, (byte) 197, (byte) 132, (byte) 218, (byte) 56, (byte) 102, (byte) 229, (byte) 187, (byte) 89, (byte) 7, (byte) 219, (byte) 133, (byte) 103, (byte) 57, (byte) 186, (byte) 228, (byte) 6, (byte) 88, (byte) 25, (byte) 71, (byte) 165, (byte) 251, (byte) 120, (byte) 38, (byte) 196, (byte) 154, (byte) 101, (byte) 59, (byte) 217, (byte) 135, (byte) 4, (byte) 90, (byte) 184, (byte) 230, (byte) 167, (byte) 249, (byte) 27, (byte) 69, (byte) 198, (byte) 152, (byte) 122, (byte) 36, (byte) 248, (byte) 166, (byte) 68, (byte) 26, (byte) 153, (byte) 199, (byte) 37, (byte) 123, (byte) 58, (byte) 100, (byte) 134, (byte) 216, (byte) 91, (byte) 5, (byte) 231, (byte) 185, (byte) 140, (byte) 210, (byte) 48, (byte) 110, (byte) 237,  
            (byte) 179, (byte) 81, (byte) 15, (byte) 78, (byte) 16, (byte) 242, (byte) 172, (byte) 47, (byte) 113, (byte) 147, (byte) 205, (byte) 17, (byte) 79, (byte) 173, (byte) 243, (byte) 112, (byte) 46, (byte) 204, (byte) 146, (byte) 211, (byte) 141, (byte) 111, (byte) 49, (byte) 178, (byte) 236, (byte) 14, (byte) 80, (byte) 175, (byte) 241, (byte) 19, (byte) 77, (byte) 206, (byte) 144, (byte) 114, (byte) 44, (byte) 109, (byte) 51, (byte) 209, (byte) 143, (byte) 12, (byte) 82, (byte) 176, (byte) 238, (byte) 50, (byte) 108, (byte) 142, (byte) 208, (byte) 83, (byte) 13, (byte) 239, (byte) 177, (byte) 240, (byte) 174, (byte) 76, (byte) 18, (byte) 145, (byte) 207, (byte) 45, (byte) 115, (byte) 202, (byte) 148, (byte) 118, (byte) 40, (byte) 171, (byte) 245, (byte) 23, (byte) 73, (byte) 8,  
            (byte) 86, (byte) 180, (byte) 234, (byte) 105, (byte) 55, (byte) 213, (byte) 139, (byte) 87, (byte) 9, (byte) 235, (byte) 181, (byte) 54, (byte) 104, (byte) 138, (byte) 212, (byte) 149, (byte) 203, (byte) 41, (byte) 119, (byte) 244, (byte) 170, (byte) 72, (byte) 22, (byte) 233, (byte) 183, (byte) 85, (byte) 11, (byte) 136, (byte) 214, (byte) 52, (byte) 106, (byte) 43, (byte) 117, (byte) 151, (byte) 201, (byte) 74, (byte) 20, (byte) 246, (byte) 168, (byte) 116, (byte) 42, (byte) 200, (byte) 150, (byte) 21, (byte) 75, (byte) 169, (byte) 247, (byte) 182, (byte) 232, (byte) 10, (byte) 84, (byte) 215, (byte) 137, (byte) 107, 53 };  

    /** 
     * 计算数组的CRC8校验值 
     *  
     * @param data 
     *            需要计算的数组 
     * @return CRC8校验值 
     */  
    public static byte calcCrc8(byte[] data) {  
        return calcCrc8(data, 0, data.length, (byte) 0);  
    }  

    /** 
     * 计算CRC8校验值 
     *  
     * @param data 
     *            数据 
     * @param offset 
     *            起始位置 
     * @param len 
     *            长度 
     * @return 校验值 
     */  
    public static byte calcCrc8(byte[] data, int offset, int len) {  
        return calcCrc8(data, offset, len, (byte) 0);  
    }  

    /** 
     * 计算CRC8校验值 
     *  
     * @param data 
     *            数据 
     * @param offset 
     *            起始位置 
     * @param len 
     *            长度 
     * @param preval 
     *            之前的校验值 
     * @return 校验值 
     */  
    public static byte calcCrc8(byte[] data, int offset, int len, byte preval) {  
        byte ret = preval;  
        for (int i = offset; i < (offset + len); ++i) {  
            ret = crc8_tab[(0x00ff & (ret ^ data[i]))];  
        }  
        return ret;  
    }  

    // 测试  
    public static void main(String[] args) {  
        byte crc = CRC8.calcCrc8(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });  
        System.out.println("" + Integer.toHexString(0x00ff & crc));  
    }  
}  

参考:http://www.xjtudll.cn/Exp/273/

关注我的公众号,轻松了解和学习更多技术
这里写图片描述

crc8校验的原理,程序和检验软件 CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。 CRC校验可以简单地描述为:例如我们要发送一些数据(信息字段),为了避免一些干扰以及在接收端的对读取的数据进行判断是否接受的是真实的数据,这时我们就要加上校验数据(即CRC校验码),来判断接收的数据是否正确。在发送端,根据要传送的k位二进制码序列,以一定的规则(CRC校验有不同的规则。这个规则,在差错控制理论中称为“生成多项式”。)产生一个校验用的r位校验码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则(即与发送时生成CRC校验码相同的规则)进行检验,校验采用计算机的模二除,即除数和被除数(即生成多项式)做异或运算,进行异或运算时除数和被除数最高位对齐,进行按位异或运算,若最终的数据能被除尽,则传输正确;否则,传输错误。 CRC8即最终生成的CRC校验码为1字节,其生成多项式,生成多项式为g(x)=x8+x5+x4+1,相当于g(x)=1•x8+0•x7+0•x6+1•x5+1•x4+0•x3+0•x2+0•x1+1•x0,即对应的二进制数为100110001。 CRC8校验算法: 1.CRC8校验的一般性算法: 例如: 信息字段代码为: 00000001 00000010 ———— 对应m(x)=x8+x 生成多项式为:g(x)=x8+x5+x4+1 ———— 对应g(x)的二进制代码为:100110001 现在我们将要对2字节数据0x0102生成CRC8校验码,并最终将生成的1字节CRC校验码跟在0x0102的后面,即 0x01 02 ##,(##即8为CRC码),最终生成的3字节数据就是经CRC8校验生成的数据。 先计算x8m(x)=x16+x9,对应的2进制数为:100000010 00000000 。可以看到这样运算所得到的结果其实就是将信息字段代码的数左移8位。因为最终要将生成的8位CRC8校验码附在信息字段的后面,所以要将信息字段的数左移8位。最后用x8m(x)得到的二进制数对生成多项式g(x)进行模二运算,最终的余数(其二进制数的位数一定比生成多项式g(x)的位数小)就是所要的CRC8校验码。 100000010 00000000 ^ 100110001 --------------------------- 000110011 00000000 ^ 100110 001 --------------------------- 010101 00100000 ^ 10011 0001 --------------------------- 00110 00110000 ^ 100 110001 --------------------------- 010 11110100 ^ 10 0110001 --------------------------- 00 10010110 对x8m(x)做模二运算取余得10010110(0x96),这个8位的二进制数就是CRC8校验码。所以,经CRC8校验后研发送的数据就是0x010296。 2.CRC8校验在DS18B20中的应用: 以上分析的是常规的CRC8校验。在DS18B20中,有两处用到CRC。一是DS18B20的8字节的序列号,最后一字节是前面七个字节的CRC码,这是为了保证序列号的唯一性与正确性;另一个是在DS18B20内部9字节的高速温度存储器,其第9字节是前面8个字节的CRC校验码,这是为了温度数据传输的正确性。而在DS18B20中生成CRC码所用到的方不同于常规生成算法,它采用的是逆序CRC信息单元编码算法,该CRC的生成是由DS18B20中的多项式寄存器通过其中所包含的移位寄存器以及异或门对输入该多项式寄存器的每一位二进制数做一定的运算所得到的CRC码(可以查看Maxim官网上DS18B20的应用笔记Note27,专门介绍DS18B20CRC详细生成过程)。在此列举两种DS18B20CRC校验的C程序。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛瑄

文章不错,请博主吃包辣条

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值