글 / Modbus·OPC UA

Modbus 예외 코드

예외 응답은 기능 코드에 0x80을 더한 값으로 반환되고, 뒤따르는 1바이트가 거절 사유를 나타낸다.

작성일 · 읽는 시간 2분 · Modbus Application Protocol V1.1b3 기준

예외 응답의 형식

장비가 요청을 수신했지만 처리할 수 없으면 정상 응답 대신 예외 응답을 전송한다. 기능 코드의 최상위 비트를 1로 설정하여, 즉 0x80을 더하여 반환하고 그 뒤에 예외 코드 1바이트를 추가한다. 03 요청에는 0x83이, 06 요청에는 0x86이 반환된다.

기능 코드에 0x80을 더한 예외 응답 두 바이트의 형식

pythonexception.py
pdu = bytes.fromhex("83 02")  # 03 요청에 돌아온 예외 응답

function, code = pdu[0], pdu[1]
if function & 0x80:
    # 최상위 비트를 지우면 원래 기능 코드가 나온다
    print(f"기능 코드 {function & 0x7F:02X}, 예외 코드 {code:02X}")
# 기능 코드 03, 예외 코드 02

예외 코드

코드 이름 의미
01 Illegal Function 장비가 해당 기능 코드를 지원하지 않거나 현재 상태에서는 처리할 수 없음
02 Illegal Data Address 시작 주소부터 개수만큼의 범위가 장비에 존재하지 않음
03 Illegal Data Value 요청에 포함된 값이 올바르지 않음. 개수가 허용 범위를 벗어난 경우 등
04 Server Device Failure 처리 중 복구할 수 없는 오류가 발생함
06 Server Device Busy 장시간 소요되는 명령을 처리하는 중. 이후에 재전송해야 함

레지스터가 100개인 장비의 주소는 0부터 99까지이다. 96부터 4개를 읽는 요청은 처리되고, 96부터 5개를 읽는 요청은 예외 코드 02로 거절된다.

주소 0~99인 장비에서 처리되는 읽기와 02로 거절되는 읽기

예외 코드 03은 레지스터에 쓰려는 값이 장비의 프로그램이 기대하는 범위를 벗어났음을 의미하지 않는다. 사양에는 프로토콜이 레지스터 값의 의미를 알지 못한다고 기술되어 있다. 게이트웨이를 경유할 때는 0A(경로 없음)와 0B(후단 장비가 응답하지 않음)도 발생한다.

03 읽기의 예외 코드 판정 순서

text
기능 코드를 지원하는가        아니면 01
개수가 1~125 안인가           아니면 03
시작 주소와 끝 주소가 있는가  아니면 02
읽기에 성공했는가             아니면 04

03 읽기 요청의 예외 코드를 정하는 네 단계 판정 순서

무응답과의 구분

예외 응답은 요청이 장비까지 손상 없이 도착했다는 의미이기도 하다. 요청이 전송 중에 손상되었거나 도달하지 못했으면 장비는 아무것도 전송하지 않고, 송신 측은 timeout(응답 대기 시간 초과)으로 이를 감지한다. 예외 코드가 반환되었다면 통신선보다 요청 내용을 먼저 점검한다. 다만 0B의 경우에만 게이트웨이 후단의 통신선과 장비 번호를 점검한다.