엑셀 매크로

체크섬 (CRC16-CCITT) 엑셀 매크로로 구현하기_3-2) 간략하게 구현

지마군 2024. 3. 7. 15:27

3-1) CRC16 논리적 흐름을 그대로 구현

3-2) 최대한 간략화하여 구현

3-3) 사전 연산 테이블 활용하여 구현

 

CRC16 구현 정리

1) 다항식 및 사용할 변수 선언

2) HEX값 뒤에 16비트 추가

3) HEX값을 5자리로 나누어 순차적으로 연산

 

이번에는 입력된 HEX값을 앞에서부터 5자리로 나누어 1단위 씩 반복연산을 하는 방식으로 구현하였다.

참고로 5자리를 사용한 이유는 다항식 연산 0x1021이

엄밀하게는 계산 여부를 판단하기 위한 구분용 자리 1이 생략된 형태로, 실제로는 0x11021이 사용되며

결국 한번 계산할 때마다 HEX값 5자리에 영향을 주기 때문이다.

 

 

1) 다항식 및 사용할 변수 선언

Dim crcValue                'CRC 다항식 0x1021 : x^16 + x^12 + x^5 + 1, x^16은 표기 생략
crcValue = Array("88108", "44084", "22042", "11021")

crcValue 계산용 다항식 0x11021과 그 값을 2배로 곱한 값을 역순으로 4개 입력한 테이블

0x11021 x2↙

0x22042 x2↙

0x44084 x2↙

0x88108

정확하게는 0x11021을 오른쪽으로 1비트 씩 비트시프트 한 값.

 

VBA에는 비트 시프트가 없기에 테이블 형태로 사전 정의하였다.

16비트 2비트
0x88108 1000 1000 0001 0000 1000
0x44084 0100 0100 0000 1000 0100
0x22042 0010 0010 0000 0100 0010
0x11021 0001 0001 0000 0010 0001

 

 

2) HEX값 뒤에 16비트 추가

    crcData = crcData & "0000"

계산 진행을 위하여 16비트, 즉 0x0000을 HEX값 뒤에 추가한다.

ex) crcData = 0x1A3B → 0x1A3B0000

 

3) HEX값을 5자리로 나누어 순차적으로 연산

    For i = 1 To Len(crcData) - 4
        crcCalTemp = Left(crcData, 5)                               '연산할 값 5자리 추출
        For j = 1 To 4                                              '1주기 당 4회 계산
            If "&H" & Left(crcCalTemp, 1) >= 2 ^ (4 - j) Then       '비트 시프트 대체 : 앞자리가 1일때 (1000 → 0100 → 0010 → 0001)
                For k = 1 To 5                                      '5자리 순차적으로 XOR 연산
                    crcTemp = "&H" & Mid(crcCalTemp, k, 1) Xor "&H" & Mid(crcValue(j - 1), k, 1)
                    crcTempAssy = crcTempAssy & Hex(crcTemp)
                Next k
                crcCalTemp = crcTempAssy    '중간 연산값 저장
                crcTempAssy = ""
            End If
        Next j
        crcData = Mid(crcCalTemp, 2) & Mid(crcData, 6)      '결과값 가장 앞자리 삭제하고 뒷부분 합치기
    Next i

 

HEX값 앞자리 5개를 분리

분리한 값의 앞자리부터 각 값이 1이면 XOR 연산, 아니면 다음으로.

5회 연산한 결과에 HEX값의 6번째 자리부터 끝까지를 붙임

→ 즉 HEX값에 5회 XOR 반복 연산한 결과

다시 수정된 HEX값에서 앞자리 5개를 분리하여 연산. 

→ 즉 앞단계에서 연산한 HEX값 결과 4자리 + 신규 1자리 연산

 

ex) 0x1A3B0를 순차적으로 XOR 연산

결과값 중 앞자리 0을 뺀 0xB391을 기존 HEX값의 앞 5자리 대신에 입력

0x1A3B0000 → 0xB391000

이 과정을 HEX값이 4자리가 될 때까지 반복

  0x1A3B0 0001 1010 0011 1011 0000 앞자리가 0 : Pass
xor 0x88108 1000 1000 0001 0000 1000
  0x1A3B0 0001 1010 0011 1011 0000 앞자리가 0 : Pass
xor 0x44084 0100 0100 0000 1000 0100
  0x1A3B0 0001 1010 0011 1011 0000 앞자리가 0 : Pass
xor 0x22042 0010 0010 0000 0100 0010
  0x1A3B0 0001 1010 0011 1011 0000 앞자리가 1 : XOR연산
xor 0x11021 0001 0001 0000 0010 0001
  0x0B391 0000 1011 0011 1001 0001  

 

 

 

간단하기 설명하자면

기존에 사용한 방식은 HEX값을 하나하나 2진수로 변경하여 비트 단위로 XOR 연산을 했는데,

다행히 엑셀에서 HEX값의 XOR 연산을 지원하므로 16진수를 그대로 XOR 연산에 사용한 것이다.

 

그 결과, 16진수 → 2진수 변환, 2진수 → 16진수 변환하는 과정이 사라져서

프로그램의 계산 과정이 상당히 간소화되었다.

다만 비트시프트에 대한 기본적인 이해가 필요한 방법이다.

 

 

*****

벌써 내가 작성한 코드를 보면서도 왜 이렇게 했는지 헷갈리기 시작했다.

위에 내용에도 뭔가 착오가 있을수도....

 

리마인드 겸 블로그에 글을 남기기로 했는데, 아니었으면 정말 잊어버렸을 수도 있겠다.