我有一个Avl数据包,我通过GPRS从设备接收。
协议手册说该数据包在最后4个字节上有一个16位CRC,并给出了CRC计算的源代码:
public static int getCrc16(Byte[] buffer) {
return getCrc16(buffer, 0, buffer.length, 0xA001, 0);
}
public synchronized static int getCrc16(Byte[] buffer, int offset, int bufLen, int polynom, int preset) {
preset &= 0xFFFF;
polynom &= 0xFFFF;
int crc = preset;
for (int i = 0; i < bufLen; i++) {
int data = buffer[i + offset] & 0xFF;
crc ^= data;
for (int j = 0; j < 8; j++) {
if ((crc & 0x0001) != 0) {
crc = (crc >> 1) ^ polynom;
} else {
crc = crc >> 1;
}
}
}
return crc & 0xFFFF;
}
所以我得到数据包发送给我的CRC编号,然后我调用getCrc16作为Byte数组,我已经存储了数据包,然后比较这两个数字吧?
以下是我在程序中使用的代码:
public static String toBinaryString(byte n) {
StringBuilder sb = new StringBuilder("00000000");
for (int bit = 0; bit < 8; bit++) {
if (((n >> bit) & 1) > 0) {
sb.setCharAt(7 - bit, '1');
}
}
return sb.toString();
}
int CalculatedCRC = getCrc16(AvlPacket);
System.out.println("Calculated CRC= " + CalculatedCRC);
int index = (AvlPacket.length)-4;
String BinaryRecievedCRC = "";
for (int j = 0; j < 4; j++) {
BinaryRecievedCRC+= toBinaryString(AvlPacket[index]);
index+=1;
}
int RecievedCRC = Integer.parseInt(BinaryRecievedCRC, 2);
System.out.println("Recieved CRC= " + RecievedCRC);
toBinaryString()将一个字节转换为它的二进制文件并将其放入一个字符串中!
所以我通过手册中给出的getCrc16()来计算CRC。然后在数据包结束前取4个字节的索引,这样我就可以读取最后4个字节并获得随数据包发送的CRC!
for循环获取每个最后一个字节,并且withBinaryString()将所有它们以二进制形式组合成一个String!所以我得到类似0000000000000000101011011101001(手册指出前两个字节总是零,因为它是一个16位CRC )
所以我只是将Binary String解析为signed int并比较两个CRC ......!
然而我得到的结果如下:
计算的CRC = 21395 -----收到的CRC = 30416
或
计算的CRC = 56084 -----收到的CRC = 10504
我已经测试了很多数据包,并且它们不能全部丢失数据......我也在解析数据所以我知道我得到的数据是正确的!
我在这一切中缺少什么?
答案 0 :(得分:0)
文档措辞可能有问题(或者你对它的理解)。如果数据包中存在16位CRC,则最有可能占用两个字节,而不是四(以二进制形式)。如果它是一个小数,即使四个字节也不够(你需要5个didgts来存储它作为无符号十进制字符串)。
您的代码显示您进行了转换(但我无法看到它应该执行的转换类型):
BinaryRecievedCRC+= toBinaryString(AvlPacket[index]);
我希望CRC能够以二进制形式存储在数据中,所以我假设您唯一需要弄清楚的是使用了哪个字节顺序以及CRC存储在数据中的位置。
编辑:根据您的评论判断,您需要像这样提取CRC:
public int getCRC(byte[] data, int index) {
return ((data[index] & 0xFF) << 8)) | (data[index + 1] & 0xFF);
}
答案 1 :(得分:0)
所以我得到数据包发给我的CRC号,然后我调用getCrc16 我已经存储数据包然后比较的字节数组 两个号码对吧?
错误。您计算整个消息的CRC,包括CRC字节,结果应为零。
答案 2 :(得分:0)
解决了问题!
问题是数据包在进入数据部分之前有8个其他字节! 所以在计算CRC之前,我必须排除前8个字节以及发送CRC的最后4个字节!
现在数字一致并且上面的代码是正确的,除了getCrc16函数中的for循环从i = 8开始(以便跳过不属于Data部分的数据包的前8个字节! )
谢谢大家的时间!