CRC查表法——表的由來及Java實現CRC8校驗演算法
你也可以檢視我的其他同類文章,也會讓你有一定的收貨!
大概思路
我先說一下查表法,表的計算方法,以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的表格
索引 | 資料 | 表值 |
---|---|---|
0 | 0000 | 0000 |
1 | 0001 | 0011 |
2 | 0010 | 0110 |
3 | 0011 | 0101 |
4 | 0100 | 1100 |
5 | 0101 | 1111 |
6 | 0110 | 1010 |
7 | 0111 | 1001 |
8 | 1000 | 1011 |
9 | 1001 | 1000 |
10 | 1010 | 1101 |
11 | 1011 | 1110 |
12 | 1100 | 0111 |
13 | 1101 | 0100 |
14 | 1110 | 0001 |
15 | 1111 | 0010 |
用查表法計算之前的例子:
——————————————
A 0 0 1 1 1 1 1 0
0 1 0 1 表中查詢資料0011對應的表值為0101
——————
1 0 1 1
Java實現CRC8校驗——查表法
/**
* 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));
}
}
關注我的公眾號,輕鬆瞭解和學習更多技術