1.Design
2.Code
import java.io.IOException;
public class CRC16Checker {
private static int[] index = new int[] { 16, 15, 2, 0 };
private static int[] getBinary(String text) {
StringBuffer num = new StringBuffer();
String s; char ch;
for (int i = 0; i < text.length(); i++) { // Change each char to binary code.
s = Integer.toBinaryString(text.charAt(i));
// If the code is less than 8 bit, make it as 8 bit.
for (int j = 8 - s.length(); j > 0; j--) num.append(0);
num.append(s);
}
int len = num.length();
int[] code = new int[len];
for (int i = 0; i < len; i++) // Change each 0/1 char to int.
code[i] = Character.getNumericValue(num.charAt(i));
return code;
}
private static String toHex(int[] num) {
StringBuffer hex = new StringBuffer(num.length / 4);
char[] ch = new char[4];
for (int i = 0; i < num.length;) {
// Change each 0/1 int to char.
ch[0] = Character.forDigit(num[i++], 2);
ch[1] = Character.forDigit(num[i++], 2);
ch[2] = Character.forDigit(num[i++], 2);
ch[3] = Character.forDigit(num[i++], 2);
// Change each 4-bit-code to hex number.
hex.append(Integer.toHexString(Integer.parseInt(String.valueOf(ch), 2)));
}
return hex.toString();
}
// CRC codes main process
public static int[] makeCRCCodes(int[] sourceCodes, int[] multinomial) {
// The lenght of CRC code is N bits longer than source code. The codes
// from 0 to sourceLength are same as the source. N bits after source
// are the CRC codes. N is decided by the multinomial.
// CRC碼數組總長為原碼長加上校驗碼碼長。數組前部存放原碼。校驗碼存放在數組
// 最後的N位。校驗碼長度決定於生成多項式數組0位置上的元素。
int sourceLength = sourceCodes.length;
int codesLength = sourceLength + multinomial[0];
int[] crcCodes = new int[codesLength];
// Copy source code from 0 to sourceLength. 拷貝原碼。
System.arraycopy(sourceCodes, 0, crcCodes, 0, sourceLength);
int temp, pos;
// Division system. 除法器。
for (int i = 0; i < sourceLength; i++) {
// Count value of the input adding the first register.
// 用第i位原碼和第一個寄存器值模二加。
temp = (crcCodes[sourceLength] + sourceCodes[i]) % 2;
// Move registers forwards from (1, length) to (0, length - 1).
// 第二個寄存器及以後的所有寄存器值前移1位。
System.arraycopy(
crcCodes, sourceLength + 1, crcCodes, sourceLength, multinomial[0] - 1);
// Set the last register with counted value.
// 最後一個寄存器值存放計算好的輸入值。
crcCodes[codesLength - 1] = temp;
// Count other registers. 按生成多項式的值算出位置,模二加出該寄存器的值。
for (int j = index.length - 2; j > 0; j--) {
pos = codesLength - multinomial[j] - 1;
crcCodes[pos] = (crcCodes[pos] + temp) % 2;
}
}
return crcCodes;
}
public static void main(String[] args) throws IOException {
System.out.print("Input hex data :");
StringBuffer buf = new StringBuffer();
char ch = (char) System.in.read();
while (ch != '\r' && ch != '\n') {
buf.append(ch);
ch = (char) System.in.read();
}
// Get binary codes.
int[] b = CRC16Checker.getBinary(buf.toString());
// Make CRC codes.
b = CRC16Checker.makeCRCCodes(b, CRC16Checker.index);
// Output code as binary number.
for (int i = 0; i < b.length;) {
for (int j = 0; j < 4; j++, i++) System.out.print(b[i]);
System.out.print(' ');
}
System.out.println();
// Output code as hex number.
System.out.println("The CRC16 code is :" + CRC16Checker.toHex(b));
}
}
3. Test report :
Case : A (ASCII = 41)
Result : 410186
CRC bits : 0168 (0000 0001 1000 0110)
Run program :
Input hex data :A
0100 0001 0000 0001 1000 0110
The CRC16 code is :410186
Case : CRC16TEST (ASCII = 43 52 43 31 36 54 45 53 54)
Result : 455243313654455354fb66
CRC bits : fb66 (1111 1011 0110 0110)
Run program :
Input hex data :CRC16TEST
0100 0011 0101 0010 0100 0011 0011 0001 0011 0110 0101 0100 0100 0101 0101 0011 0101 0100 1111 1011 0110 0110
The CRC16 code is :435243313654455354fb66
Case : 5k (ASCII = 35 6b)
Result : 356b3f79
CRC bits : 3f79 (0011 1111 0111 1001)
Run program :
Input hex data :5k
0011 0101 0110 1011 0011 1111 0111 1001
The CRC16 code is :356b3f79