UART 통신, 제대로 이해하기
임베디드를 시작하면 가장 먼저 만나는 통신 프로토콜, UART. "그냥 시리얼 통신이잖아요"라고 넘기기기엔 아는 만큼 보이는 게 달라집니다.
1. UART가 뭔가요?
UART는 Universal Asynchronous Receiver/Transmitter의 약자입니다.
이름을 풀어보면 그 자체로 설명이 됩니다.
| 단어 | 의미 |
| Universal | 다양한 디바이스와 호환 |
| Asynchronous | 클럭 신호 없이 통신 (비동기) |
| Receiver/Transmitter | 송신과 수신을 모두 담당 |
임베디드 개발을 하다 보면 UART를 가장 먼저, 가장 많이 만납니다. MCU와 PC를 연결해 디버깅 메시지를 출력하거나, 두 MCU끼리 데이터를 주고받을 때 쓰입니다.
2. 직렬 vs 병렬 통신
UART를 이해하려면 먼저 직렬(Serial) 통신이 무엇인지 알아야 합니다.
병렬 통신 (Parallel)
데이터: 0b10110101
선 8개 → 한 번에 8비트 전송
D7 ──────────────
D6 ──────────────
D5 ──────────────
...
D0 ──────────────
빠르지만 선이 많이 필요하고, 거리가 멀어질수록 신호 간 간섭(노이즈) 문제가 생깁니다.
직렬 통신 (Serial)
데이터: 0b10110101
선 1개 → 1비트씩 순서대로 전송
TX ─ 1 ─ 0 ─ 1 ─ 1 ─ 0 ─ 1 ─ 0 ─ 1 ──
선이 적고 안정적입니다. 느린 것처럼 보이지만, Baud Rate를 높이면 충분히 빠릅니다.
UART는 직렬 통신입니다.
3. UART의 동작 원리
연결 구조
UART는 단 2개의 선으로 통신합니다.
MCU A MCU B
TX ───────────────► RX
RX ◄─────────────── TX
GND ─────────────── GND ← 반드시 공통 GND!
GND를 꼭 연결해야 합니다. 전압 기준이 달라지면 신호를 제대로 읽지 못합니다.
비동기(Asynchronous)란?
I2C나 SPI 같은 통신은 클럭 신호(CLK)를 함께 보내서 "지금 데이터 읽어"라는 타이밍을 맞춥니다.
UART는 클럭이 없습니다. 그럼 어떻게 타이밍을 맞출까요?
송수신 양쪽이 미리 같은 속도 (Baud Rate)를 약속합니다.
약속된 속도를 기준으로 수신 측이 스스로 타이밍을 계산해 비트를 읽습니다.
이 "약속"이 조금이라도 어긋나면 데이터가 깨집니다. 그래서 파라미터 설정이 중요합니다.
4. 핵심 파라미터
UART를 쓸 때 반드시 양쪽이 동일하게 설정해야 하는 4가지입니다.
① Baud Rate (보드레이트)
1 초에 몇 비트를 전송하는가를 나타냅니다.
| 주요 Baud Rate | 특징 |
| 9600 | 가장 기본값, 느리지만 안정적 |
| 115200 | 임베디드 개발에서 가장 많이 씀 |
| 921600이상 | 고속, 노이즈에 민감 |
예를 들어 115200 bps라면, 1비트를 전송하는 데 걸리는 시간은 약 8.68 μs입니다.
② 데이터 비트 (Data Bits)
한 번에 전송하는 데이터의 비트 수입니다. 보통 8비트를 씁니다. (7비트도 가능)
③ 패리티 비트 (Parity Bit)
오류 검출을 위한 비트입니다. 보통 None(없음)으로 설정합니다.
| 설정 | 의미 |
| None | 패리티 없음 (가장 일반적) |
| Even | 1의 개수가 짝수가 되도록 |
| Odd | 1의 개수가 홀수가 되도 |
④ 스톱 비트 (Stop Bit)
프레임의 끝을 알리는 비트입니다. 보통 1비트를 씁니다.
📌 정리: "115200 8N1"
임베디드 개발에서 UART 설정을 간단히 표현할 때 이런 식으로 씁니다.
115200 8 N 1
│ │ │ └─ Stop bit: 1
│ │ └───── Parity: None
│ └───────── Data bits: 8
└─────────────── Baud Rate: 115200
5. UART 프레임 구조
실제로 데이터가 어떻게 전송되는지 프레임 구조를 보면 명확해집니다.
평상시 (Idle) → Start → D0 D1 D2 D3 D4 D5 D6 D7 → (Parity) → Stop → Idle
HIGH ─────┐ ┌──────────
│ S 0 1 0 1 0 0 0 1 N P │
LOW └──────────────────────────────────────────────┘
↑ ↑
Start bit (항상 LOW) Stop bit (항상 HIGH)
- Idle 상태: 아무것도 안 보낼 때는 HIGH를 유지합니다
- Start bit: 전송 시작을 알리는 LOW 신호 1비트
- Data bits: LSB(최하위 비트)부터 순서대로 전송
- Stop bit: 전송 종료를 알리는 HIGH 신호
6. UART vs USART
STM32 같은 MCU의 데이터시트를 보면 USART라는 용어가 자주 등장합니다.
| UART | USART | |
| 풀네임 | Universal Aysnc R/T | Universal Sync/Async R/T |
| 클럭 라인 | 없음 | 있음 (동기 모드 지원) |
| 일반 사용 | 비동기 통신 | 대부분 비동기로 사용 |
USART는 UART의 상위 호환입니다. 동기 모드 (SCLK 포함)도 지원하지만, 실제로는 대부분 비동기 (UART) 모드로 사용합니다.
7. 실제로 어디에 쓰이나요?
임베디드 개발에서 UART가 활약하는 대표적인 상황들입니다.
- 디버깅 (가장 중요!)
`printf()`로 변수값이나 상태 메시지를 PC 터미널에 출력합니다. 임베디드에서의 `console.log()`라고 생각하면 됩니다. - GPS 모듈 연동
GPS 모듈은 대부분 UART로 NMEA 포맷 데이터를 전송합니다. - 블루투스/Wi-Fi 모듈
HC-06, ESP8266 같은 모듈이 UART로 MCU와 통신합니다. - MCU 간 통신
두 MCU가 간단한 데이터를 주고받을 때 UART가 편리합니다.
8. 마치며
UART는 단순해 보이지만, 임베디드 개발의 기초 중 기초입니다.
Baud Rate가 다르면 데이터가 깨져서 해석이 불가능하다
GND를 연결하지 않으면 통신이 안 된다.
TX->RX, RX->TX로 교차 연결해야 한다.
이 세 가지만 기억해도 UART 관련트러블 슈팅의 절반은 해결됩니다.