[解決済み] CRC16チェックサムを計算する関数
質問内容
RS232またはRS485接続でシンプルで信頼性の高い通信を行うためのライブラリに取り組んでいます。 このコードの一部には、回線ノイズによる破損を検出するために、データのCRC16チェックサムを使用することが含まれています。 CRC16チェックサムを計算する関数を作成しましたが、正しい値が出力されないようです。
私が書いた関連するコードは以下の通りです(以下も参照できます)。 こちら ).
#include <stdint.h>
#define CRC16 0x8005
uint16_t gen_crc16(const uint8_t *data, uint16_t size)
{
uint16_t out = 0;
int bits_read = 0, bit_flag;
/* Sanity check: */
if(data == NULL)
return 0;
while(size > 0)
{
bit_flag = out >> 15;
/* Get next bit: */
out <<= 1;
out |= (*data >> (7 - bits_read)) & 1;
/* Increment bit counter: */
bits_read++;
if(bits_read > 7)
{
bits_read = 0;
data++;
size--;
}
/* Cycle check: */
if(bit_flag)
out ^= CRC16;
}
return out;
}
出力したものを照合している このオンラインCRC計算機 .
CRC16の計算方法についての私の理解が誤っているか、オンラインの計算機が誤っているかのどちらかであるという結論に達しました(前者の方が可能性が高そうです)。 どなたか、私がどこで間違っているのか、教えていただけませんか?
解決方法は?
同じ多項式を使用しても、データビットの処理方法、CRCの特定の初期値(0であったり、0xffffであったり)の使用、CRCのビットの反転などの細かい違いによって結果が異なる場合があります。例えば、ある実装ではデータバイトの下位ビットから順に処理し、ある実装では上位ビットから順に処理します(現在のあなたの実装と同じです)。
また、すべてのデータビットを通過させた後、CRCの最後のビットを「プッシュアウト」する必要があります。
CRCアルゴリズムはハードウェアで実装されるように設計されているため、ビット順序の処理方法はソフトウェアの観点からはあまり意味をなさない場合があることを覚えておいてください。
lammertbies.nl CRC計算機のページにあるようにCRC16を多項式0x8005で照合したい場合、CRC関数に以下の変更をする必要があります。
- a) データビットを最上位ビットからではなく、最下位ビットからCRCループに通す。
- b) 入力データ終了後、CRCの最後の16ビットをCRCレジスタから押し出す。
- c) CRCビットを反転させる(このビットはハードウェア実装からのキャリーオーバーだと思われます)
つまり、関数は次のようになります。
#define CRC16 0x8005
uint16_t gen_crc16(const uint8_t *data, uint16_t size)
{
uint16_t out = 0;
int bits_read = 0, bit_flag;
/* Sanity check: */
if(data == NULL)
return 0;
while(size > 0)
{
bit_flag = out >> 15;
/* Get next bit: */
out <<= 1;
out |= (*data >> bits_read) & 1; // item a) work from the least significant bits
/* Increment bit counter: */
bits_read++;
if(bits_read > 7)
{
bits_read = 0;
data++;
size--;
}
/* Cycle check: */
if(bit_flag)
out ^= CRC16;
}
// item b) "push out" the last 16 bits
int i;
for (i = 0; i < 16; ++i) {
bit_flag = out >> 15;
out <<= 1;
if(bit_flag)
out ^= CRC16;
}
// item c) reverse the bits
uint16_t crc = 0;
i = 0x8000;
int j = 0x0001;
for (; i != 0; i >>=1, j <<= 1) {
if (i & out) crc |= j;
}
return crc;
}
その関数は
0xbb3d
を渡すと、私の場合は
"123456789"
.
関連
-
[解決済み】stdinとSTDIN_FILENOの違いは何ですか?
-
[解決済み】変数の警告が設定されているが使用されていない
-
[解決済み】 strcpyとstrdupの比較
-
[解決済み] テスト
-
[解決済み】「構造体でもユニオンでもないものにメンバー'*******'を要求する」とはどういう意味ですか?
-
[解決済み】宣言指定子で2つ以上のデータ型がある場合のエラー【非公開
-
[解決済み】エラー:呼び出されたオブジェクトは、関数または関数ポインタではない
-
[解決済み] エラー: `itoa` はこのスコープで宣言されていません。
-
[解決済み】C言語でpow( )への未定義参照、math.hを含むにもかかわらず【重複】。
-
[解決済み】C言語の関数ポインタはどのように機能するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Valgrind - strcpyのサイズ1の無効な書き込み
-
[解決済み] clang: error: linker command failed with exit code 1が表示されるのはなぜですか?
-
[解決済み】警告。この関数ではXが初期化されていない状態で使用される可能性があります。
-
[解決済み】「構造体でもユニオンでもないものにメンバー'*******'を要求する」とはどういう意味ですか?
-
[解決済み] [Solved] なぜこのようなエラーが発生するのでしょうか。「データ定義に型またはストレージクラスがない」?
-
[解決済み】 「配列のイニシャライザーはイニシャライザーリストまたは文字列リテラルでなければなりません」と表示されるのですが?
-
[解決済み】C言語でint64_t型を表示する方法
-
[解決済み] エラー:整数が期待されるところで集約値が使用された
-
[解決済み】int型配列へのポインタのスカラ・イニシャライザの過剰要素
-
[解決済み】.axfファイルとは何ですか?