Principle of CRC16 and implementation in Java

7 minute read

校验方式详解

校验方式 多项式 初始值 前/后 异或值
CRC16_CCITT x16+x12+x5+1(0x1021) 0x0000 低/高 0x0000
CRC16_CCITT_FALSE x16+x12+x5+1(0x1021) 0xFFFF 高/低 0x0000
CRC16_XMODEM x16+x12+x5+1(0x1021) 0x0000 高/低 0x0000
CRC16_X25 x16+x12+x5+1(0x1021) 0xFFFF 低/高 0xFFFF
CRC16_MODBUS x16+x15+x2+1(0x8005) 0xFFFF 低/高 0x0000
CRC16_IBM x16+x15+x2+1(0x8005) 0x0000 低/高 0x0000
CRC16_MAXIM x16+x15+x2+1(0x8005) 0x0000 低/高 0xFFFF
CRC16_USB x16+x15+x2+1(0x8005) 0xFFFF 低/高 0xFFFF
CRC16_DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1(0x3D65) 0x0000 低/高 0xFFFF

校验原理和步骤

  1. 预置1个16位的寄存器为十六进制FFFF(即全为1),称此寄存器为CRC寄存器;
  2. 把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器,高八位数据不变;
  3. 把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位;
  4. 如果移出位为0:重复第3步(再次右移一位);如果移出位为1,CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;
  5. 重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;
  6. 重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;
  7. 将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换;
  8. 最后得到的CRC寄存器内容即为:CRC码。
  • 以上计算步骤中的多项式 0xA001 是 0x8005 按位颠倒后的结果。
  • 0x8408 是 0x1021 按位颠倒后的结果。

Java 实现

  1/**
  2 * Author:boxla
  3 * Time:2019/09/11 16:09
  4 */
  5public class CRC16 {
  6 
  7    /**
  8     * @param buffer
  9     * @return
 10     */
 11    public static int CRC16_CCITT(byte[] buffer) {
 12        int wCRCin = 0x0000;
 13        int wCPoly = 0x8408;
 14        for (byte b : buffer) {
 15            wCRCin ^= ((int) b & 0x00ff);
 16            for (int j = 0; j < 8; j++) {
 17                if ((wCRCin & 0x0001) != 0) {
 18                    wCRCin >>= 1;
 19                    wCRCin ^= wCPoly;
 20                } else {
 21                    wCRCin >>= 1;
 22                }
 23            }
 24        }
 25        return wCRCin ^= 0x0000;
 26 
 27    }
 28 
 29    /**
 30     * @param buffer
 31     * @return
 32     */
 33    public static int CRC16_CCITT_FALSE(byte[] buffer) {
 34        int wCRCin = 0xffff;
 35        int wCPoly = 0x1021;
 36        for (byte b : buffer) {
 37            for (int i = 0; i < 8; i++) {
 38                boolean bit = ((b >> (7 - i) & 1) == 1);
 39                boolean c15 = ((wCRCin >> 15 & 1) == 1);
 40                wCRCin <<= 1;
 41                if (c15 ^ bit)
 42                    wCRCin ^= wCPoly;
 43            }
 44        }
 45        wCRCin &= 0xffff;
 46        return wCRCin ^= 0x0000;
 47    }
 48 
 49    /**
 50     * @param buffer
 51     * @return
 52     */
 53    public static int CRC16_XMODEM(byte[] buffer) {
 54        int wCRCin = 0x0000;
 55        int wCPoly = 0x1021;
 56        for (byte b : buffer) {
 57            for (int i = 0; i < 8; i++) {
 58                boolean bit = ((b >> (7 - i) & 1) == 1);
 59                boolean c15 = ((wCRCin >> 15 & 1) == 1);
 60                wCRCin <<= 1;
 61                if (c15 ^ bit)
 62                    wCRCin ^= wCPoly;
 63            }
 64        }
 65        wCRCin &= 0xffff;
 66        return wCRCin ^= 0x0000;
 67    }
 68 
 69 
 70    /**
 71     * @param buffer
 72     * @return
 73     */
 74    public static int CRC16_X25(byte[] buffer) {
 75        int wCRCin = 0xffff;
 76        int wCPoly = 0x8408;
 77        for (byte b : buffer) {
 78            wCRCin ^= ((int) b & 0x00ff);
 79            for (int j = 0; j < 8; j++) {
 80                if ((wCRCin & 0x0001) != 0) {
 81                    wCRCin >>= 1;
 82                    wCRCin ^= wCPoly;
 83                } else {
 84                    wCRCin >>= 1;
 85                }
 86            }
 87        }
 88        return wCRCin ^= 0xffff;
 89    }
 90 
 91    /**
 92     * @param buffer
 93     * @return
 94     */
 95    public static int CRC16_MODBUS(byte[] buffer) {
 96        int wCRCin = 0xffff;
 97        int POLYNOMIAL = 0xa001;
 98        for (byte b : buffer) {
 99            wCRCin ^= ((int) b & 0x00ff);
100            for (int j = 0; j < 8; j++) {
101                if ((wCRCin & 0x0001) != 0) {
102                    wCRCin >>= 1;
103                    wCRCin ^= POLYNOMIAL;
104                } else {
105                    wCRCin >>= 1;
106                }
107            }
108        }
109        return wCRCin ^= 0x0000;
110    }
111 
112    /**
113     * @param buffer
114     * @return
115     */
116    public static int CRC16_IBM(byte[] buffer) {
117        int wCRCin = 0x0000;
118        int wCPoly = 0xa001;
119        for (byte b : buffer) {
120            wCRCin ^= ((int) b & 0x00ff);
121            for (int j = 0; j < 8; j++) {
122                if ((wCRCin & 0x0001) != 0) {
123                    wCRCin >>= 1;
124                    wCRCin ^= wCPoly;
125                } else {
126                    wCRCin >>= 1;
127                }
128            }
129        }
130        return wCRCin ^= 0x0000;
131    }
132 
133    /**
134     * @param buffer
135     * @return
136     */
137    public static int CRC16_MAXIM(byte[] buffer) {
138        int wCRCin = 0x0000;
139        int wCPoly = 0xa001;
140        for (byte b : buffer) {
141            wCRCin ^= ((int) b & 0x00ff);
142            for (int j = 0; j < 8; j++) {
143                if ((wCRCin & 0x0001) != 0) {
144                    wCRCin >>= 1;
145                    wCRCin ^= wCPoly;
146                } else {
147                    wCRCin >>= 1;
148                }
149            }
150        }
151        return wCRCin ^= 0xffff;
152    }
153 
154    /**
155     * @param buffer
156     * @return
157     */
158    public static int CRC16_USB(byte[] buffer) {
159        int wCRCin = 0xFFFF;
160        int wCPoly = 0xa001;
161        for (byte b : buffer) {
162            wCRCin ^= ((int) b & 0x00ff);
163            for (int j = 0; j < 8; j++) {
164                if ((wCRCin & 0x0001) != 0) {
165                    wCRCin >>= 1;
166                    wCRCin ^= wCPoly;
167                } else {
168                    wCRCin >>= 1;
169                }
170            }
171        }
172        return wCRCin ^= 0xffff;
173    }
174 
175    /**
176     * @param buffer
177     * @return
178     */
179    public static int CRC16_DNP(byte[] buffer) {
180        int wCRCin = 0x0000;
181        int wCPoly = 0xA6BC;
182        for (byte b : buffer) {
183            wCRCin ^= ((int) b & 0x00ff);
184            for (int j = 0; j < 8; j++) {
185                if ((wCRCin & 0x0001) != 0) {
186                    wCRCin >>= 1;
187                    wCRCin ^= wCPoly;
188                } else {
189                    wCRCin >>= 1;
190                }
191            }
192        }
193        return wCRCin ^= 0xffff;
194    }
195}

相关资料

在线 CRC 校验工具