C 언어로 구현한 Bitwise CRC 계산 함수
비트를 하나씩 옮겨가며 손으로 계산하는 방법을 그대로 C로 구현해 만든 CRC-5, CRC-7, CRC-8, CRC-10, CRC-16, CRC-32 계산 함수이다. 더 나은 효율의 라이브러리들이 있지만, 스스로 검증은 할 수 있어야 한다.
2021년 12월, 본 필자가 방송신호 자동절체 제어기를 개발하기 위해 CRC 계산을 공부하며 만들어 본 CRC-5, CRC-7, CRC-8, CRC-10, CRC-16, CRC-32 계산 함수이다.
비트를 하나씩 옮겨가며 손으로 계산하는 방법을 그대로 C로 구현했다. CRC의 동작 개념을 잡기 위해 만든 것이므로, 당연히 효율성이나 속도 따위는 고려 대상이 아니다.
인터넷을 조금만 뒤져보거나 사용하는 개발 환경을 찾아보면, 똑똑한 사람들이 공개해 둔 효율적인 라이브러리들이 널려 있다. 실제 개발에는 이러한 라이브러리들을 가져다 사용하는 게 효율적이다.
하지만 일단 내가 하려는 것이 무엇인지, 어떤 데이터를 집어넣어서 어떤 결과가 출력되어야 하는지는 스스로 검증할 수 있어야 한다. 다른 사람이 만들어 둔 라이브러리는 효율을 위한 도움이어야 한다. 아무것도 모르고 대책 없이 가져다 쓰기만 한다면 당장은 편해도 나중에 문제가 생기기 마련이다.
본문의 설명은 CC BY 4.0을 따르며, 예제 코드와 관련 데이터는 BSD-3 Clause License에 따라 사용할 수 있다.
CRC-5 계산함수
// SAPJIL CRC Calcurator by eqmaker
unsigned char CRC5_Generator(unsigned char *datastream, unsigned int numberofbyte, unsigned char poly)
{
unsigned char rtn=0;
for (unsigned int i=0; i<numberofbyte+1; i++)
{
for (char j= ((i==numberofbyte) ? 4 : 7); j>=0; j--)
{
if (rtn & 1<<4)
{
rtn = rtn << 1;
rtn = (((i==numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
rtn = rtn ^ poly;
}
else
{
rtn = rtn << 1;
rtn = (((i==numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
}
}
}
return rtn & 0b00011111;
}
CRC-7 계산함수
// SAPJIL CRC Calcurator by eqmaker
unsigned char CRC7_Generator(unsigned char *datastream, unsigned int numberofbyte, unsigned char poly)
{
unsigned char rtn=0;
for (unsigned int i=0; i<numberofbyte+1; i++)
{
for (char j= ((i==numberofbyte) ? 6 : 7); j>=0; j--)
{
if (rtn & 1<<6)
{
rtn = rtn << 1;
rtn = (((i==numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
rtn = rtn ^ poly;
}
else
{
rtn = rtn << 1;
rtn = (((i==numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
}
}
}
return rtn & 0b01111111;
}
CRC-8 계산함수
// SAPJIL CRC Calcurator by eqmaker
unsigned char CRC8_Generator(unsigned char *datastream, unsigned int numberofbyte, unsigned char poly)
{
unsigned char rtn=0x00;
for (unsigned int i=0; i<numberofbyte+1; i++)
{
for (char j=7; j>=0; j--)
{
if (rtn & 0x80)
{
rtn = rtn << 1;
rtn = (((i==numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
rtn = rtn ^ poly;
}
else
{
rtn = rtn << 1;
rtn = (((i==numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
}
}
}
return (rtn);
}
CRC-10 계산함수
// SAPJIL CRC Calcurator by eqmaker
void CRC10_Generator(unsigned char *datastream, unsigned int numberofbyte, unsigned int poly)
{
unsigned int rtn=0;
for (unsigned int i=0; i<numberofbyte+2; i++) // 8bit x 2 = 16bit 나머지 (중 10bit 사용)
{
for (char j=((i==numberofbyte+1) ? 1 : 7); j>=0; j--) // 15-6 14-5 13-4 12-3 11-2 10-1 9-0
{
if (rtn & 1<<9)
{
rtn = rtn << 1;
rtn = (((i>=numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
rtn = rtn ^ poly;
}
else
{
rtn = rtn << 1;
rtn = (((i>=numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
}
}
}
rtn = rtn & 0x03ff;
printf("CRC10 : %04X\n", rtn);
}
CRC-16 계산함수
// SAPJIL CRC Calcurator by eqmaker
void CRC16_Generator(unsigned char *datastream, unsigned int numberofbyte, unsigned int poly)
{
unsigned int rtn=0;
for (unsigned int i=0; i<numberofbyte+2; i++) // 8bit x 2 = 16bit 나머지
{
for (char j=7; j>=0; j--)
{
if (rtn & 0x8000)
{
rtn = rtn << 1;
rtn = (((i>=numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
rtn = rtn ^ poly;
}
else
{
rtn = rtn << 1;
rtn = (((i>=numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
}
}
}
rtn = rtn & 0xffff;
printf("CRC16 : %04X\n", rtn);
}
CRC-32 계산함수
// SAPJIL CRC Calcurator by eqmaker
void CRC32_Generator(unsigned char *datastream, unsigned int numberofbyte, unsigned int poly)
{
unsigned int rtn=0;
for (unsigned int i=0; i<numberofbyte+4; i++) // 8bit x 4 = 32bit
{
for (char j=((i==numberofbyte+1) ? 7 : 7); j>=0; j--)
{
if (rtn & 1<<31)
{
rtn = rtn << 1;
rtn = (((i>=numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
rtn = rtn ^ poly;
}
else
{
rtn = rtn << 1;
rtn = (((i>=numberofbyte) ? 0 : datastream[i]) & (1<<j)) ? (rtn | 1) : rtn;
}
}
}
printf("CRC32 : %08X\n", rtn);
}
🔄 갱신 내역
- — 최초 게시
- — 블로그 이전
- — 블로그 이전 및 2차 수정
- — 3차 수정