CRC(cyclic redundancy checking) : 주기적 덧(붙임) 검사

CRC는 통신 링크로 전송되어온 데이터 내에 에러가 있는지 확인하기 위한 방법 중의 하나이다. 송신장치는 전송될 데이터 블록에 16 비트 또는 32 비트 다항식을 적용하여, 그 결과로 얻어진 코드를 그 블록에 덧붙인다. 수신측에서는 데이터에 같은 다항식을 적용하여 그 결과를 송신측이 보내온 결과와 비교한다. 만약 두 개가 일치하면, 그 데이터는 성공적으로 수신된 것이며, 그렇지 않은 경우 그 데이터 블록을 재 송신하도록 송신측에게 요구한다.

 

ITU-T(이전의 CCITT)는 송신블록에 부가될 코드를 얻는데 사용되는 16 비트 다항식에 대한 표준을 제정했다. IBM의 SDLC와 다른 프로토콜들은 CRC-16과 다른 16 비트 다항식을 사용한다. 16 비트 CRC는 두 개의 비트가 동시에 에러가 난 경우를 포함하여, 일어날 수 있는 모든 에러에 대하여 99.998% 검출을 보장한다. 이 정도의 검출보증은 4 KB 이하의 데이터 블록 전송에는 충분한 것으로 평가되고 있으며, 그 이상의 대량 전송에는 32 비트 CRC가 사용된다. 이더넷과 토큰링 프로토콜에서도 모두 32 비트 CRC를 사용한다.

 

다소 덜 복잡하고 에러 검출능력도 다소 떨어지는 방법으로서 체크섬 방식이 있다. 이러한 방법을 사용하는 프로토콜 목록을 보려면 모뎀 에러교정 프로토콜을 참조하라


 

16비트 CRC 값 계산 코드

디바이스와 데이타를 교환하는 프로그램을 작성할 때 crc 체크가 제대로 되는지 확인하기 위하여 테스트용으로 16비트 crc 값을 생성하는 짧은 코드를 만들어 보았다. 사용 방법은 crc값을 만들고자 하는 데이타를 파일로 저장하고 아래 함수의 인자로 파일명을 전달해 주면 된다.

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
 
unsigned int CRC16R(char data, unsigned int crc16);
 
void main(int argc, char *argv[])
{
        FILE *in;       
        //unsigned char data[250];
        unsigned char *data;
        long len,fl,i;
        int tc;
        unsigned char temp;
        
        unsigned int crc1,crc2,crc16;
        
        crc1=0;
        crc2=0;
        crc16=0xffff;
 
        if(argc<2){
                printf("usage : crc <filename>\n");
                return;
        }
 
        if((in = fopen(argv[1],"rb")) == NULL){
                printf("can't open %s\n",argv[1]);
                return;
        }
 
        // read from file
        fseek(in,0L,SEEK_END);
        fl = ftell(in);
        fseek(in,0L,SEEK_SET);
 
        data = (unsigned char *)malloc(fl);
        memset(data, '\0', sizeof(data));
 
        for(len=0;len<fl;len++) {
                tc = fgetc(in);
                if (EOF==tc) {
                        fclose(in);
                }
                data[len]= (unsigned char)tc;
        }
        
        data[len]='\0';
 
        // calc. crc
        for     (i=0;i<len;i++){
                temp = data[i];
                crc16=CRC16R(temp, crc16);
                printf("0x%2x, 0x%4x\n", temp, crc16);
        }
 
        crc1 = crc16 & 0xff;
        if (crc1 <0x80) crc1 ^= 0xff;
        crc2 = ((crc16>>8)&0xff);
        if (crc2 <0x80) crc2 ^= 0xff;
 
        printf("crc16 is 0x%4x\n",crc16);
        printf("crc1 is 0x%2x\n",crc1);
        printf("crc2 is 0x%2x\n",crc2);
 
        free(data);
        getch();
}
 
unsigned int CRC16R(unsigned char data, unsigned int crc16)
{
        int i;
        unsigned int temp_crc16;
        unsigned char temp_data;
 
        temp_crc16 = crc16;
        temp_data = (unsigned char) data;
 
        temp_data <<=1;
        for ( i = 8; i > 0; i--){
 
                temp_data >>= 1;
                if ((temp_data ^ temp_crc16) & 0x0001)
                        temp_crc16 = (temp_crc16 >> 1) ^ 0x8408;
                else
                        temp_crc16 >>= 1;
        }
        return(temp_crc16);
}

 

출처: http://home.dasomnetwork.com/~leedw

Posted by 김용환 '김용환'

댓글을 달아 주세요