算法的要求是如下:
① 装一个16 位寄存器,所有数位均为1。
② 取被校验串的一个字节与16 位寄存器的高位字节进行“异或”运算。运算结果放
入这个16 位寄存器。
③ 把这个16 寄存器向右移一位。
④ 若向右(标记位)移出的数位是1,则生成多项式1010 0000 0000 0001 和这个寄
存器进行“异或”运算;若向右移出的数位是0,则返回③。
⑤ 重复③和④,直至移出8 位。
⑥ 取被校验串的下一个字节
⑦ 重复③~⑥,直至被校验串的所有字节均与16 位寄存器进行“异或”运算,并移位
8 次。
⑧ 这个16 位寄存器的内容即2 字节CRC 错误校验码。
校验码按照先高字节后低字节的顺序存放。
我自己理解实现了下:
public static short crc16(byte[] data) {
short crc = (short) 0xFFFF;
short dxs = (short) 0xA001;
byte tc;
byte sbit;
for (int i = 0; i < data.length; i++) {
tc = (byte) ((crc & 0xff00) >> 8);
crc = (short) (tc ^ data[i]);
for (int r = 0; r < 8; r++) {
sbit = (byte) (crc & 0x01);
crc = (short) (crc >> 1);
if (sbit != 0)
crc = (short) (crc ^ dxs);
}
}
System.out.println(bytesToHexString(new byte[] {
(byte) ((crc & 0xff00) >> 8), (byte) (crc & 0xff) }));
return crc;
}
//将字节数组按16进制输出
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (stringBuilder.length() != 0) {
stringBuilder.append(",");
}
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
可是我计算出的接口和文档上对不上,不知道哪里有问题?
改成这样就行了,因为java里面没有无符号整数,可以用长一点的整数来避免变成负数的问题。
public static short calcCrc16(byte[] data) {
int crc = 0xffff;
int dxs = 0xa001;
int hibyte;
int sbit;
for (int i = 0; i < data.length; i++) {
hibyte = crc >> 8;
crc = hibyte ^ data[i];
for(int j=0; j<8; j++) {
sbit = crc & 0x0001;
crc = crc >> 1;
if(sbit == 1)
crc ^= dxs;
}
}
return (short)(crc & 0xffff);
}