← Embedded C 강의 목록으로
🔌
8051
8051 · 선수: 10강

11. UART 시리얼 통신

값을 "사람이 읽는 글자"로 PC와 주고받으려면 통신이 필요합니다. 가장 기본이 UART(시리얼)입니다 — 선 두 가닥(TXD/RXD)으로 텍스트를 주고받죠. UART는 비동기라 양쪽이 보율(baud)을 똑같이 약속해야 합니다. 8051은 SCON으로 모드를, Timer1로 보율을, SBUF로 한 바이트를 넣고 뺍니다. 9600bps·8N1로 문자열을 보내고, 보율 정확도를 위해 11.0592MHz를 쓰는 이유를 익힙니다.

UART시리얼보율SCONSBUF11.0592MHz
소요 시간
약 1.5~2시간
난이도
📊 중급
선수 조건
🎯 10강
결과물
SCON·Timer1·SBUF로 9600bps 8N1 UART를 초기화해 PC에 문자열을 송신하고, 보율 리로드(TH1)를 계산할 수 있습니다.

이 강의에서 배우는 것

  • 1동기/비동기 통신의 차이와 UART 프레임(start·data·stop)을 설명한다
  • 2SCON으로 Mode1(8비트 UART)과 수신 허용(REN)을 설정한다
  • 3Timer1(Mode2 자동 리로드)로 보율을 만들고 TH1을 계산한다
  • 4SBUF/TI/RI로 한 바이트를 송수신한다
  • 5UART용 11.0592MHz 크리스털을 쓰는 이유를 안다

소개

데이터를 한 비트씩 한 선으로 보내는 방식이 시리얼입니다. UART는 별도 클럭선 없이 동작하는 비동기 방식이라, 양쪽이 같은 보율(예 9600bps)로 맞춰 두는 것이 전제입니다. 연결은 보통 TXD(P3.1)·RXD(P3.0)·GND 세 가닥.

핵심 개념

1) 프레임 8N1

c
유휴(1) → [start=0] → [d0..d7] → [stop=1] → 유휴(1)
                       ↑ 데이터는 LSB(d0)부터!
/* 데이터8 · 패리티 없음(N) · 정지1 = 8N1 */

2) SCON 과 보율(Timer1)

표준 설정 `SCON = 0x50` → SM1=1(Mode1, 8비트 UART) + REN=1(수신 허용). 8051은 Timer1을 Mode2(8비트 자동 리로드)로 두고 오버플로 속도로 보율을 만듭니다.

c
보율 = Fosc / (384 × (256 - TH1))   (SMOD=0)
/* 11.0592MHz, 9600bps: n = 11059200/(384*9600) = 3 (정수!) → TH1 = 256-3 = 0xFD */
⚠️

11.0592MHz는 표준 보율에서 n이 정수로 떨어져 오차 0입니다. 12MHz는 9600에서 약 8.5% 오차가 나 통신이 깨집니다 — UART용 보드가 11.0592MHz를 쓰는 이유.

3) SBUF 송수신

c
void uart_tx(unsigned char c){ SBUF=c; while(TI==0); TI=0; }
unsigned char uart_rx(void){ while(RI==0); RI=0; return SBUF; }
/* TI/RI 는 하드웨어가 세우기만 함 — 소프트웨어가 매번 0으로 클리어해야 한다 */

핵심 예제

c
#include <reg52.h>
void uart_init(void){
    SCON = 0x50;            /* Mode1 + REN */
    TMOD &= 0x0F; TMOD |= 0x20;   /* Timer1 Mode2(보율) */
    TH1 = 0xFD; TL1 = 0xFD;       /* 9600 @ 11.0592MHz */
    TR1 = 1;
}
void uart_tx(unsigned char c){ SBUF=c; while(TI==0); TI=0; }
void uart_puts(const char *s){ while(*s) uart_tx((unsigned char)*s++); }
void main(void){ uart_init(); while(1){ uart_puts("Hello, 8051!\r\n"); } }

보율 리로드 검산(11.0592MHz): 1200→0xE8, 2400→0xF4, 4800→0xFA, 9600→0xFD. 시뮬레이터 View → Serial Windows → UART #1 창에서 출력을 확인합니다.

자주 하는 실수

Q. 한 글자는 나오는데 두 번째부터 멈춰요.

A. TI(송신 완료 플래그)를 클리어하지 않았습니다. 하드웨어는 TI를 1로 세우기만 하니 매 송신 후 TI=0; 으로 지워야 합니다(수신은 RI도).

Q. 글자가 깨져서 나와요.

A. 보율 불일치입니다. 터미널 보율을 9600으로, Xtal을 11.0592MHz로 맞췄는지 확인하세요. 12MHz면 TH1=0xFD라도 실제 ~10417bps라 깨집니다.

Q. 송신은 되는데 수신이 안 돼요.

A. SCON의 REN(수신 허용)을 안 켰을 수 있습니다(0x50은 REN=1 포함). RI를 읽은 뒤 클리어했는지도 확인하세요.

정리

  • UART는 클럭선 없는 비동기 시리얼 — 양쪽이 같은 보율로 약속한다
  • 프레임: start(0) → 데이터 8(LSB부터) → stop(1), 패리티 없으면 8N1
  • SCON=0x50(Mode1·REN), Timer1 Mode2(TMOD|=0x20)로 보율 생성
  • TH1 = 256 - Fosc/(384×보율). 11.0592MHz면 정수로 떨어진다
  • SBUF에 쓰면 송신·읽으면 수신. TI/RI는 매번 클리어한다

과제

  1. 받은 문자를 그대로 되돌려 보내는 에코(echo) 프로그램 작성(uart_rx → uart_tx)
  2. 4800bps·19200bps 의 TH1 값을 계산하고 pc_test 로 검산
  3. putchar 를 UART 송신으로 재정의해 printf 로 숫자를 출력(8051에서 무거운 이유도 설명)
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드(과제·정답 포함)는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗