06. 8051 구조·SFR·reg52.h
1~5편의 토대 위에서 드디어 실제 칩에 올라섭니다. 첫 주인공은 임베디드 교육의 고전 8051(AT89C52)입니다. 8051의 주변장치(포트·타이머·시리얼·인터럽트)는 모두 SFR(특수 기능 레지스터)로 제어합니다. Keil C51의 <reg52.h> 가 SFR을 이름으로 미리 선언해 둬서 P1 = 0x0F; 처럼 변수에 대입하듯 하드웨어를 다룹니다. 포트에 쓰는 두 방법(전체 / sbit 비트)을 익힙니다.
이 강의에서 배우는 것
- 18051의 기본 구조(CPU·ROM/RAM·포트·타이머·시리얼·인터럽트)를 개략한다
- 2SFR이 무엇이고 메모리 어디(0x80~0xFF)에 위치하는지 설명한다
- 3<reg52.h> 가 SFR을 이름으로 노출하는 방식을 이해한다
- 4포트 전체 쓰기(P1 = ...)와 비트 쓰기(sbit)를 구분해 쓴다
- 5C51 전용 키워드 sfr·sbit·bit 의 쓰임을 안다
소개
8051은 구조가 단순하고 레지스터가 적어 "C로 하드웨어를 어떻게 만지는가"를 배우기에 가장 좋은 칩입니다. 이 트랙의 8051 예제는 μVision 내장 시뮬레이터(Peripherals → I/O-Ports)에서 검증하며, 실제 보드는 필요 없습니다.
핵심 개념
1) 8051 한눈에 보기
| 자원 | 내용 |
|---|---|
| CPU | 8비트, 누산기(ACC) 중심 |
| 메모리 | 코드 ROM(8KB), 내부 RAM 256B + SFR |
| 입출력 | 4개 8비트 포트 P0~P3 |
| 타이머/시리얼 | Timer0/1(+T2), UART 1채널 |
8051에서 int 는 16비트입니다(2편). 8비트로 충분한 값은 unsigned char(uint8_t)로 RAM·코드 크기를 아낍니다.
2) SFR — 특수 기능 레지스터
SFR은 주변장치를 제어하는 레지스터로 내부 RAM 0x80~0xFF 영역에 배치됩니다. 주소가 8의 배수(0x80·0x88·0x90…)인 SFR(P0~P3·TCON·SCON·IE 등)은 sbit 으로 개별 비트 접근(bit-addressable)이 가능합니다.
| SFR | 주소 | 역할 |
|---|---|---|
| P1 | 0x90 | 포트 1 |
| TMOD | 0x89 | 타이머 모드 |
| SCON | 0x98 | 시리얼 제어 |
| IE | 0xA8 | 인터럽트 인에이블 |
3) <reg52.h> 와 포트 쓰기 두 방법
#include <reg52.h> /* sfr P1 = 0x90; 등을 미리 선언 */
P1 = 0x0F; /* (1) 포트 전체 쓰기: 하위 4비트=1 */
sbit LED0 = P1 ^ 0; /* (2) sbit: P1 의 0번 비트에 이름 (파일 범위) */
LED0 = 1; /* P1.0 만 1, 나머지 비트는 그대로 */`P1 ^ 0` 의 ^ 는 XOR이 아니라 "P1의 0번 비트"를 뜻하는 C51 전용 표기입니다. sfr·sbit·bit 은 표준 C에 없는 Keil C51 확장이라 이 main.c 는 PC gcc 로 컴파일되지 않습니다(로직은 pc_test.c 로).
핵심 예제
포트 전체 쓰기 후 개별 비트를 조작한 최종값을 PC에서 검산합니다(SFR을 일반 변수로 흉내).
#include <stdio.h>
int main(void) {
unsigned char P1 = 0x0F; /* 전체 쓰기 */
P1 = (unsigned char)(P1 & ~(1u << 0)); /* LED0 = 0 */
P1 = (unsigned char)(P1 | (1u << 7)); /* LED7 = 1 */
printf("P1 = 0x%02X\n", P1); /* 0x8E */
return 0;
}시뮬레이터: Peripherals → I/O-Ports → Port 1 창에서 P1 = 0x8E(1000 1110) 패턴을 확인합니다.
자주 하는 실수
Q. gcc 로 main.c 를 컴파일하니 reg52.h 가 없대요.
A. <reg52.h>·sfr·sbit 은 Keil C51 전용입니다. 디바이스 main.c 는 μVision에서만 빌드됩니다. PC에서는 pc_test.c(표준 C)로 로직만 검산하세요.
Q. sbit LED = P1 ^ 0; 을 함수 안에 썼더니 오류가 나요.
A. sfr/sbit 선언은 파일 범위(전역)에 둬야 합니다. 함수 안에서는 선언할 수 없으니 main 위쪽에 두세요.
Q. 큰 카운터에 int 를 썼더니 이상해요.
A. 8051에서 int 는 16비트입니다. 8비트면 충분한 포트 값/카운터는 unsigned char 를, 큰 수는 unsigned int(16비트)/unsigned long(32비트)을 명시하세요.
정리
- 8051은 단순한 8비트 MCU로 주변장치를 SFR(0x80~0xFF)로 제어한다
- <reg52.h> 가 P1·TMOD·IE 등 SFR을 이름으로 제공한다
- 포트는 전체 쓰기(P1 = 0x0F)와 비트 쓰기(sbit)로 다룬다
- sfr·sbit·bit 은 C51 전용이라 PC gcc 로는 안 된다(로직은 pc_test.c)
- 8비트로 충분한 값엔 unsigned char 로 자원을 아낀다
과제
- P1 에 0xAA 를 쓴 뒤 sbit 으로 P1.0 과 P1.7 만 반전한 결과를 예측하고 pc_test 로 검산
- P2 의 하위 4비트만 켜고 상위 4비트는 보존하는 코드를 마스크로 작성
- μVision에서 AT89C52 빈 프로젝트를 만들고 Port 1 창으로 P1 값 변화를 관찰