8051 Microcontroller
Complete Programming
Assembly • Embedded Guide
C • Timers • Serial • Interrupts
1. Programming 8051 Using Assembly Language
Assembly language gives direct control over the 8051 hardware. Each instruction maps one-to-one to an opcode.
The 8051 uses a mnemonic-based ISA with four fields per line:
Field Purpose Example
Label Optional name for address START:
Mnemonic Operation code MOV, ADD, DJNZ
Operand Data or register #55H, A, R0
Comment Starts with semicolon ; Load 55H
Data Types & Directives
Directive Purpose Example
ORG Set code origin address ORG 0000H
DB Define byte data MSG DB 'A', 0DH
DW Define 16-bit word VAL DW 1234H
EQU Define constant symbol COUNT EQU 50
END End of source file END
Concept of Subroutine
A subroutine is a reusable code block invoked with LCALL (long) or ACALL (absolute). The PC is pushed to the
stack on call and restored by RET.
MAIN: MOV A, #10H
LCALL DELAY ; Call subroutine
SJMP $ ; Infinite loop
DELAY: MOV R0, #0FFH ; Load counter
LOOP: DJNZ R0, LOOP ; Decrement until 0
RET ; Return to caller
Software Delay Programming
At 12 MHz crystal, 1 machine cycle = 1 µs. Nested loops create precise delays.
DELAY_1MS:
MOV R1, #4 ; Outer loop (x4)
OUTER:
MOV R0, #0FFH ; Inner: 255 iterations
INNER:
DJNZ R0, INNER ; ~255 us per pass
DJNZ R1, OUTER ; 4 x 255us = ~1 ms
RET
Delay formula: Delay ≈ (R0 × R1 × 2) machine cycles × (12 / Fosc)
2. Programming 8051 Using Embedded C
Embedded C uses standard C extended with hardware-specific keywords. The popular compiler for 8051 is Keil
µVision (C51).
Advantage Description
Readable Far easier to write and maintain than assembly
Portable Code can be adapted to similar architectures
Debuggable Better tools and compiler diagnostics
Libraries Access to standard C math/string libraries
Speed Faster development cycle
#include <reg51.h> // 8051 SFR definitions
sbit LED = P1^0; // Bit-addressable port pin
void delay_ms(unsigned int ms) {
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 120; j++); // ~1ms at 12MHz
}
void main() {
while(1) {
LED = 1; // Turn LED on
delay_ms(500);
LED = 0; // Turn LED off
delay_ms(500);
}
}
3. Timer / Counter in 8051
The 8051 has two 16-bit timer/counters: Timer 0 and Timer 1. They share the TMOD (Timer Mode) and TCON
(Timer Control) SFRs.
TMOD Register (0x89) — Upper nibble = Timer 1, Lower nibble = Timer 0
Bit Name Function
7/3 GATE 1 = timer runs only when INTx pin is high
6/2 C/T 0 = timer mode (clock), 1 = counter mode (ext. pin)
5/1 M1 Mode select bit 1 (see mode table)
4/0 M0 Mode select bit 0
Timer Modes (M1:M0)
M1 M0 Mode Description
0 0 Mode 0 — 13-bit TH (8 bits) + TL lower 5 bits
0 1 Mode 1 — 16-bit TH (8 bits) + TL (8 bits), no auto-reload
1 0 Mode 2 — 8-bit auto TL counts, TH stores reload value
1 1 Mode 3 — Split Timer 0 splits into two 8-bit timers
Timer Mode 1 — 50 ms delay example (12 MHz)
void Timer0_50ms() {
TMOD = 0x01; // Timer0, Mode 1 (16-bit)
TH0 = 0xB3; // Reload: 65536 - 46083 = 19453 = 0x4BFD
TL0 = 0xFD;
TR0 = 1; // Start timer
while(TF0 == 0); // Wait for overflow flag
TR0 = 0; // Stop
TF0 = 0; // Clear overflow flag
}
Counter Mode
Set C/T = 1 in TMOD to count falling edges on T0 (P3.4) or T1 (P3.5). Used for counting encoder pulses, objects
on a conveyor, RPM sensing, etc.
4. Serial Communication in 8051
The 8051 has a built-in UART supporting full-duplex asynchronous serial. TXD = P3.1, RXD = P3.0. A MAX232
chip converts TTL levels to RS-232 ±12V levels.
RS-232 DB-9 Pinout
Pin Signal Direction Function
2 RxD In Receive data
3 TxD Out Transmit data
5 GND — Signal ground
7 RTS Out Request to send (handshake)
8 CTS In Clear to send (handshake)
SCON Register (Serial Control)
Bits Name Function
7-6 SM0:SM1 00=Mode 0, 01=Mode 1 (8-bit UART), 10=Mode 2, 11=M
4 REN Receive Enable — must be 1 to receive data
1 TI Transmit Interrupt — set when byte TX complete
Bits Name Function
0 RI Receive Interrupt — set when byte RX complete
Serial port programming — 9600 baud at 11.0592 MHz
TMOD = 0x20; // Timer1 Mode 2 (8-bit auto-reload)
TH1 = 0xFD; // 9600 baud at 11.0592 MHz
SCON = 0x50; // Mode 1, REN=1
TR1 = 1; // Start Timer1
void uart_tx(char ch) {
SBUF = ch; // Load transmit buffer
while(TI == 0); // Wait until TX complete
TI = 0; // Clear flag
}
char uart_rx() {
while(RI == 0); // Wait for received byte
RI = 0; // Clear flag
return SBUF; // Return data
}
5. Programming the Interrupts
The 8051 supports 5 interrupt sources with two priority levels. The IE register enables individual interrupts; EA is
the global enable. The IP register sets priority.
Interrupt Vector Table
Source Flag Vector Addr IE Bit ISR No.
External INT0 (P3.2) IE0 0003H EX0 (bit0) 0
Timer 0 overflow TF0 000BH ET0 (bit1) 1
External INT1 (P3.3) IE1 0013H EX1 (bit2) 2
Timer 1 overflow TF1 001BH ET1 (bit3) 3
Serial port (TI/RI) TI/RI 0023H ES (bit4) 4
IE Register (0xA8) bit layout
EA (bit7) | — | ET2 | ES | ET1 | EX1 | ET0 | EX0 (bit0) EA=1 enables all; individual bits selectively enable each source.
IP Register (0xB8) — Interrupt Priority
Set IP bit = 1 for HIGH priority, 0 for LOW priority. A high-priority ISR can preempt (interrupt) a running low-priority ISR.
Same priority ISRs cannot preempt each other.
Interrupt programming in Embedded C (Keil)
#include <reg51.h>
void ext0_isr(void) interrupt 0 { // External INT0
P1 = ~P1; // Toggle Port 1
}
void timer0_isr(void) interrupt 1 { // Timer 0
TH0 = 0xB3; TL0 = 0xFD; // Reload for 50ms
P2_0 = ~P2_0; // Toggle LED
}
void serial_isr(void) interrupt 4 { // Serial port
if(RI) { RI = 0; P1 = SBUF; } // Echo received byte
}
void main() {
EA = 1; EX0 = 1; ET0 = 1; ES = 1; // Enable
IT0 = 1; // INT0: falling edge trigger
IP = 0x02; // Timer 0 = high priority
// ... init timer and serial ...
while(1);
}
Quick Reference Summary
Topic Key Registers Key Concept
Assembly A, R0-R7, DPTR LCALL/RET for subroutines; DJNZ for loops
Timers TMOD, TCON, TH/TL Mode 2 = 8-bit auto-reload; Mode 1 = 16-bit
Counter TMOD bit C/T=1 Counts falling edges on T0/T1 pins
Serial SCON, SBUF, TMOD Timer1 Mode 2 = baud rate; TI/RI = status
Interrupts IE, IP, TCON EA = global enable; interrupt N in Keil C
8051 Microcontroller Programming Guide • Generated by Claude