<!doctype html>
CRC 계산과 해석
— Lammert Bies의 “On-line CRC calculation and free library”를 참고하여 정리한 실무 가이드
1) CRC(순환중복검사)란?
CRC(Cyclic Redundancy Check)는 전송 또는 저장 중에 발생할 수 있는 비트 오류를 검출하기 위해 전송 데이터에 대해 다항식 기반의 나머지를 붙이는 방법입니다. CRC는 하드웨어·소프트웨어에서 효율적으로 구현 가능하며 짧은 버스트 오류나 단일/다중 비트 오류 검출에 매우 효과적입니다. :contentReference[oaicite:1]{index=1}
2) CRC의 수학적 배경(간단히)
메시지 비트열을 하나의 다항식으로 보고, 미리 정한 생성 다항식 G(x)로 나눈 나머지를 CRC로 사용합니다. 연산은 모듈로-2(=비트 단위 XOR, 캐리 무시)로 이루어지므로 하드웨어 구현이 간단합니다. :contentReference[oaicite:2]{index=2}
3) 자주 쓰이는 CRC 다항식(참조)
| 이름 | 다항식 (hex) | 특징 / 용도 |
|---|---|---|
| CRC-16 | 0x8005 (반사 표현 0xA001) | Modbus RTU 등에서 널리 사용 |
| CRC-CCITT (CRC-16-CCITT) | 0x1021 | 통신 규격, 표준 테스트 문자열(“123456789”) 검증에 자주 사용 |
| CRC-32 | 0x04C11DB7 | 네트워크 패킷, 파일 무결성 |
출처: Lammert Bies — 다항식 및 이론적 설명. :contentReference[oaicite:4]{index=4}
4) Modbus CRC-16(실무 파라미터)
- 다항식: 0x8005 (반사형으로 0xA001로 구현되는 경우가 일반적)
- 초기값(init): 0xFFFF
- 반사(in/out): 적용(일반적으로 true)
- 최종 XOR: 0x0000
- 바이트 전송 순서: LSB(하위 바이트) 먼저 전송
(위 파라미터 표준은 Lammert Bies 설명과 업계 관행을 기반으로 요약했습니다). :contentReference[oaicite:5]{index=5}
5) 구현 방법 — 비트 연산(단순) vs 테이블(빠름)
비트 단위(루프) 구현 — 이해하기 쉬움
// C: Modbus-style CRC-16 (bitwise)
#include <stdint.h>
uint16_t crc16_bitwise(const uint8_t *buf, size_t len) {
uint16_t crc = 0xFFFF;
for (size_t i = 0; i < len; ++i) {
crc ^= buf[i];
for (int j = 0; j < 8; ++j) {
if (crc & 0x0001) crc = (crc >> 1) ^ 0xA001;
else crc >>= 1;
}
}
return crc; // 반환값: 0xHHLL (High<<8 | Low), 전송 시 LSB 먼저
}
테이블 기반(lookup) — 속도 우선
256-entry 테이블을 사용하면 바이트 단위로 빠르게 갱신할 수 있어 실무에서는 보통 이 방법을 사용합니다. 테이블은 런타임에 생성하거나 정적 테이블로 코드에 포함시킵니다(임베디드에선 정적 테이블 선호).
// C: 테이블 방식 (사용 예)
uint16_t crc = 0xFFFF;
for (size_t i=0; i<len; ++i) {
uint8_t idx = (uint8_t)(crc ^ buf[i]);
crc = (crc >> 8) ^ crc16_table[idx];
}
6) 검증(테스트 벡터)
구현 검증을 위해 널리 쓰이는 테스트 문자열은 "123456789" 입니다. CRC 계산기가 표준과 일치한다면 이 문자열에 대해 알려진 결과와 일치해야 합니다(이 방법은 Lammert Bies 페이지에서 권장됨). :contentReference[oaicite:6]{index=6}
| 표현 | 데이터 | 예상 CRC |
|---|---|---|
| CRC-16-IBM (예) | 123456789 | 0xBB3D (구현에 따라 다름—파라미터에 유의) |
테스트 벡터는 사용된 CRC 파라미터(init/reflect/xorout)에 따라 값이 달라집니다. 동일 파라미터를 사용했는지 확인하세요.
7) Python 예제
# Python: simple Modbus CRC
def modbus_crc(data: bytes) -> int:
crc = 0xFFFF
for b in data:
crc ^= b
for _ in range(8):
if crc & 0x0001:
crc = (crc >> 1) ^ 0xA001
else:
crc >>= 1
return crc
frame = bytes([0x01,0x03,0x00,0x6B,0x00,0x03])
print(hex(modbus_crc(frame))) # 예: 0x7687
8) 구현 시 주의사항 (체크리스트)
- 파라미터 확인: 다항식, 초기값, 반사, xorout을 정확히 맞출 것 — 구현간 불일치의 가장 흔한 원인.
- 바이트 순서(Endianness): Modbus는 CRC를 LSB 먼저 전송. 전송-수신 순서 일치 필요.
- 프레임 경계: RTU처럼 프레임 경계가 명확하지 않을 경우 CRC 처리 범위를 정확히 지정해야 함.
- 테스트 벡터: “123456789” 또는 공개된 바이트 벡터로 검증.
- 성능: 임베디드에서 빈번한 계산은 테이블 방식이나 하드웨어 가속 검토.
Lammert Bies의 문서는 CRC 이론·선택권고·테스트 방법을 상세히 설명하고 있습니다. 구현 전 해당 문서를 참고해 파라미터를 정확히 이해하세요. :contentReference[oaicite:7]{index=7}
9) 추가 리소스
- Lammert Bies — On-line CRC calculation and free library. (본 글의 주 근거 자료). :contentReference[oaicite:8]{index=8}
- libcrc — CRC libraries (다양한 CRC 구현 라이브러리)
CRC 계산과 해석
— Lammert Bies의 “On-line CRC calculation and free library”를 참고하여 정리한 실무 가이드
1) CRC(순환중복검사)란?
CRC(Cyclic Redundancy Check)는 ...
9) 추가 리소스
10) Modbus CRC16 계산기
'HardWare' 카테고리의 다른 글
| TP4056 완전 가이드 — 핀아웃 · 사용법 · RPROG 계산기 · 설계 팁 (0) | 2025.10.10 |
|---|---|
| 배터리 충전 회로의 CC/CV 제어 원리 (0) | 2025.10.10 |
| 아두이노 제어문 완전 정리 (0) | 2025.09.26 |
| CAN 통신의 기초 — 챕터 1 (1) | 2025.09.26 |
| Modbus 프로토콜 (RTU vs TCP) CRC계산기 (0) | 2025.09.26 |