<img src="http://blogimgs.naver.com/nblog/ico_scrap01.gif" class="i_scrap" width="50" height="15" alt="본문스크랩" /> 16비트 CRC 값 계산 코드
java core 2006. 10. 7. 10:30CRC(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);
}