1

デバイスからGPRSを介して受信しているAvlパケットがあります。

プロトコルマニュアルによると、パケットの最後の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番号を取得し、パケットを保存したByte配列に対してgetCrc16を呼び出して、2つの番号を比較します。

プログラム内で使用するコードは次のとおりです。

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ループは最後の各バイトを受け取り、toBinaryString()を使用して、それらすべてをバイナリ形式で文字列に結合します!したがって、0000000000000000101011011101001のようなものが得られます(マニュアルには、最初の2バイトは16ビットCRCであるため、常にゼロであると記載されています)

したがって、バイナリ文字列を符号付き整数に解析し、2つのCRCを比較します...!

それでも私は次のような結果を得る:

計算されたCRC=21395-----受信されたCRC=30416

また

計算されたCRC=56084-----受信されたCRC=10504

私は多くのパケットでテストしましたが、すべてのパケットでデータが失われることはありません。また、データも解析しているので、取得したデータが正しいことがわかります。

私はこれすべてに何が欠けていますか?

4

3 に答える 3

0

問題が解決しました!

問題は、データ部分に入る前に、パケットに 8 つの他のバイトがあることでした! そのため、CRC を計算する前に、送信された CRC の最初の 8 バイトと最後の 4 バイトを除外する必要がありました。

getCrc16 関数の for ループが i=8 から始まることを除いて、数字は一致し、上記のコードは正しいです (データ部分に属さないパケットの最初の 8 バイトをスキップするため!)

ありがとうございました!

于 2012-09-25T10:28:00.833 に答える
0

したがって、パケットが送信するCRC番号を取得し、パケットを格納したバイト配列に対してgetCrc16を呼び出して、2つの数値を比較しますよね??

違う。CRC バイトを含むメッセージ全体で CRC を計算すると、結果はゼロになるはずです。

于 2012-09-25T01:54:55.883 に答える
0

ドキュメントの文言 (またはそれに対するあなたの理解) に問題がある可能性があります。パケットに 16 ビットの CRC がある場合、4バイト(バイナリ形式)ではなく2バイトを占有する可能性が最も高くなります。10 進数の場合、4 バイトでも十分ではありません (符号なし 10 進文字列として格納するには、5 桁が必要です)。

あなたのコードは、変換を行っていることを示しています (ただし、どのような種類の変換を行うべきかはわかりません):

BinaryRecievedCRC+= toBinaryString(AvlPacket[index]);

CRC はバイナリ形式でデータに格納されることを期待しているので、把握する必要があるのは、どのエンディアンが使用され、CRC がデータのどこに格納されているかだけだと思います。

編集:あなたのコメントから判断すると、次のようにCRCを抽出する必要があります:

public int getCRC(byte[] data, int index) {
    return ((data[index] & 0xFF) << 8)) | (data[index + 1] & 0xFF);
}
于 2012-09-24T13:28:36.707 に答える