HomeDigital Electronics › 8051 Microcontroller
MICROCONTROLLER

8051 Microcontroller

Complete reference: internal architecture, 40-pin diagram, memory map, all SFRs, timer modes, interrupt vectors, UART baud rate calculation, instruction set, and assembly examples.

8-bit CPU 4KB ROM 128B RAM 4 × 8-bit I/O Ports 2 × 16-bit Timers Full-duplex UART 5 Interrupts 12MHz Crystal

Internal Architecture

The 8051 is a Harvard architecture — separate address spaces for program memory (ROM) and data memory (RAM). All major peripherals are on-chip, connected via an internal 8-bit data bus.

CPU CORE ALU Accumulator B Reg PSW / Flags PC 16b SP 8b DPTR 16b R0–R7 (4 banks) Control Unit (Instruction Decoder + Sequencer) Internal 8-bit Data Bus Program ROM 4 KB Internal · 0x0000–0x0FFF +60KB external via PSEN Internal RAM 128 Bytes · 0x00–0x7F Reg banks + Bit-addr + GP SFR Space Special Function Regs 0x80–0xFF (21 registers) OSC / Clock 12 MHz Crystal ÷12 → 1 MHz machine cycle Timers 0 & 1 16-bit, 4 modes each TMOD · TCON TH0/TL0 · TH1/TL1 UART Full-duplex Serial SCON · SBUF Interrupts 5 sources, 2 priorities IE · IP · Vectors Port 0 AD0–AD7 Addr/Data mux Port 1 General I/O No alt function Port 2 A8–A15 High address byte Port 3 RXD TXD INT WR Alternate functions

Key Features

FeatureSpecification
CPU8-bit, Boolean processor, Harvard architecture
ClockUp to 12 MHz; 1 machine cycle = 12 clock periods
Program Memory4 KB internal ROM; up to 64 KB external via PSEN
Data Memory128 bytes internal RAM; up to 64 KB external via RD/WR
I/O Ports4 × 8-bit bidirectional (P0–P3) = 32 pins total
Timers2 × 16-bit (Timer 0, Timer 1) — 4 modes each
Serial PortFull-duplex UART — 4 modes; baud via Timer 1
Interrupts5 sources, 2 priority levels; 6 vectors
Instruction Set111 instructions; single-cycle to 4-cycle
Package40-pin DIP (standard), also PLCC, QFP variants
SupplyVCC = 5V (CMOS variants: 3.3V)

40-Pin DIP Pinout

8051 MCS-51 Family 123 456 789 101112 131415 1617 P1.0P1.1P1.2 P1.3P1.4P1.5 P1.6P1.7 RST P3.0/RXDP3.1/TXD P3.2/INT0P3.3/INT1 P3.4/T0P3.5/T1 P3.6/WRP3.7/RD 403938 373635 343332 313029 282726 2524 VCC (+5V) P0.0/AD0P0.1/AD1 P0.2/AD2P0.3/AD3 P0.4/AD4P0.5/AD5 P0.6/AD6P0.7/AD7 EA/VPP ALE/PROG PSEN P2.7/A15P2.6/A14 P2.5/A13P2.4/A12 P2.3/A11 XTAL2 (18) · XTAL1 (19) · GND (20) P2.0–P2.2 (21–23)

Memory Organization

Internal RAM (0x00–0x7F)

0x00–0x1F
Register Banks 0–3
R0–R7 × 4 banks (RS1,RS0 in PSW selects)
0x20–0x2F
Bit-Addressable Area
128 individually addressable bits (0x00–0x7F)
0x30–0x7F
General Purpose RAM
Stack grows upward from SP default 0x07
0x80–0xFF
SFR Space
Only specific addresses are valid SFRs

Program Memory (64KB)

0x0000–0x0FFF
Internal ROM (4KB)
EA=1 uses internal; EA=0 forces external
0x1000–0xFFFF
External ROM (60KB)
Accessed via PSEN, P0 (AD), P2 (A8–A15)
0x0000
Reset Vector
0x0003, 0x000B…
Interrupt Vectors

CPU Registers

Accumulator (ACC / A) — 0xE0

Primary working register for all ALU operations. Results of ADD, SUB, MUL, DIV, ANL, ORL, XRL all land here. Bit-addressable (ACC.0–ACC.7).

B Register — 0xF0

Second operand for MUL AB and DIV AB. MUL result: A=low byte, B=high byte. DIV result: A=quotient, B=remainder. Used as general-purpose otherwise.

Program Counter (PC) — 16-bit

Not directly addressable. Holds address of next instruction. Increments automatically. Modified by JMP, CALL, RET. Reset to 0x0000 on power-up or RST.

Stack Pointer (SP) — 0x81

8-bit. Default = 0x07 after reset. Stack grows upward (pre-increment on PUSH, post-decrement on POP). Stays in internal RAM; avoid SP > 0x7F.

Data Pointer (DPTR) — 0x82/0x83

16-bit register formed by DPH (0x83) and DPL (0x82). Used with MOVX (external RAM access) and MOVC (program memory table lookup). Only 16-bit register in 8051.

R0–R7 (Register Banks)

Four banks of 8 registers (R0–R7), each 8-bit. Active bank selected by RS1:RS0 bits in PSW. Bank 0 at 0x00–0x07, Bank 1 at 0x08–0x0F, Bank 2 at 0x10–0x17, Bank 3 at 0x18–0x1F.

PSW — Program Status Word (0xD0)

7
CY
6
AC
5
F0
4
RS1
3
RS0
2
OV
1
0
P
BitNameDescription
CYCarrySet by carry-out from bit 7 in ADD; borrow in SUBB; also used in bit operations
ACAux CarryCarry from bit 3 to bit 4; used by DA A (decimal adjust)
F0User FlagGeneral-purpose flag, set/cleared by software
RS1:RS0Reg Bank00=Bank0, 01=Bank1, 10=Bank2, 11=Bank3
OVOverflowSet if signed arithmetic overflows (carry into bit 7 ≠ carry out)
PParityHardware-set: 1 if ACC has odd number of 1s (even parity)

Special Function Registers (SFRs)

SFRAddressBit-addr?Function
P00x80YesPort 0 I/O latch (AD0–AD7, open-drain, needs pull-ups)
SP0x81NoStack Pointer — default 0x07 after reset
DPL0x82NoData Pointer low byte
DPH0x83NoData Pointer high byte
PCON0x87NoPower control; SMOD (bit 7) doubles UART baud rate
TCON0x88YesTimer control; TF1, TF0 overflow flags; TR1, TR0 run bits; IE1, IE0, IT1, IT0
TMOD0x89NoTimer mode select — upper nibble=Timer1, lower=Timer0
TL00x8ANoTimer 0 low byte
TL10x8BNoTimer 1 low byte
TH00x8CNoTimer 0 high byte
TH10x8DNoTimer 1 high byte (reload value in Mode 2)
P10x90YesPort 1 I/O latch (general-purpose only)
SCON0x98YesSerial control — SM0/SM1 mode, REN, TI, RI flags
SBUF0x99NoSerial buffer — write=transmit, read=receive (separate regs)
P20xA0YesPort 2 I/O latch (A8–A15 for external memory)
IE0xA8YesInterrupt enable — EA, ET2, ES, ET1, EX1, ET0, EX0
P30xB0YesPort 3 — alternate functions: RXD, TXD, INT0, INT1, T0, T1, WR, RD
IP0xB8YesInterrupt priority — PT2, PS, PT1, PX1, PT0, PX0
PSW0xD0YesProgram Status Word (see above)
ACC0xE0YesAccumulator
B0xF0YesB register (MUL/DIV operand)

Timer / Counter

Both timers are 16-bit up-counters. Each can count internal clock pulses (timer mode) or external pulses on T0 (P3.4) / T1 (P3.5) pins (counter mode). Configured via TMOD and TCON.

TMOD Register (0x89) — not bit-addressable

7
GATE
6
C/T̄
5
M1
4
M0
3
GATE
2
C/T̄
1
M1
0
M0

Upper nibble = Timer 1 · Lower nibble = Timer 0 · GATE=1: timer runs only when INTx pin is HIGH · C/T̄=0: timer, 1: counter

M1:M0ModeDescription
00Mode 013-bit timer (TH as 8-bit + TL lower 5-bit). Legacy MCS-48 compatible.
01Mode 116-bit timer/counter (TH:TL). Most commonly used. No auto-reload.
10Mode 28-bit auto-reload — TL counts, reloads from TH on overflow. Ideal for UART baud rate.
11Mode 3Timer 0 only: splits into two 8-bit timers (TL0 and TH0). Timer 1 stops.

Timer Delay Calculation

At 12 MHz: machine cycle = 1 µs. For a 50 ms delay in Mode 1 (16-bit):
Counts needed = 50,000. Initial value = 65536 − 50000 = 15536 = 0x3CB0
So: TH0 = 0x3C, TL0 = 0xB0, TMOD = 0x01, TR0 = 1, poll TF0.

Interrupt System

SourceVectorIE BitFlagTriggered by
External INT00x0003EX0 (IE.0)IE0 (TCON.1)P3.2 low-level or falling edge (IT0)
Timer 00x000BET0 (IE.1)TF0 (TCON.5)Timer 0 overflow
External INT10x0013EX1 (IE.2)IE1 (TCON.3)P3.3 low-level or falling edge (IT1)
Timer 10x001BET1 (IE.3)TF1 (TCON.7)Timer 1 overflow
Serial Port0x0023ES (IE.4)TI or RITransmit complete (TI) or byte received (RI)

Enable an interrupt: set its IE bit and set EA (IE.7). Priority: set the corresponding IP bit for high priority (high priority ISR can interrupt a low priority ISR).

Serial Port (UART)

SCON Register (0x98)

7
SM0
6
SM1
5
SM2
4
REN
3
TB8
2
RB8
1
TI
0
RI
SM0:SM1ModeDescriptionBaud Rate
000Shift register (synchronous), 8-bitfosc / 12
0118-bit UART (1 start, 8 data, 1 stop)Timer 1 Mode 2
1029-bit UART, fixed baudfosc/64 or fosc/32
1139-bit UART, variable baudTimer 1 Mode 2

Baud rate formula (Mode 1, SMOD=0): Baud = fosc ÷ (384 × (256 − TH1))
For 9600 baud at 11.0592 MHz: TH1 = 256 − (11059200 ÷ 384 ÷ 9600) = 256 − 3 = 0xFD

Instruction Set Summary

Data Transfer

MOV dst,src — internal move
MOVX A,@DPTR — external RAM read
MOVC A,@A+DPTR — program memory (tables)
PUSH / POP direct — stack operations
XCH A,Rn — exchange accumulator

Arithmetic

ADD A,src — A = A + src
ADDC A,src — A = A + src + CY
SUBB A,src — A = A − src − CY
MUL AB — 16-bit result in B:A
DIV AB — A=quotient, B=remainder
INC / DEC — increment/decrement
DA A — decimal adjust after ADD

Logical

ANL / ORL / XRL A,src — bitwise AND/OR/XOR
CLR A — A = 0
CPL A — A = ~A (complement)
RL / RLC A — rotate left (with/without CY)
RR / RRC A — rotate right
SWAP A — exchange nibbles of A

Branching

AJMP / LJMP addr — unconditional jump
SJMP rel — short relative jump (±127)
JZ / JNZ rel — jump if A=0 / A≠0
JC / JNC rel — jump on carry
DJNZ Rn,rel — decrement and jump if not zero
CJNE A,src,rel — compare and jump

Bit Operations

SETB bit — set bit to 1
CLR bit — clear bit to 0
CPL bit — complement bit
MOV C,bit / MOV bit,C — move to/from carry
ANL C,bit / ORL C,bit — bit AND/OR with carry
JB / JNB / JBC bit,rel — jump on bit

Subroutine / Misc

ACALL / LCALL addr — call subroutine (pushes PC)
RET — return from subroutine (pops PC)
RETI — return from interrupt (also clears priority)
NOP — no operation (1 machine cycle)
ORL / ANL direct,#data — direct bit manipulation

Assembly Code Examples

1 — LED Blink on P1.0

; Toggle P1.0 continuously with ~500ms delay at 12MHz
ORG    0000H
MAIN:
    SETB   P1.0          ; LED ON
    ACALL  DELAY500
    CLR    P1.0          ; LED OFF
    ACALL  DELAY500
    SJMP   MAIN

; ~500ms delay using nested loops (12 MHz → 1µs/cycle)
DELAY500:
    MOV    R0,#250
D1: MOV    R1,#250
D2: MOV    R2,#8
D3: DJNZ   R2,D3         ; 8 cycles ≈ 8µs
    DJNZ   R1,D2
    DJNZ   R0,D1
    RET
    END

2 — Timer 0 Mode 1 Interrupt (50ms)

; Timer 0 Mode 1 — 50ms interrupt at 12MHz, toggle P2.0
ORG    0000H
    LJMP   MAIN
ORG    000BH          ; Timer 0 interrupt vector
    LJMP   T0_ISR

ORG    0030H
MAIN:
    MOV    TMOD,#01H   ; Timer 0, Mode 1 (16-bit)
    MOV    TH0,#3CH    ; 65536-50000 = 15536 = 0x3CB0
    MOV    TL0,#0B0H
    SETB   ET0          ; Enable Timer 0 interrupt
    SETB   EA           ; Global interrupt enable
    SETB   TR0          ; Start timer
    SJMP   $            ; Wait (background loop)

T0_ISR:
    MOV    TH0,#3CH    ; Reload
    MOV    TL0,#0B0H
    CPL    P2.0         ; Toggle LED
    RETI
    END

3 — UART Transmit a Byte (9600 baud @ 11.0592 MHz)

; Initialize UART Mode 1, 9600 baud, transmit 'A'
ORG    0000H
MAIN:
    MOV    TMOD,#20H   ; Timer 1, Mode 2 (auto-reload)
    MOV    TH1,#0FDH   ; 9600 baud at 11.0592MHz
    MOV    TL1,#0FDH
    SETB   TR1          ; Start Timer 1
    MOV    SCON,#50H   ; Mode 1, REN=1 (receive enabled)

    MOV    A,#'A'       ; Character to send (0x41)
    MOV    SBUF,A       ; Load transmit buffer → starts TX
WAIT: JNB  TI,WAIT      ; Poll TI flag (set when TX done)
    CLR    TI           ; Clear TI manually
    SJMP   $
    END

4 — Lookup Table with MOVC

; Read 7-segment display code for digit in R0 (0–9)
ORG    0000H
MAIN:
    MOV    R0,#3        ; Digit to display = 3
    MOV    A,R0
    MOV    DPTR,#SEG_TABLE
    MOVC   A,@A+DPTR    ; A = SEG_TABLE[A]
    MOV    P1,A          ; Output to 7-seg on Port 1
    SJMP   $

SEG_TABLE:
    ; Common-cathode 7-segment codes for 0–9
    DB     3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
    END

Frequently Asked Questions

What is the difference between EA=0 and EA=1?

When EA=1 (pin 31 tied to VCC): the 8051 executes from internal ROM for addresses 0x0000–0x0FFF, then switches to external ROM for 0x1000–0xFFFF. When EA=0 (pin 31 tied to GND): all program memory is fetched externally even in the 0x0000–0x0FFF range — used when no internal ROM is present or for in-circuit programming.

Why is 11.0592 MHz crystal preferred for UART?

Standard baud rates (9600, 19200, 38400, 115200) are exact multiples of 11.0592 MHz when divided by Timer 1 Mode 2 prescaler chain. With 12 MHz, TH1 values produce fractional baud rates with ±0.16% error — acceptable for most links but 11.0592 MHz gives exactly 0% error. The formula: TH1 = 256 − (11059200 ÷ 384 ÷ baud).

What happens if the stack overflows into SFR space?

The internal RAM is only 128 bytes (0x00–0x7F). If SP exceeds 0x7F and the CPU executes PUSH or CALL, the data is written to addresses 0x80–0xFF which is the SFR space, corrupting SFR values silently. Best practice: keep SP below 0x60, limit subroutine nesting depth, and avoid large local variable usage in ISRs.

What is the difference between MOVX and MOVC?

MOVX accesses external data memory (via RD/WR strobes, DPTR or R0/R1). Used for external RAM chips. MOVC accesses program memory (via PSEN strobe). Used to read read-only tables stored in ROM. You cannot write to program memory at runtime with MOVC — it is read-only.