CCITT CRC-16

디지탈 데이터를 송수신하는 과정에서 데이터가 오류없이 정상적으로 수신되었는지 확인하기 위해 흔히 CRC(Cyclic Redundancy Code)를 사용한다.

CRC에는 다양한 종류가 있는데, 대표적인 것이 CCITT CRC-16이다. 이것은 전송데이터를 특정 다항식을 이용하여 나눗셈을 수행하고 남은 나머지 16비트를 전송데이터의 뒷부분에 추가적으로 전송하는 것을 의미한다. 수신측에서는 동일한 다항식으로 나눗셈을 수행하여 나머지가 특정값이면 수신데이터에 오류가 없다고 추정하는 것이다.

CCITT CRC-16의 다항식은 다음과 같다.

 또는 0x1021

위 다항식의 좌측을 이진수로 표시하면 b’10001000000100001로 표기할 수 있으며, 우측은 이를 16진수로 표기한 것으로 MSB는 항상 1이기 때문에 이를 생략하고 16비트만 표기한 것이다. CRC의 계산은 전송하고자 하는 2진 데이터에 을 곱하고, 즉 b’10000000000000000을 곱하고 이를 위의 다항식으로 나누어서 나머지를 데이터에 이어서 전송하는 것이다. 수신측에서는 수신한 데이터를 위의 다항식으로 나누어 나머지가 0이면 수신데이터에 오류가 없는 것이고 0이 아니면 데이터에 오류가 발생하였다는 것을 의미한다. 나누는 과정에서는 일반적인 산술 나누기와 달리 각 비트 간에 xor을 수행한다. 이 과정을 간단하게 설명하기 위해 3비트의 CRC를 계산하는 과정을 살펴보면 다음과 같다. 우선 다항식을 b’011로 하고 전송하고자 하는 데이터를 b’11010011101100 라고 한다면 송수신부의 CRC 계산 과정은 다음과 같다.
- 송신부


- 수신부(오류가 없는 경우)



- 수신부(오류 포함)
그런데, 위의 CRC를 계산하는 과정은 shift register를 이용하여 다음과 같이 쉽게 구현할 수 있다. 여기서 + 는 modulo 2 더하기를 의미한다. 즉 2 비트를 xor을 취하면 된다.


이제 다시 CCITT CRC-16 다항식을 적용하여 보면 회로는 다음과 같이 구성할 수 있다.

 


그리고 인터넷에서 CCITT CRC-16을 찾아보면 규격이 다음과 같이 정의 되어 있다고 나온다. 

Width = 16 bits
Truncated polynomial = 0x1021
Initial value = 0xFFFF
Input data is NOT reflected
Output CRC is NOT reflected
No XOR is performed on the output CRC

위의 글을 보면 레지스터의 초기 값을 모두 1로 해야 한다는 것을 알 수 있고, CRC 계산 결과를 그대로 전송해야 된다. 그런데 또 인터넷에서 그냥 CRC-16 계산기를 찾아보면 다음과 같은 다양한 CRC-16 표를 볼 수 있다. 이 표에서 Poly는 다항식, Init는 레지스터 초기값, RefIn은 입력 비트의 순서를 반대로 한다는 것이고, RefOut 출력 비트의 순서를 반대로 한다는 뜻이다. 그리고 XorOut은 계산된 CRC 값에 대해 표에 나와 있는 값과 xor을 취해서 전송한다는 뜻이다. 즉 0xFFFF라고 표시 되어 있으면 계산된 CRC 비트 모두 not을 취해서 전송하여야 한다.

 

Algorithm

Result

Check

Poly

Init

RefIn

RefOut

XorOut

1

CRC-16/CCITT-FALSE

0x29B1

0x29B1

0x1021

0xFFFF

false

false

0x0000

2

CRC-16/ARC

0xBB3D

0xBB3D

0x8005

0x0000

true

true

0x0000

3

CRC-16/AUG-CCITT

0xE5CC

0xE5CC

0x1021

0x1D0F

false

false

0x0000

4

CRC-16/BUYPASS

0xFEE8

0xFEE8

0x8005

0x0000

false

false

0x0000

5

CRC-16/CDMA2000

0x4C06

0x4C06

0xC867

0xFFFF

false

false

0x0000

6

CRC-16/DDS-110

0x9ECF

0x9ECF

0x8005

0x800D

false

false

0x0000

7

CRC-16/DECT-R

0x007E

0x007E

0x0589

0x0000

false

false

0x0001

8

CRC-16/DECT-X

0x007F

0x007F

0x0589

0x0000

false

false

0x0000

9

CRC-16/DNP

0xEA82

0xEA82

0x3D65

0x0000

true

true

0xFFFF

10

CRC-16/EN-13757

0xC2B7

0xC2B7

0x3D65

0x0000

false

false

0xFFFF

11

CRC-16/GENIBUS

0xD64E

0xD64E

0x1021

0xFFFF

false

false

0xFFFF

12

CRC-16/MAXIM

0x44C2

0x44C2

0x8005

0x0000

true

true

0xFFFF

13

CRC-16/MCRF4XX

0x6F91

0x6F91

0x1021

0xFFFF

true

true

0x0000

14

CRC-16/RIELLO

0x63D0

0x63D0

0x1021

0xB2AA

true

true

0x0000

15

CRC-16/T10-DIF

0xD0DB

0xD0DB

0x8BB7

0x0000

false

false

0x0000

16

CRC-16/TELEDISK

0x0FB3

0x0FB3

0xA097

0x0000

false

false

0x0000

17

CRC-16/TMS37157

0x26B1

0x26B1

0x1021

0x89EC

true

true

0x0000

18

CRC-16/USB

0xB4C8

0xB4C8

0x8005

0xFFFF

true

true

0xFFFF

19

CRC-A

0xBF05

0xBF05

0x1021

0xC6C6

true

true

0x0000

20

CRC-16/KERMIT

0x2189

0x2189

0x1021

0x0000

true

true

0x0000

21

CRC-16/MODBUS

0x4B37

0x4B37

0x8005

0xFFFF

true

true

0x0000

22

CRC-16/X-25

0x906E

0x906E

0x1021

0xFFFF

true

true

0xFFFF

23

CRC-16/XMODEM

0x31C3

0x31C3

0x1021

0x0000

false

false

0x0000


앞에서 설명한 규격과 위의 표를 보면 일반적인 CCITT CRC-16은 표에서 1번에 해당한다. 그런데 어떤 시스템에서는 위 표에서 11번을 따른 다는 것을 CRC 계산 결과를 통해 알 수 있다. 그리고 11번에 따른 데이터 스트림을 수신부에서 CRC 부분까지 CRC를 계산하여 보면 오류가 발생하지 않았을 때 x’1d0f가 레지스터 값이다. 따라서 수신부에서 CRC 계산을 수행하여 레지스터에 x’1d0f가 남아 있다고 하면 전송이 정상적으로 이루어 진 것이다.

댓글

이 블로그의 인기 게시물