3

ファームウェアの更新のために CRC16 チェックサムを作成する必要があります。このデータを送信すると (16 進文字列からバイト [] に変換されます)

020000810000120000000002F001128100000C9462050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C94941050C

コントローラーから次のCRC16を取得します

-17514

Javaでこれを確認しようとしましたが、同じ値を取得できません。

これは、C の元の関数です。

static uint16_t crc16_update(uint16_t crc, uint8_t a)
{
  crc ^= a;
  for (unsigned i = 0; i < 8; ++i) {
    if (crc & 1)
      crc = (crc >> 1) ^ 0xA001;
    else
      crc = (crc >> 1);
  }
  return crc;
}


static uint16_t crc16(const uint8_t *b, size_t l)
{
  uint16_t crc = 0;
  while (l-- > 0)
    crc = crc16_update(crc, *b++);
  return crc;
}

これはJavaで変換された関数です:

public static int crc16_update(int crc, int a) {
    crc ^= a;
    for (int i = 0; i < 8; ++i) {
        if ((crc & 1) != 0) {
            crc = (crc >> 1) ^ 0xA001;
        } else {
            crc = (crc << 1);
        }
    }
    return crc;
}

public static int crc16(byte[] bytes) {
    int crc = 0;
    for (byte b:bytes) {
        crc = crc16_update(crc, b);
    }
    return crc;
}

...しかし、うまくいきません。どうしたの?

4

4 に答える 4

1
public static int crc16_update(int crc, int a) {
    crc ^= a;
    for (int i = 0; i < 8; ++i) {
        if ((crc & 1) != 0) {
            crc = (crc >> 1) ^ 0xA001;
        } else {
            crc = (crc << 1);

looper で述べたよう>> 1、C コードにaがあります。

        }
    }
    return crc;
}

次に、他の関数について説明します。

public static int crc16(byte[] bytes) {
    int crc = 0;
    for (byte b:bytes) {
        crc = crc16_update(crc, b);

crc16_updateintJava では 2 番目の引数としてuint8_t、C では a を受け取ります。バイトにb最上位/符号ビットが設定されている場合、値は負であるためint、引数として に変換するとcrc16_update、符号拡張され、多くの 1- が得られます。 C にはないビット。

最下位の 8 以外のすべてのビットをマスクする必要があります。

crc16_update(crc, ((int)b) & 0xFF);
于 2012-11-23T13:38:51.797 に答える
0

>>>演算子を使用してみてください。

Javaでは、これは符号>>を保持するのとは対照的に、符号なしシフト演算子です。

また、Javauint16_tの場合と同様に、これは16ビット型であることに注意してください。shortビットレベルで機能するアルゴリズムを書き直すときは、適切なビット長を使用するようにしてください。

于 2012-11-23T12:50:03.817 に答える
0

問題は、整数が Java で署名されていることではありませんが、間違ったデータ型を使用していることです。int32ビットで、使用するアルゴリズムは型のデータサイズに敏感です。short16 ビットとbyte8 ビットで使用します。

>>>@Anony-Mousse で言及されているように、必要に応じても使用します。

于 2012-11-23T12:52:21.490 に答える
0

私は正しい方法を見つけました。今、それはうまくいきます!問題は、インターンが short と int の間で変換したことだと思います。

public static int crc16_update(int crc, byte a) {
    crc ^= ((a+128) & 0xff);
    for (int i = 0; i < 8; ++i) {
        if ((crc & 1) != 0) {
            crc = ((crc >>> 1) ^ 0xA001) & 0xffff;
        }
        else {
            crc = (crc >>> 1) & 0xffff;
        }
    }
    return crc;
}

public static short crc16(byte[] bytes) {
    int crc = 0;
    for (byte b : bytes) {
        crc = crc16_update(crc, b);
    }
    return (short) crc;
}
于 2012-11-24T11:42:00.643 に答える