RS-485 장비 통신 프로그래밍: Address·Command·CRC·Response 처리하기
RS-485 장비 통신 프로그래밍: Address·Command·CRC·Response 처리하기#
1장 RS-485 프로그래밍은 RS-232와 무엇이 다른가#
RS-232에서는 흔히 PC와 장비 하나가 직접 연결됩니다.
PC
│
│ RS-232
│
Device반면 RS-485는 하나의 Bus에 여러 장비를 연결하는 구성이 가능합니다.
Controller
│
────┼──────────────── RS-485 Bus
│
├─ Device 01
├─ Device 02
├─ Device 03
└─ Device 04따라서 프로그램에서도 새로운 문제가 생깁니다.
어느 장비에 보낼 것인가?
→ Address
무슨 작업을 요청할 것인가?
→ Command
응답이 누구에게서 왔는가?
→ Response Address
데이터가 깨지지 않았는가?
→ CRC / Checksum
응답이 없으면 어떻게 할 것인가?
→ Timeout / Retry즉 RS-485 프로그램은 단순히 byte를 보내고 받는 것을 넘어 여러 장비가 공유하는 통신 회선을 관리하는 프로그램이 됩니다.
2장 RS-485와 장비 Address는 별개의 개념이다#
중요한 점부터 짚어야 합니다.
RS-485 자체가 다음과 같은 Address를 정의하는 것은 아닙니다.
Device 01
Device 02
Device 03RS-485는 기본적으로 전기적인 통신 방식입니다.
장비 Address와 Command 구조는 그 위에서 사용하는 Protocol이 결정합니다.
예를 들어 제조사 Protocol이:
[Address][Command][Data][CRC]구조를 사용할 수도 있고,
Modbus RTU라면:
[Server Address][Function Code][Data][CRC]같은 구조를 사용합니다.
따라서:
RS-485 = Address 기반 Protocol
이라고 이해하면 안 됩니다.
정확하게는:
RS-485 Bus 위에서 사용하는 상위 Protocol이 Address를 정의할 수 있다
가 맞습니다.
3장 가장 먼저 장비 Address를 확인한다#
RS-485 Bus에 다음 세 장비가 있다고 하겠습니다.
Device A
Address 0x01
Device B
Address 0x05
Device C
Address 0x09Controller가 Address 0x05에 명령을 보내면 해당 Address를 사용하는 장비가 Response하도록 Protocol을 설계할 수 있습니다.
장비 Address 설정 방법은 제품마다 다릅니다.
DIP Switch 방식#
장비에 있는 DIP Switch를 조합해 Address를 지정할 수 있습니다.
예:
SW1 ON
SW2 OFF
SW3 ON
SW4 OFFRotary Switch 방식#
숫자 Dial을 돌려 Address를 지정하는 장비도 있습니다.
Software 설정#
전용 관리 프로그램이나 Serial Command를 통해 Address를 설정할 수도 있습니다.
EEPROM·Flash 저장#
설정한 Address를 내부 비휘발성 Memory에 저장하는 장비도 있습니다.
중요한 것은 같은 Bus 안에서 Protocol상 충돌하는 Address를 사용하지 않도록 관리하는 것입니다.
4장 Packet은 Address와 Command를 함께 전달한다#
가상의 장비 Protocol을 하나 만들어보겠습니다.
[Address]
[Command]
[Length]
[Payload]
[CRC]예:
05 10 01 01 XX XX의미를 가정하면:
05
→ Device Address
10
→ Command
01
→ Payload Length
01
→ Payload
XX XX
→ CRC입니다.
프로그램에서는 이 구조를 그대로 byte 배열로 만들어야 합니다.
예를 들어 Java라면:
byte[] packet = {
0x05,
0x10,
0x01,
0x01,
0x00,
0x00
};C#이라면:
byte[] packet =
{
0x05,
0x10,
0x01,
0x01,
0x00,
0x00
};마지막 두 byte는 CRC가 들어갈 자리라고 가정합니다.
실제 Packet 구조와 Command 값은 반드시 사용하는 장비의 Protocol 문서를 따라야 합니다.
5장 CRC는 데이터가 깨졌는지 검사한다#
RS-485가 비교적 Noise에 강한 차동 신호 방식을 사용한다고 해서 데이터 오류가 절대로 발생하지 않는 것은 아닙니다.
그래서 상위 Protocol에서 CRC나 Checksum을 사용하는 경우가 많습니다.
예:
TX
05 10 01 01 A1 3C
└──── CRC수신 장비는:
수신 Packet
↓
자신이 CRC 계산
↓
Packet의 CRC와 비교합니다.
일치하면:
Packet 정상다르면:
Packet 손상 가능성으로 판단할 수 있습니다.
CRC는 암호화나 인증 기능이 아닙니다.
전송 중 오류를 검출하기 위한 수단입니다.
CRC 알고리즘은 Protocol마다 다르다#
다음을 모두 확인해야 합니다.
Polynomial
Initial Value
Bit Reflection
Final XOR
CRC Byte Order예를 들어 아래 코드는 흔히 볼 수 있는 CRC-16 계열의 한 형태일 뿐입니다.
public static int crc16(
byte[] data,
int offset,
int length) {
int crc = 0xFFFF;
for (int i = offset;
i < offset + length;
i++) {
crc ^= data[i] & 0xFF;
for (int bit = 0;
bit < 8;
bit++) {
if ((crc & 0x0001) != 0) {
crc =
(crc >> 1) ^ 0xA001;
} else {
crc >>= 1;
}
}
}
return crc & 0xFFFF;
}이 방식이 자신의 장비 Protocol과 같다고 가정해서는 안 됩니다.
특히 Modbus RTU라면 정해진 CRC-16/Modbus 규칙을 사용하지만 제조사 전용 Protocol은 전혀 다른 방식일 수 있습니다.
6장 Command를 보냈으면 Response까지 연결해서 관리한다#
장비 통신 프로그램에서는 단순히:
Send 완료를 성공으로 보면 안 됩니다.
올바른 흐름은 다음과 같습니다.
Command 생성
↓
TX
↓
장비 수신
↓
장비 처리
↓
Response 생성
↓
RX
↓
CRC 확인
↓
Address 확인
↓
Command·Status 확인
↓
업무 결과 처리예를 들어:
TX
05 10 01 01 A1 3C를 보냈다고 하겠습니다.
Response가:
RX
05 10 01 00 B2 4D로 돌아왔다면 프로그램은 최소한 다음을 확인해야 합니다.
Address가 0x05인가?
기대한 Command Response인가?
Length가 정상인가?
CRC가 맞는가?
Status가 성공인가?그 후에야 Application에서 성공 여부를 결정합니다.
7장 RS-485에서는 송신과 수신 방향도 중요하다#
2선식 RS-485는 흔히 Half Duplex로 사용됩니다.
즉 같은 Pair를 이용해 송신과 수신을 번갈아 수행합니다.
Controller
│
│ TX
▼
Device
Controller
▲
│ RX
│
Device동시에 양방향으로 계속 송신하는 구조가 아닙니다.
USB-RS485 Adapter나 Serial Driver가 송수신 방향 전환을 자동으로 처리해주는 경우도 많지만, 일부 환경에서는 방향 제어가 별도로 필요할 수 있습니다.
따라서 프로그램에서 다음을 고려해야 합니다.
TX 시작
TX 완료
송신 Driver 해제
RX 전환
Response 대기방향 전환 Timing이 잘못되면:
Command 마지막 byte 손실
Response 첫 byte 손실
응답 없음
불완전한 Frame등이 발생할 수 있습니다.
8장 하나의 Bus에서 여러 장비를 순서대로 Polling할 수 있다#
다음 장비가 있다고 하겠습니다.
Address 01
Temperature Sensor
Address 02
Controller
Address 03
Meter
Address 04
ActuatorController는 일정한 순서로 상태를 조회할 수 있습니다.
Address 01 상태 요청
↓
Response
Address 02 상태 요청
↓
Response
Address 03 상태 요청
↓
Response
Address 04 상태 요청
↓
Response이를 단순 Polling 구조로 만들 수 있습니다.
하지만 장비 수가 늘어나면 다음 문제가 생깁니다.
Polling Cycle 증가
Timeout 누적
느린 장비의 영향
Retry로 인한 전체 지연
Bus 점유 증가예를 들어 Device 하나를 최대 500ms 기다리고 100대를 순차 조회한다면 최악의 경우 전체 주기가 크게 늘어날 수 있습니다.
따라서 RS-485 Multi-drop 프로그램에서는 개별 장비뿐 아니라 Bus 전체의 Polling Schedule까지 설계해야 합니다.
9장 Timeout과 Retry는 무조건 짧게 설정하는 것이 아니다#
장비에 Command를 보냈지만 Response가 오지 않는다고 하겠습니다.
TX
↓
...
↓
Response 없음프로그램에는 Timeout이 필요합니다.
하지만 다음처럼:
100ms를 모든 장비에 적용해서는 안 됩니다.
장비에 따라 정상 처리 시간이 다르기 때문입니다.
예:
상태 조회
50ms
설정 저장
300ms
Calibration
1초 이상처럼 Command 종류에 따라서도 달라질 수 있습니다.
따라서 Timeout은:
Protocol 규격
Device 최대 처리 시간
Command 종류
Bus 장비 수
Retry 정책을 기준으로 설정해야 합니다.
Retry도 주의해야 한다#
다음처럼 무조건 재전송하면 문제가 될 수 있습니다.
Command
↓
Timeout
↓
Command 재전송첫 번째 Command를 장비가 실제로 실행했지만 Response만 유실된 경우라면 같은 동작이 두 번 실행될 수 있기 때문입니다.
특히 물리 동작이나 상태 변경 Command에서는:
Event ID
Sequence Number
Current State 확인
Idempotency같은 상위 설계가 필요할 수 있습니다.
10장 Receive Buffer와 Packet Parser를 분리한다#
Serial Port에서:
read()했다고 해서 Packet 하나가 정확히 들어온다는 보장은 없습니다.
예를 들어 Packet:
05 10 01 01 A1 3C가 다음처럼 들어올 수 있습니다.
첫 번째 Read:
05 10두 번째 Read:
01 01 A1세 번째 Read:
3C따라서 구조는 다음처럼 만드는 것이 좋습니다.
Serial Port
↓
Raw byte
↓
Receive Buffer
↓
Frame Extraction
↓
CRC Validation
↓
Packet Parser
↓
Device ResponseParser는 다음 정보를 확인할 수 있습니다.
Address
Command
Length
Payload
CRC불완전한 Packet은 Buffer에 남겨두고 다음 수신 데이터를 기다립니다.
11장 Java와 C#에서는 Transport와 Protocol을 분리하자#
처음 프로그램을 만들 때는 다음 코드를 하나의 Class에 몰아넣기 쉽습니다.
Serial Open
Packet 생성
CRC 계산
Send
Read
Response 분석
Retry
업무 처리하지만 장비가 늘어나면 유지보수가 어려워집니다.
다음처럼 분리하는 것이 좋습니다.
SerialTransport
│
├─ Open
├─ Close
├─ Send
└─ Receive
Rs485BusManager
│
├─ Device Address
├─ Polling
├─ Timeout
└─ Retry
ReceiveBuffer
│
└─ byte 누적
PacketParser
│
├─ Frame 검사
├─ Length 검사
└─ CRC 검사
DeviceProtocol
│
├─ Command 생성
└─ Response 해석
DeviceService
│
└─ 실제 업무 처리이 구조를 사용하면 Transport가 나중에:
RS-485
↓
TCP Gateway로 변경되더라도 Device Protocol을 재사용하기 쉬워집니다.
12장 RS-422를 함께 다룰 때는 물리 구조를 구분한다#
RS-422와 RS-485는 둘 다 Differential Signaling을 사용하지만 동일한 기술은 아닙니다.
특히 현장에서 흔히 접하는 구성에서는 RS-422가:
TX+
TX-
RX+
RX-처럼 송수신 Pair를 분리한 Full Duplex 구조로 사용되는 경우가 많습니다.
반면 2선식 RS-485는:
A
BPair를 공유하는 Half Duplex 구성이 흔합니다.
따라서 프로그램에서는 같은 Serial API를 사용하더라도 실제 Adapter와 Driver가:
송수신 방향을 어떻게 제어하는가?를 확인해야 합니다.
상위 Packet Protocol은 같을 수도 있지만 물리적인 Transport 동작은 다를 수 있습니다.
13장 종단저항·Bias·배선 문제는 코드로 해결할 수 없다#
RS-485 프로그램을 아무리 잘 만들어도 물리 Bus가 잘못되어 있으면 통신은 불안정합니다.
대표적으로 확인해야 할 항목입니다.
| 항목 | 확인할 내용 |
|---|---|
| A/B | 극성과 제조사 표기 확인 |
| 종단저항 | Bus 양 끝 구성과 장비 권장값 확인 |
| Bias | Idle 상태 기준 전압 유지 방식 확인 |
| Stub | 불필요하게 긴 분기 최소화 |
| Ground | Common-mode 범위와 현장 접지 설계 확인 |
| Cable | 차동 통신에 적합한 Cable 사용 |
| Topology | 기본적으로 Bus 구조 중심으로 검토 |
흔히 120Ω Termination을 이야기하지만 모든 현장에서 무조건 120Ω 두 개라는 공식처럼 적용해서는 안 됩니다.
Cable 특성과 Transceiver, 제조사 권장 구성 등을 확인해야 합니다.
또한 A/B 표기는 제조사마다 반대로 사용되는 사례가 있으므로 이름만 보고 연결하지 말고 Manual을 확인하는 것이 안전합니다.
14장 장애는 TX·RX Hex Log를 기준으로 추적한다#
RS-485 장애 분석에서 가장 중요한 증거 중 하나가 Raw Packet Log입니다.
예:
2026-09-24 15:30:21.112
PORT=COM5
CONFIG=9600-8-N-1
TX
05 10 01 01 A1 3C
2026-09-24 15:30:21.168
RX
05 10 01 00 B2 4D최소한 다음 정보를 기록하는 것이 좋습니다.
Timestamp
Port
Baud·Parity·Stop
TX / RX
Device Address
Command
Hex Dump
CRC Result
Timeout
Retry Count
Exception이렇게 하면 다음 상황을 구분할 수 있습니다.
TX 자체가 안 됨
TX는 됐지만 Response 없음
Response가 다른 Address에서 옴
CRC 실패
잘못된 Command Response
Timeout 반복15장 RS-485 통신 장애를 순서대로 확인한다#
장비 5대 중 Address 03만 응답하지 않는다고 하겠습니다.
1단계 장비 자체#
Power
Address 설정
Firmware
통신 설정2단계 배선#
A / B
Connector
Cable
Ground
분기3단계 Bus#
Termination
Bias
Topology
Noise4단계 Serial 설정#
Baud Rate
Data Bits
Parity
Stop Bits5단계 Protocol#
Address
Command
Length
CRC6단계 Application#
Timeout
Retry
Parser
Device State이 순서로 확인하면:
RS-485가 안 됩니다.라는 막연한 문제를 구체적인 원인으로 좁힐 수 있습니다.
16장 실습은 물리 동작이 없는 Simulator부터 시작한다#
실제 Actuator나 설비를 움직이는 Command로 처음 테스트하는 것은 피하는 것이 좋습니다.
먼저 Simulator를 구성합니다.
예:
Virtual Bus
Address 01
Simulator
Address 05
Simulator
Address 09
Simulator그리고 다음 정도부터 검증합니다.
Address 01
→ 상태 조회
Address 05
→ 상태 조회
Address 09
→ 상태 조회확인 항목:
올바른 Address로 전송되는가?
Response Address가 일치하는가?
CRC가 검증되는가?
Timeout이 동작하는가?
없는 Address에서 Timeout이 발생하는가?
Retry 횟수가 제한되는가?그 후 Hardware 시험 환경에서 실제 장비의 비위험 조회 Command를 검증하는 순서가 좋습니다.
17장 흔히 하는 잘못된 구현#
RS-485에 Address 기능이 있다고 생각한다#
Address는 RS-485 전기 규격이 아니라 상위 Protocol에서 정의합니다.
Address가 다르면 동시에 송신해도 된다고 생각한다#
같은 Half Duplex Bus에서는 여러 장비가 동시에 송신하면 충돌할 수 있습니다.
Protocol 차원에서 송신 Timing을 관리해야 합니다.
CRC가 맞으면 장비 동작도 성공했다고 생각한다#
CRC는 Packet이 손상되지 않았는지를 검사하는 것입니다.
실제 Command 처리 성공 여부는 Response Status 등을 별도로 확인해야 합니다.
Timeout이 나면 무조건 같은 Command를 재전송한다#
상태 변경 Command는 첫 번째 요청이 실제 실행됐을 가능성이 있으므로 중복 실행을 고려해야 합니다.
A/B 이름만 보고 연결한다#
제조사마다 표기 관례가 다를 수 있으므로 Manual과 실제 Signal 정의를 확인해야 합니다.
종단저항만 추가하면 모든 Noise 문제가 해결된다#
배선 구조, Ground, Cable, Stub, Bias, 주변 Noise Source 등을 함께 확인해야 합니다.
18장 자기 점검#
RS-485의 Address는 누가 정의하는가#
RS-485 자체가 아니라 그 위에서 사용하는 제조사 Protocol이나 Modbus 같은 상위 Protocol이 정의합니다.
하나의 Bus에서 여러 장비를 구분하는 방법은 무엇인가#
상위 Protocol이 제공하는 Device Address나 Identifier를 이용할 수 있습니다.
CRC가 정상이라는 것은 무엇을 의미하는가#
정해진 CRC 규칙 기준으로 수신 데이터에 오류가 발견되지 않았다는 의미이며 실제 장비 동작 성공이나 보안을 보장하는 것은 아닙니다.
Timeout 후 Command를 바로 재전송해도 되는가#
항상 그렇지는 않습니다. 상태 변경 Command라면 첫 요청이 처리됐지만 Response만 유실됐을 가능성을 고려해야 합니다.
RS-485 2선식에서 프로그램이 고려해야 할 추가 요소는 무엇인가#
Half Duplex 송수신 Timing과 Adapter의 Driver 방향 전환 방식 등을 확인해야 할 수 있습니다.
19장 이 글을 마치며#
RS-485 장비 통신 프로그램의 기본 흐름은 다음과 같습니다.
Serial Port Open
↓
Device Address 선택
↓
Command 생성
↓
Payload 구성
↓
CRC 계산
↓
TX
↓
송수신 방향 전환
↓
Response 대기
↓
Receive Buffer
↓
Packet Parser
↓
Address 확인
↓
CRC 검증
↓
Status 확인
↓
업무 처리특히 다음 다섯 가지를 기억하면 됩니다.
RS-485는 전기적 통신 규격이며 Device Address·Command·Packet 구조는 그 위에서 사용하는 Protocol이 정의합니다.
Multi-drop 환경에서는 어떤 Address에 어떤 Command를 보냈는지 명확하게 관리하고 Response의 Address와 Command도 함께 검증해야 합니다.
CRC는 전송 오류를 검출하는 수단이지 인증이나 실제 장비 동작 성공을 보장하는 기능은 아닙니다.
Half Duplex RS-485에서는 송신과 수신이 같은 Bus를 공유할 수 있으므로 송수신 방향과 Timing을 고려해야 합니다.
Timeout·Retry·CRC·Packet Parser를 아무리 잘 구현해도 A/B 배선·Termination·Bias·Ground·Topology가 잘못되어 있으면 안정적인 통신을 만들 수 없습니다.
결국 RS-485 프로그래밍의 핵심은 단순히 Serial Port에 byte를 보내는 것이 아닙니다.
여러 장비가 하나의 Bus를 공유하는 환경에서 Address·Command·Response를 정확하게 연결하고, 불완전한 byte Stream을 Packet으로 복원하며, Timeout·CRC·Retry와 물리 Bus 상태까지 함께 관리하는 것이 핵심입니다.