클럭 선 없이 양쪽이 미리 약속한 속도로 데이터를 주고받는 비동기 시리얼 통신 (Universal Asynchronous Receiver/Transmitter).
프레임 구조
유휴(High) ─┐ ┌─┬─┬─┬─┬─┬─┬─┬─┐ ┌─ 유휴
└─┤0│1│2│3│4│5│6│7├─┘
↑ └─────────────┘ ↑ ↑
시작비트 데이터 8비트 패리티 정지비트
(Low) (LSB 먼저) (선택) (High)
8N1 = 데이터 8비트, 패리티 없음(None), 정지 1비트 — 가장 흔한 설정이다.
클럭이 없는데 어떻게 동기를 맞추나
- ① 유휴 상태는 High
- ② 시작 비트(Low)의 하강 에지를 감지
- ③ 그 시점부터 미리 약속한 보율(baud rate)로 샘플링
- 보통 각 비트 구간의 중앙에서 (또는 3회 샘플링 후 다수결)
"시작 에지에서 타이머를 걸어 정해진 간격으로 읽는다" 가 전부다. 그래서 양쪽 속도가 정확히 같아야 한다.
보율 오차 — 실무에서 가장 흔한 문제
- 프레임 하나 = 시작 1 + 데이터 8 + 정지 1 = 10비트
- 마지막 비트까지 누적 오차가 반 비트(50%)를 넘으면 잘못 읽는다
- 한 비트당 허용 오차 약 5%
- 안전하게는 양쪽 합쳐 2~3% 이내
내부 RC 오실레이터(HSI)의 정확도가 ±1~2% 라, 양쪽이 반대 방향으로 치우치면 한계에 가까워진다. UART를 쓰면 외부 크리스털을 권장하는 이유다.
115200bps 를 만들려면 16MHz / 115200 = 138.9 → 정수 분주로는 139 → 실제 115108bps (오차 0.08%) ✓
8MHz / 115200 = 69.4 → 69 → 115942bps (오차 0.6%) ✓ 아직 괜찮다
11.0592MHz 같은 어중간한 크리스털이 존재하는 이유가 이것이다 — 표준 보율로 정확히 나누어떨어진다.
흐름 제어
- 없음(None) — : 수신 측이 못 따라가면 데이터 유실 하드웨어(RTS/CTS): 별도 신호선으로 "보내도 됨/멈춰" 소프트웨어(XON/XOFF): 특수 문자로 제어. 바이너리 데이터에는 부적합
고속에서 수신 버퍼가 넘치면 오버런이 발생한다. DMA + 링 버퍼를 쓰거나 흐름 제어를 켜야 한다.
오류 검출
| 오류 | 원인 |
|---|---|
| 프레이밍(FE) | 정지 비트 자리가 High가 아님 → 보율 불일치 또는 노이즈 |
| 패리티(PE) | 패리티가 맞지 않음 |
| 오버런(ORE) | 이전 데이터를 안 읽었는데 새 데이터 도착 |
| 노이즈(NE) | 샘플링 3회의 값이 일치하지 않음 |
프레이밍 에러가 계속 나오면 십중팔구 보율이 틀린 것이다. 글자가 깨져서 나오면 이것부터 확인한다.
RS-232 / RS-485 와의 관계
UART는 프로토콜(프레임 형식)이고, RS-232·RS-485는 전기 규격이다.
- MCU의 UART 핀 — : 0V / 3.3V (TTL 레벨)
- RS-232 — : +12V / -12V (반전!) → 레벨 시프터 필요 (MAX232)
- RS-485 — : 차동 신호 (A/B 두 선) → 트랜시버 필요
- USB-Serial — : FTDI, CP2102 칩이 변환
MCU끼리 직접 연결할 때는 TX↔RX 교차 연결만 하면 된다(GND 공통). "TX를 TX에 연결"하는 실수가 흔하다.
실무 구현 — DMA + 유휴 인터럽트
// 수신: 길이를 모르는 가변 패킷
HAL_UARTEx_ReceiveToIdle_DMA(&huart, buf, SIZE);
// 유휴 라인 검출 → 패킷 끝을 자동 판단
IDLE 인터럽트는 일정 시간 데이터가 없으면 발생한다. 가변 길이 패킷의 끝을 알아내는 표준 기법이다.
송신은 DMA로 보내고 완료 인터럽트에서 다음 버퍼를 큐잉한다. 바이트마다 인터럽트를 받으면 오버헤드가 크다.
디버깅
- 아무것도 안 나온다 — → TX/RX 교차? GND 공통? 클럭 인가?
- 글자가 깨진다 — → 보율 불일치 (오실로스코프로 비트 폭 측정)
- 가끔 깨진다 — → 오버런, 노이즈, 클럭 정확도
- 첫 글자만 이상하다 → 유휴 상태 준비 시간, 레벨 시프터 응답
오실로스코프로 1비트 폭을 재면 실제 보율을 알 수 있다. 115200bps면 한 비트가 8.68μs여야 한다.