Modbus RTU 프레임을 직접 만드는 MCU 펌웨어에서 CRC가 맞지 않으면 장치는 요청을 조용히 버릴 수 있습니다. 특히 계산된 16비트 값의 표시 순서와 선로에 보내는 두 바이트 순서를 혼동하기 쉽습니다. 이 가이드는 공식 Modbus 직렬 라인 명세의 CRC 절차를 C로 구현하고, 수신 프레임의 한 바이트를 바꾸어 오류 검출을 확인합니다.
이 예제는 호스트 PC에서 바이트 배열을 검사합니다. UART 타이밍, RS-485 방향 제어, 실제 장치 응답을 시험한 결과는 아닙니다. Modbus Organization의 직렬 라인 명세 V1.02, 2.5.1.2·부록 B
1. CRC 범위와 바이트 순서
Modbus RTU의 CRC-16은 주소 바이트부터 마지막 데이터 바이트까지 계산합니다. 시작·정지·패리티 비트와 프레임 간 침묵 시간은 계산 대상이 아닙니다. CRC 레지스터를 0xFFFF로 초기화하고 입력 바이트를 XOR한 뒤, 각 바이트마다 8회 오른쪽으로 이동합니다. 이동 전 최하위 비트가 1이면 0xA001을 XOR합니다. 결과의 하위 바이트를 먼저, 상위 바이트를 나중에 프레임에 붙입니다. 공식 CRC 알고리즘
| 예제 요청 항목 | 바이트 |
|---|---|
| 슬레이브 주소·기능 코드(보유 레지스터 읽기) | 01 03 |
| 시작 주소·읽을 개수(10개) | 00 00 00 0A |
| 계산한 16비트 CRC 표시 | 0xCDC5 |
| 실제 전송 CRC 바이트 | C5 CD |
이 표의 시작 주소 0x0000과 화면에 표시되는 40001 같은 레지스터 표기는 장치 문서에서 따로 대조하세요. 앞선 Modbus 주소·부호·워드 순서 가이드와 달리 여기서는 RTU 프레임의 CRC 검증만 다룹니다. 이 예제의 01 03 00 00 00 0A C5 CD는 표준 알고리즘의 계산값을 호스트 프로그램으로 확인한 검사용 프레임입니다.
2. 복사해서 실행하는 C 예제
아래 코드를 modbus_crc.c로 저장하고 gcc -std=c11 -Wall -Wextra -Werror modbus_crc.c -o modbus_crc로 빌드하세요. Linux에서는 ./modbus_crc, Windows PowerShell에서는 .\\modbus_crc.exe를 실행합니다. assert가 시험을 수행하므로 -DNDEBUG는 붙이지 않습니다.
예상 출력:
verify_rtu는 최소 길이를 확인한 뒤, 마지막 두 바이트를 제외한 내용으로 CRC를 다시 계산합니다. 함수는 CRC 일치 여부만 반환합니다. 슬레이브 주소, 기능 코드, 길이, 타임아웃, 예외 응답의 적절성은 별도로 검사해야 합니다. CRC는 우발적인 전송 오류 검출용이며 송신자 인증이나 암호학적 무결성 보장이 아닙니다.
3. 장치에서 값이 다르면 확인할 순서
- CRC 계산에 주소부터 데이터 끝까지 넣고, 이미 받은 CRC 두 바이트는 제외했는지 확인합니다.
- 로그의
0xCDC5를 선로 바이트CD C5로 그대로 보내지 않았는지 확인합니다. 이 예제는C5 CD입니다. - RS-485 송신 완료 전에 방향 핀을 수신으로 바꾸어 끝 바이트가 잘리지 않았는지, UART 패리티·보오율과 RTU 프레임 간 간격이 양쪽에서 일치하는지 확인합니다. CRC 코드가 맞아도 물리 계층 설정이 다르면 통신하지 못합니다.
- 가짜 배열 테스트가 통과한 뒤에는 로직 애널라이저로 실제 바이트 순서를 캡처하고, 기기별 주소·기능 지원 여부를 매뉴얼로 대조합니다.
공식 참고: Modbus 직렬 라인 명세 및 구현 안내, CRC 생성 절차 PDF.
댓글
첫 댓글을 남겨 보세요.