FirmGod

모드버스 CRC16 계산기

모드버스 RTU 프레임의 CRC-16을 계산합니다. 16진수를 붙여넣으면 두 바이트 순서로 체크섬을 보여주고, 전송할 전체 프레임까지 만들어 줍니다.

공백, 쉼표, 하이픈, 0x 접두사를 모두 인식합니다.

예시
CRC-16/MODBUS0xCDC5
10진수52677
하위 바이트 (먼저 전송)0xC5
상위 바이트 (나중 전송)0xCD
회선에 나가는 CRCC5 CD
완성된 프레임01 03 00 00 00 0A C5 CD
페이로드 길이6 bytes

모드버스 RTU가 CRC를 쓰는 이유

모드버스 RTU는 프레임의 시작과 끝을 알리는 문자가 없습니다. 대신 일정 시간 이상 회선이 조용하면 프레임이 끝난 것으로 봅니다. 그래서 수신 측은 "지금 받은 바이트 묶음이 온전한 프레임인가"를 스스로 판단해야 하고, 그 판단의 근거가 마지막 두 바이트의 CRC입니다.

노이즈가 섞인 산업 현장에서 비트 하나가 뒤집히는 일은 드물지 않습니다. CRC-16은 그런 단일 비트 오류는 물론 연속된 짧은 오류 구간도 대부분 잡아냅니다. 프레임을 조용히 버리고 재전송을 기다리는 쪽이, 잘못된 레지스터 값으로 설비를 움직이는 것보다 낫다는 설계입니다.

바이트 순서가 함정입니다

CRC-16/MODBUS의 결과는 16비트 값 하나지만, 회선에는 하위 바이트가 먼저 나갑니다. 프레임 안의 레지스터 값은 상위 바이트가 먼저인데 CRC만 반대라, 캡처를 읽다 보면 둘을 섞기 쉽습니다.

계산 결과가 0x0A1B라면 전송되는 바이트는 1B 0A입니다. 계산기가 보여주는 숫자를 그대로 캡처와 맞대어 보고 "값이 다르다"고 판단하는 것이 가장 흔한 오해입니다. 이 계산기가 상위 바이트, 하위 바이트, 그리고 회선에 나가는 순서를 따로 표시하는 이유가 여기 있습니다.

어디부터 어디까지가 대상인가

CRC는 슬레이브 주소부터 데이터의 마지막 바이트까지를 대상으로 합니다. RTU에는 헤더가 없으므로 사실상 프레임 전체입니다. 이미 CRC가 붙어 있는 프레임을 통째로 넣으면 당연히 다른 값이 나옵니다.

모드버스 TCP에는 적용되지 않습니다. TCP는 전송 계층이 이미 무결성을 보장하므로 CRC를 쓰지 않고, 대신 MBAP 헤더의 길이 필드가 프레임 경계를 알려 줍니다. TCP 프레임 끝에 CRC를 붙이면 길이 필드와 실제 바이트 수가 어긋나 장비가 프레임을 잘못 해석합니다.

CRC-16이라는 이름만으로는 부족합니다

CRC-16/MODBUS의 파라미터는 다항식 0x8005(역방향 표기로 0xA001), 초기값 0xFFFF, 입력과 출력 모두 반사, 최종 XOR 없음입니다. 같은 다항식을 쓰는 CRC-16/ARC는 초기값이 0x0000이라 결과가 전혀 다릅니다.

데이터시트에 "CRC-16"이라고만 적혀 있다면 그것만으로는 어느 모델인지 알 수 없습니다. 초기값과 반사 여부까지 확인하고, 파라미터가 다르다면 CRC 계산기에서 직접 지정해 계산하세요.

검증하는 두 가지 방법

받은 프레임이 온전한지 확인하는 방법은 두 가지입니다. 하나는 마지막 두 바이트를 떼어내고 나머지로 CRC를 계산해 떼어낸 값과 비교하는 것입니다. 다른 하나는 CRC를 포함한 프레임 전체로 CRC를 계산하는 것인데, 이때 결과가 0이면 무결한 프레임입니다.

두 번째 방법이 구현하기 간단해서 펌웨어에서 자주 쓰입니다. 이 계산기는 첫 번째 방식을 전제로 하므로 CRC를 뺀 부분만 입력하세요.

CRC가 맞는데도 통신이 안 될 때

CRC는 프레임이 온전한지만 말해 줍니다. 프레임이 온전한데도 장비가 응답하지 않는다면 다른 곳을 봐야 합니다. 슬레이브 주소가 맞는지, 기능 코드를 그 장비가 지원하는지, 레지스터 주소가 1 차이로 어긋나 있지는 않은지 — 모드버스 문서의 40001번 표기와 실제 전송되는 0번 주소를 혼동하는 일이 흔합니다.

프레임 자체를 항목별로 뜯어보려면 모드버스 프레임 파서를 쓰세요. 예외 응답이라면 어떤 예외 코드인지도 함께 표시됩니다.

자주 묻는 질문

계산한 CRC가 장비가 보낸 값과 다릅니다.

바이트 순서를 먼저 확인하세요. 모드버스 RTU는 CRC를 하위 바이트 먼저 보냅니다. 계산기가 0x0A1B를 내놓았다면 회선에는 1B 0A 순서로 나갑니다. 계산 결과를 그대로 읽고 캡처와 비교하면 뒤집힌 것처럼 보입니다. 그다음으로 흔한 원인은 입력 범위입니다. CRC는 슬레이브 주소부터 데이터 끝까지가 대상이고, 이미 붙어 있는 CRC 두 바이트는 빼야 합니다.

어느 바이트까지 넣어야 하나요?

슬레이브 주소, 기능 코드, 그리고 데이터 전체입니다. RTU 프레임에는 시작·끝 문자가 없으므로 프레임 전체가 곧 CRC 대상입니다. 모드버스 TCP라면 이야기가 다릅니다. TCP는 CRC를 쓰지 않고 MBAP 헤더가 그 역할을 대신하므로, TCP 프레임에 CRC를 붙이면 장비가 프레임 길이를 잘못 읽습니다.

CRC-16/MODBUS는 다른 CRC-16과 무엇이 다른가요?

다항식은 0xA001(역방향 표기)로 CRC-16/ARC와 같지만 초기값이 0xFFFF입니다. 0x0000으로 시작하는 ARC와는 결과가 완전히 다릅니다. 이름에 CRC-16만 적힌 자료를 그대로 믿지 말고 초기값·반사·최종 XOR까지 확인하세요. 일반 CRC 계산기에서 파라미터를 직접 맞추려면 이 사이트의 CRC 계산기를 쓰면 됩니다.

응답 프레임 검증에도 쓸 수 있나요?

쓸 수 있습니다. 받은 프레임에서 마지막 두 바이트를 떼고 나머지로 CRC를 구한 뒤 떼어낸 값과 비교하면 됩니다. 또는 CRC를 포함한 프레임 전체를 넣었을 때 결과가 0이 되는 성질을 이용해도 됩니다. 다만 이 계산기는 앞의 방식을 전제로 하므로 CRC를 빼고 입력하세요.

예외 응답도 CRC가 붙나요?

붙습니다. 예외 응답은 기능 코드의 최상위 비트가 1로 설정되고 예외 코드 한 바이트가 따라오는 짧은 프레임이며, CRC 계산 방식은 정상 응답과 완전히 같습니다. 프레임 구조를 항목별로 확인하려면 모드버스 프레임 파서를 쓰세요.