Modbus 예외 코드
예외 응답은 기능 코드에 0x80을 더한 값으로 반환되고, 뒤따르는 1바이트가 거절 사유를 나타낸다.
예외 응답의 형식
장비가 요청을 수신했지만 처리할 수 없으면 정상 응답 대신 예외 응답을 전송한다. 기능 코드의 최상위 비트를 1로 설정하여, 즉 0x80을 더하여 반환하고 그 뒤에 예외 코드 1바이트를 추가한다. 03 요청에는 0x83이, 06 요청에는 0x86이 반환된다.
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로 거절된다.
예외 코드 03은 레지스터에 쓰려는 값이 장비의 프로그램이 기대하는 범위를 벗어났음을 의미하지 않는다. 사양에는 프로토콜이 레지스터 값의 의미를 알지 못한다고 기술되어 있다. 게이트웨이를 경유할 때는 0A(경로 없음)와 0B(후단 장비가 응답하지 않음)도 발생한다.
03 읽기의 예외 코드 판정 순서
기능 코드를 지원하는가 아니면 01
개수가 1~125 안인가 아니면 03
시작 주소와 끝 주소가 있는가 아니면 02
읽기에 성공했는가 아니면 04
무응답과의 구분
예외 응답은 요청이 장비까지 손상 없이 도착했다는 의미이기도 하다. 요청이 전송 중에 손상되었거나 도달하지 못했으면 장비는 아무것도 전송하지 않고, 송신 측은 timeout(응답 대기 시간 초과)으로 이를 감지한다. 예외 코드가 반환되었다면 통신선보다 요청 내용을 먼저 점검한다. 다만 0B의 경우에만 게이트웨이 후단의 통신선과 장비 번호를 점검한다.