自分の中では既に解決済みだったので放置気味だったCRC計算。
 
今日はCRC16を計算するコード。テーブルを使わないバージョンのみ。
CRC16は末尾の処理が他と違うのが特徴。
 
[fcrc16.c]
/*
CCITT CRC16を計算する。
 
CRC16生成多項式 (ただし^は次数。XORではない。)
x = x^16+x^12+x^5+x^0
 
1000010000001000(1) = 0x8408
^x[0]            ^x[16]
 
処理はバイナリファイルの先頭から1バイトづつ、LSBを先頭としたビット列とし、
各ビットごとにCRCを右シフトし、
x^16(シフト前のCRCのLSB)の値とデータビットをXORした結果、
1ならCRC全体を生成多項式で除した後、1をMSB側から右シフトで挿入。
0なら0をMSB側から右シフトで挿入。
*/
 
#include <stdio.h>
 
unsigned long CalcCrc(unsigned char* pBuf, int nBytes);
unsigned long CalcCrc1byte(unsigned int nSample);
 
// CRCの初期値 CRC16では全ビット1
unsigned long Crc  = 0xffff;
 
// 生成多項式(除数)
unsigned long Poly = 0x8408;
 
// メインルーチン
// 指定のファイルを読んでCRC処理ルーチンに渡す
int main(int argc, char* argv[])
{
    unsigned long Result;       // CalcCrcが返すCRC値を受け取る
   
    const char nBufSize = 10240;    // システムに応じて適当なサイズの読み出しバッファ数
    int buf;
    int num;
    FILE *fd;
   
    if(argc == 2 && (fd = fopen(argv[1], "rb")) != NULL) {
       
        // 大容量バッファに変更。失敗しても問題ないのでエラー処理無し。
        setvbuf(fd, NULL, nBufSize, _IOFBF);
       
        // ファイルを先頭から1バイトずつ読み出してCRCを計算する。
        // ワード長は関係無く先頭バイトから、ビット並びはデータのLSBから処理。
        while(fread(&buf, 1, 1, fd) != 0) {
            CalcCrc((unsigned char*)&buf, 1);
        }
        fclose(fd);
       
        // 最終的なCRCの値を取得
        // (CalcCrcにバイト長0を与えて計算させずに結果を得る。ファイルサイズ0バイトに対応させるため)
        Result = CalcCrc(NULL, 0);
       
        // CRCを表示
        printf("%04X\n", Result);
    }
    else {
        printf("using>%s <file>\n", argv[0]);
    }
 
    return(0);
}
 
// バッファに詰められたデータを先頭から1バイトずつnBytesまで計算する。
// CRCは呼び出す側の変数に置いているので次回呼び出しまで単純に保存される。
unsigned long CalcCrc(unsigned char* pBuf, int nBytes)
{
    while(nBytes– != 0) {
        // 1バイトあたりのCRCを計算する
        CalcCrc1byte(*pBuf++);
    }
 
    return(Crc);
}
 
 
// 1ビットごとCRCを処理する
unsigned long CalcCrc1byte(unsigned int Data)
{
    unsigned int DataBit;   // 処理対象ビットの値
    unsigned int CrcTopBit; // CRCシフト時にあふれるビットの値
    int Bits;               // ビット処理のカウンタ
 
    Data = Data & 0xff;     // Dataにゴミがある場合の保険
 
    // 入力データはバイト単位、LSBから処理
    for(Bits=0; Bits<=7; Bits++) {
 
        DataBit   = (Data >> Bits) & 0x1;   // データの中から対象とするビットを取得
        CrcTopBit =  Crc & 0x0001;          // CRCからあふれるビットを取得
 
        // CRCは右シフトで詰める
        Crc = Crc >> 1;
 
        // CRCのあふれ(x^16の部分) xor 対象入力データ が1なら生成多項式で剰余を求める
        if(CrcTopBit ^ DataBit) {
            Crc = Crc ^ Poly;   // 右シフト時にMSBに0が詰められるので、MSBには暗黙に生成多項式の値から1が入る
        }
    }
   
    return Crc;
}
 
テーブルを使うバージョンも少しの改造で簡単にできるはず。 CRC32はテーブル使用版。
http://mzexe.spaces.live.com/blog/cns!A4AC1B4775193505!749.entry
 
広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中