4

次のように記述されたメッセージのチェックサムを作成する手順があります。

チェックサムは、「メッセージ タイプ」ワードからメッセージ ブロックの最後までのすべてのバイトの 2 の補数の合計に等しい 1 バイトで構成されます (送信されたチェックサムを除く)。最上位ビットからのキャリーは無視されます。

私が見つけた別の説明は次のとおりです。 チェックサム値には、データ メッセージ内の他の単語 (つまり、メッセージ タイプ、メッセージ長、およびデータ ワード) のモジュロ 256 合計の 2 の補数が含まれます。受信機器は、受信した単語のモジュロ 256 和を計算し、この和を受信したチェックサム ワードに追加することができます。ゼロの結果は、通常、メッセージが正しく受信されたことを示します。

これは、メッセージ (チェックサムを除く) のすべてのバイトの値を合計し、この数値の modulo 256 を取得することを意味すると理解しています。この数値の 2 の補数を取得します。これが私のチェックサムです。

しかし、メッセージの例に問題があります(設計ドキュメントからのものなので、正しくエンコードされていると想定する必要があります)。

unsigned char arr[] = {0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30,0x2,0x8,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe};

したがって、最後のバイト 0xE はチェックサムです。チェックサムを計算する私のコードは次のとおりです。

bool isMsgValid(unsigned char arr[], int len) {
   int sum = 0;
   for(int i = 0; i < (len-1); ++i) {
      sum += arr[i];
   }
   //modulo 256 sum
   sum %= 256;

   char ch = sum;

   //twos complement
   unsigned char twoscompl = ~ch + 1;

   return arr[len-1] == twoscompl;
}


int main(int argc, char* argv[])
{
   unsigned char arr[] = {0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30,0x2,0x8,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe};
   int arrsize = sizeof(arr) / sizeof(arr[0]);

   bool ret = isMsgValid(arr, arrsize);

   return 0;
}

仕様はこちら:= http://www.sinet.bt.com/227v3p5.pdf

必要なアルゴリズムを誤解していると思います。このチェックサムを作成する方法はありますか?

Flippin 仕様の作成者は、データ例で間違いを犯しました。これを見つけてここに戻ってきて、他の人も見つけました。お時間を無駄にしてしまい申し訳ありません。私のコードを改善するための有用なコメントのように見えるので、私は応答を研究します。

4

3 に答える 3

6

リンクした pdf からサンプル メッセージを誤ってコピーしました。2 番目のパラメーターの長さは 9 バイトですが、コードで 0x08 を使用しました。

このドキュメントでは、パラメーターに実際には 9 バイトがあるのに、3 列目に「8 バイト」と誤って記載されています。2 番目の列には、正しく「00001001」と記載されています。

つまり、テスト メッセージは次のようになります。

{0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30, // param1
 0x2,0x9,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe}  // param2
     ^^^

ret == trueあなたのプログラムを試してみると、正しいメッセージ配列が表示されます。

于 2012-09-02T18:56:46.953 に答える
1

コメントに同意: チェックサムが間違っているようです。このデータは .PDF のどこにありますか?

一般的なヒント:

符号なし型をアキュムレータとして使用します。これにより、オーバーフロー時に明確に定義された動作が得られます。長いメッセージにはそれが必要になります。同様に、結果を char 変数に格納する場合は、unsigned char にします。

ただし、保存する必要はありません。符号なしの型で計算を行い、結果を補数し、1 を加算し、上位ビットをマスクして 8 ビットの結果を得るだけです。

また、2 の補数演算を使用するハードウェアを使用している場合は、ここにトリックがあります。チェックサムを含むすべての値を加算し、上位ビットをマスクします。入力が正しい場合、結果は 0 になります。

于 2012-09-02T18:49:07.377 に答える
1

受信機器は、受信した単語のモジュロ 256 和を計算し、この和を受信したチェックサム ワードに追加することができます。

チェックサムを理解するには、この条件を使用する方がはるかに簡単です。

{byte 0} + {byte 1} + ... + {last byte} + {checksum} = 0    mod 256
{checksum} = -( {byte 0} + {byte 1} + ... + {last byte} )   mod 256

他の人が言ったように、個々のビットを操作するときは、実際には符号なしの型を使用する必要があります。これは、剰余演算を行う場合にも当てはまります。符号付きの型を使用すると、かなり多くの符号関連の間違いにさらされることになります。OTOH、符号なしの数字を使用して自分自身を開いているほとんどの唯一の間違い2u-3uは、正の数を忘れているようなものです。

(符号付きの数値と符号なしの数値を一緒に混合することに注意してください。これには多くの微妙な点も含まれます)

于 2012-09-02T18:59:50.153 に答える