FirmGod

모드버스 RTU 프레임 파서·빌더

캡처한 모드버스 RTU 프레임을 항목별로 분해하거나, 기능 코드와 주소로 요청 프레임을 만듭니다. 예외 응답과 CRC 오류를 따로 표시합니다.

시리얼 스니퍼에서 그대로 붙여넣으세요. 구분자와 0x 접두사는 무시합니다.

Samples:

CRC valid

Slave 1, function 3 (Read Holding Registers)

항목바이트의미
Slave address011
Function code033 — Read Holding Registers
Start address00 000 (0x0000)
Quantity00 0A10
CRC-16 (low byte first)C5 CD0xCDC5 — valid

RTU 프레임의 구조

모드버스 RTU 프레임은 네 부분입니다. 슬레이브 주소 한 바이트, 기능 코드 한 바이트, 기능마다 다른 데이터, 그리고 CRC 두 바이트입니다. 시작 문자도 끝 문자도 없고 길이 필드도 없습니다.

그래서 수신 측은 회선이 조용해지는 것으로 프레임의 끝을 판단합니다. 3.5문자 시간 이상 아무것도 오지 않으면 끝난 것으로 봅니다. 간단하지만 타이밍에 민감해서, 운영체제가 끼어드는 환경에서는 프레임 경계를 놓치는 일이 생깁니다.

주소 표기가 두 가지입니다

장비 문서에 40001, 30001 같은 다섯 자리 번호가 적혀 있는 경우가 많습니다. 앞자리가 레지스터 종류를, 나머지가 1부터 세는 번호를 나타내는 표기입니다. 회선에 나가는 주소는 이것이 아닙니다.

  • 40001 → 보유 레지스터, 전송 주소 0x0000
  • 40002 → 보유 레지스터, 전송 주소 0x0001
  • 30001 → 입력 레지스터, 전송 주소 0x0000

하나씩 어긋나는 문제의 대부분이 여기서 나옵니다. 문서의 번호에서 1을 빼고, 앞자리는 기능 코드로 옮겨 넣어야 합니다.

예외 응답을 읽는 법

슬레이브가 요청을 처리할 수 없으면 기능 코드의 최상위 비트를 세워 돌려줍니다. 0x03 요청에 0x83이 오면 예외이고, 그다음 한 바이트가 이유입니다.

  • 01 — 지원하지 않는 기능 코드
  • 02 — 주소가 범위 밖. 레지스터 개수를 확인하세요.
  • 03 — 값이나 개수가 허용 범위 밖
  • 04 — 슬레이브 내부 오류
  • 06 — 슬레이브가 바쁨. 잠시 후 재시도.

02가 가장 흔하고, 원인은 대개 앞서 말한 주소 표기 혼동입니다.

요청을 만들 때 확인할 것

읽기 요청은 시작 주소와 개수를 담습니다. 개수에는 상한이 있어서 코일은 2000개, 레지스터는 125개까지 한 번에 읽을 수 있습니다. 이를 넘기면 예외 03이 돌아옵니다.

쓰기는 단일과 다중이 나뉩니다. 0x06은 레지스터 하나, 0x10은 여러 개입니다. 다중 쓰기에는 바이트 수 필드가 따로 있어 레지스터 개수의 두 배가 들어가야 하고, 이 값이 틀리면 슬레이브가 프레임을 잘못 해석합니다.

CRC가 맞는데 응답이 없다면

프레임이 온전한데도 조용하다면 회선 설정을 보세요. 보율, 패리티, 정지 비트가 한쪽만 달라도 상대는 프레임을 인식하지 못합니다. RS-485라면 종단 저항과 극성도 확인 대상입니다.

CRC 자체를 확인하려면 모드버스 CRC16 계산기를 쓰세요. TCP 프레임이라면 구조가 다르므로 모드버스 TCP 프레임 빌더 쪽입니다.

자주 묻는 질문

레지스터 주소가 하나씩 어긋납니다.

문서의 40001번 표기와 회선에 나가는 주소는 다릅니다. Holding register 40001은 전송될 때 0x0000입니다. 4로 시작하는 다섯 자리 표기는 사람이 읽기 위한 것이고, 프로토콜은 0부터 세는 16비트 주소를 씁니다. 40001을 그대로 넣으면 엉뚱한 레지스터를 읽습니다.

응답의 기능 코드가 요청보다 128 큽니다.

예외 응답입니다. 슬레이브가 요청을 처리하지 못했을 때 기능 코드의 최상위 비트를 세우고 예외 코드 한 바이트를 붙입니다. 0x03 요청에 0x83으로 답했다면 그다음 바이트가 이유입니다. 01은 지원하지 않는 기능, 02는 주소 범위 밖, 03은 값이 허용 범위 밖, 04는 슬레이브 내부 오류입니다.

프레임 길이를 어떻게 아나요?

RTU에는 길이 필드가 없습니다. 기능 코드마다 구조가 정해져 있어 그것으로 길이를 계산하고, 프레임의 끝은 3.5문자 시간 이상의 침묵으로 판단합니다. 그래서 회선이 느리거나 타이머가 부정확하면 두 프레임이 하나로 붙어 보이는 일이 생깁니다.

브로드캐스트는 어떻게 보내나요?

슬레이브 주소 0으로 보내면 모든 장비가 받습니다. 다만 응답은 오지 않습니다. 쓰기 명령에만 쓸 수 있고 성공했는지 확인할 방법이 없으므로, 중요한 설정에는 개별 주소로 보내고 응답을 확인하는 편이 안전합니다.

코일과 레지스터가 어떻게 다른가요?

코일은 1비트, 레지스터는 16비트입니다. 기능 코드도 다릅니다. 01은 코일 읽기, 02는 이산 입력 읽기, 03은 보유 레지스터 읽기, 04는 입력 레지스터 읽기입니다. 읽기 전용인지 쓰기 가능한지도 함께 정해지므로, 쓰기가 거부된다면 대상이 입력 쪽일 가능성이 있습니다.