2017-01-26 11 views
1

私は、マイクロコントローラのファームウェアを更新するためにブートローダーと通信するプログラムを作成しています。 CRC calculation以外はすべて準備ができています。CRC16-CCITT結果が正しくありませんか?

hereのCRC計算機能を使用して、多項式x16 + x12 + x5 + 1(0b10001000000100001)のCRC16を計算しました。

しかし、入力0x3304000の結果は間違っています。私はこれを確認しましたwebsite。また、私はCで複製しているpythonスクリプトでダブルチェックしました。 PythonスクリプトはCRCを正しく計算します。

uint16_t crc16(uint8_t *data_p, unsigned length) 
{ 
    unsigned char i; 
    unsigned int data; 
    unsigned int crc = 0xffff; 

    if (length == 0) 
     return (~crc); 

    do 
    { 
     for (i=0, data=(unsigned int)0xff & *data_p++; 
      i < 8; 
      i++, data >>= 1) 
     { 
       if ((crc & 0x0001)^(data & 0x0001)) 
        crc = (crc >> 1)^POLY; 
       else crc >>= 1; 
     } 
    } while (--length); 

    crc = ~crc; 
    data = crc; 
    crc = (crc << 8) | (data >> 8 & 0xff); 

    return (crc); 
} 
+0

私はエンディアンを責めます。 –

+0

私は 'uint8_t'配列を渡しています。私は、エンディアンは問題ではないはずです。 – abhiarora

+0

ウェブサイトがCRC16-CCITTを使用していることをどのように知っていますか? –

答えて

3

は、私はあなたがリンク先のWebサイトでのアルゴリズムで掲示Cコードを比較してきた、と私は2つの主な違いを見つけた:あなたがプロセスに逆の順序でビットを掲載

1)Cコードウェブサイトのこれは、CRC計算自体(Webサイトが左にシフトする右シフト)と、入力の各バイトの処理(Webサイトが最上位ビットを最初に処理する最下位ビットを最初に処理する)の両方に当てはまります。

2)Cコードは、返される前にCRC値のすべてのビットを反転し、下位バイトと上位バイトをスワップします。ウェブサイトのアルゴリズムには、そのような後処理は含まれていません。

uint16_t crc16(const uint8_t *data_p, unsigned length) 
{ 
    unsigned char i; 
    uint8_t data; 
    unsigned int crc = 0; // 0xffff; 

    while (length-- > 0) 
    { 
    for (i = 0, data = *data_p++; 
     i < 8; 
     i++, data <<= 1) 
    { 
     if ((crc >> 15)^(data >> 7)) 
     crc = (crc << 1)^POLY; 
     else 
     crc <<= 1; 

     crc &= 0xffff; 
    } 
    } 

    return crc; 
} 

違い:

1)dataローカル変数は、現在のタイプuint8_tである

私はあなたのウェブサイトに一致するように貼り付けたCコードを更新しました。

2)crc変数は、@AShellyのように、0xFFFFの代わりに0に初期化されます。 Webサイトでは、計算を開始する前にすべてのレジスタを0に初期化すると具体的に言及しています。

3)別に長さ0をテストするのではなく、ループを 'do'ループから 'while'ループに再構成したので、 'length 4)forループでは、dataは右ではなく左にシフトします。これは、ビットを最初にビットを処理し、次にそのビットを右に処理するなどです。左シフトは、後続の各ビットを上位ビット位置に移動します。入力の新しいビットでキャリーを組み合わせ

5)ifステートメントは、現在の代わりにそれぞれの下位ビットのデータ(data >> 7)の高いビットとCRC(crc >> 15)の上位ビットを比較しています。コードの残りの部分は、crcが16番目の位置にビットを持たず、dataが8番目の位置にビットを持たないことが保証されているため、これらのシフトは1ビットのみを保証します。

6)実際のcrcの計算は、右ではなく左にシフトします。

7)crcを左にシフトした後、16番地のビットをマスクします。これは、ポイント4で言及されたコードの一部であり、crc >> 15が単一ビットのみを生成することを保証する。 (crcuint16_tとすることによっても可能です)

8)後処理コードが削除されます。ループが完了すると、最後のcrc値がそのまま返されます。

これらの変更により、C関数によって生成されたCRCがWebサイトと一致します。

+2

良い答えですが、 "downto"演算子を使用する機会を逃した: 'while(length - > 0)' – AShelly

+0

あなたの答えをありがとう。それは期待どおりに動作します。私はまた、そのウェブサイトが実装しているものに一致しようとしましたが、私はいくつかを逃したと思います。素晴らしい答え。百万のアップホーンに値する – abhiarora

1

CRC-16は、それが初期化子と多項式に依存し、独自の仕様ではありません。ここで

は、ウェブサイトからのコードです。私は疑いがあります 0xFFFF あなたが使用しているウェブサイトは 0x0000を初期設定として使用しています。

過去の仕事では、いくつかの既知の入力についてウェブサイトの結果を最初に検証した後、実装を検証するためにthis websiteを使用しました。

+0

はい、私は自分のアルゴリズムを見て、私のプログラムで0x0000初期化子を使用しようとしましたが、それは助けになりませんでした – abhiarora

関連する問題