2021/12/14

C#でCRCを計算する


CRCとはCyclic Redundancy Checkの略で、通信データの破損検出の仕組みの一つです。

通信データをある値(生成多項式)で割り算して、余りをデータに付与して送信します。
受信側で再度計算して付与された余りが合っているかどうか確認し、合致しない場合は通信データ破損とみなします。

同じような誤り検出にチェックサムがありますが、チェックサムはデータを足し算した結果を付与します。
足し算よりは割り算の方が複雑なアルゴリズムとなり、その分信頼度は向上します。

Modbus通信やイーサネット通信などで使われているようです。

CRCの種類

CRCには以下のパラメータがあり、これらの値により計算値が異なってきます。
そのため、CRCと一言で言ってもたくさんの種類が存在しています。


例) CRC-16-IBM

その他の種類については wikipediaに記述がありますので参照ください。

CRCの計算方法

CRCの計算方法は、「ビット演算方式」と「テーブル演算方式」があります。


以降は、CRC-16-IBMのビット演算方式の計算をC#で実施してみます。
(Modbus-RTUで使われているものです)

計算コード

//CRC計算(CRC16-IBM / 生成多項式:x16+x15+x2+1, initial value is 0xFFFF, 右回り)
int[] DATA;
int CRC = 0xffff;
int CRC16POLY = 0xa001;

foreach (byte i in Data)
{
  CRC ^= i;
  for (var j = 0; j < 8; j++)
  {
    if ((CRC & 1) == 1)
    {
      CRC >>= 1;
      CRC ^= CRC16POLY;
    }
    else
    {
      CRC >>= 1;
    }
  }
}

//最終的に、CRCに計算結果が代入されています。

githubにサンプルコードを上げていますので、よろしければ参照ください。
github

計算コードの解説

コードで実施している内容は下記になります。
データを生成多項式で割り算しています。

  1. 初期値”0xFFFF”と、送信データ値の最初の1byte目をXORする。 
  2. 右へ1ビットシフトする。
  3. CF(キャリーフラグ)=1の場合、”0xA001”とXORする。CF=0の場合、何もしない。
  4. 上記2と3を8回繰り返す。
  5. 送信データの次の1byteとXORする。
  6. 上記2から5を、送信データの最後のbyteまで繰り返す。

以上です。


コメント(githubのアカウントが必要です)