In short: The 8051 has five interrupt sources (two external, two timer, one serial) that vector to fixed addresses 3 bytes apart starting at 0003H, are individually unmasked through the IE register and ranked into two priority levels through the IP register, so the CPU can suspend mainline code, run a short ISR, and return exactly where it left off.
Why interrupts matter on the 8051
Polling wastes cycles. If your firmware sits in a while(!TF0); loop waiting for a timer to roll over, the CPU can do nothing else and your latency is at the mercy of the loop. Interrupts invert the control flow: the hardware event asserts a flag, and the processor automatically diverts execution into a service routine the instant the current instruction finishes. On a classic 12-clock 8051 running at 12 MHz, each machine cycle is 1 µs, and the interrupt latency is typically 3 to 8 machine cycles depending on what instruction is executing and whether a higher- or equal-priority ISR is already active. That bounded, predictable response is exactly what you need for a UART that must be emptied before the next byte arrives, or a motor-control loop that must fire on a fixed timer tick.
Key fact: The 8051 core recognizes exactly 5 interrupt sources. The enhanced 8052 adds a sixth (Timer 2), vectoring at 002BH — but the baseline 8051 interview answer is five.
The five interrupt sources
Each source has a flag bit, a vector, and an enable bit. Learn the table below cold — it comes up in almost every embedded interview.
| Source | Flag | Vector (byte) | IE enable bit |
|---|---|---|---|
| External 0 (INT0, pin P3.2) | IE0 | 0003H | EX0 |
| Timer 0 overflow | TF0 | 000BH | ET0 |
| External 1 (INT1, pin P3.3) | IE1 | 0013H | EX1 |
| Timer 1 overflow | TF1 | 001BH | ET1 |
| Serial port (TX or RX) | TI / RI | 0023H | ES |
Two subtleties interviewers probe. First, the external interrupts can be edge- or level-triggered, selected by the IT0/IT1 bits in the TCON register: set IT0=1 for a falling-edge trigger, IT0=0 for an active-low level trigger. For edge mode the hardware sets IE0 and clears it automatically on entry; for level mode the pin must be released high before the ISR returns, or the interrupt re-fires. Second, the serial interrupt is shared — both TI (transmit complete) and RI (receive complete) vector to 0023H, so your ISR must test both flags and clear whichever fired, because the hardware does not clear TI or RI for you.
Vector addresses and why they are 8 bytes apart
The vectors sit at 0003H, 000BH, 0013H, 001BH, 0023H — a spacing of 8 bytes. That is deliberate: a trivial ISR can live entirely inside those 8 bytes, but a real ISR rarely does. The standard practice is to place a single jump instruction at the vector (LJMP myISR, 3 bytes) that redirects to the real handler elsewhere in code memory. Reset itself vectors to 0000H, which is why startup code typically begins with an LJMP main past the interrupt block.
Key fact: When an interrupt is accepted, the hardware pushes the 16-bit PC onto the stack and loads it with the vector — equivalent to an automatic LCALL. The matching RETI pops the PC and clears the internal "priority-active" latch, which a plain RET would not do.
The IE register: masking individual sources
IE (Interrupt Enable, address A8H, bit-addressable) is the gatekeeper. Bit 7 (EA) is the global enable: with EA=0 no interrupt is served regardless of the other bits. The layout is EA – – ES ET1 EX1 ET0 EX0. A common bring-up pattern in 8051 C (Keil C51) looks like this:
EA = 1; // global enable
ET0 = 1; // enable Timer 0 interrupt
ES = 1; // enable serial interrupt
A frequent bug: forgetting to set EA. Every per-source bit can be correct and nothing fires because the master switch is off. In assembly the one-shot equivalent is MOV IE,#92H (EA + ES + ET0).
Priority levels: the IP register
The 8051 supports just two priority levels — high (1) and low (0) — set per source in the IP register (address B8H). A high-priority ISR can interrupt a low-priority one, but not vice versa, and a source can never interrupt itself or another at the same level. When two sources at the same level are pending simultaneously, a fixed internal polling order breaks the tie, from highest: INT0, Timer0, INT1, Timer1, Serial. So with default IP=00H, external 0 always wins over the serial port.
Writing a correct ISR
An ISR must do three things well: enter fast, touch only what it owns, and leave the machine exactly as it found it. In C51 you declare the handler with the interrupt keyword and a vector number (0–4), and the compiler generates the context save/restore and the RETI:
void timer0_isr(void) interrupt 1 // vector 1 = Timer 0
{
TF0 = 0; // (auto-cleared on entry, shown for clarity)
tick++; // short, deterministic work only
}
Rules that separate working firmware from flaky firmware: keep ISRs short (no blocking delays, no printf); clear only serial flags manually (TI/RI), since timer and edge-external flags are cleared by hardware; mark shared variables volatile so the optimizer does not cache them; and if a variable is wider than one byte, guard the read in main with a brief interrupt disable to avoid a torn read. When ISRs nest, the C51 compiler can share register banks — use using 1 to give a high-priority ISR its own bank and avoid an expensive push/pop sequence. For verification, a logic analyzer or a cycle-accurate simulator (Keil µVision's simulator, or an 8051 model in a Cadence/Siemens co-simulation flow) lets you measure real latency rather than guess it. These same discipline rules carry straight over to the interrupt controllers on ARM Cortex-M parts you will meet next.
FAQ
How many interrupts does the 8051 have?
Five on the base 8051: two external (INT0, INT1), two timer (Timer 0, Timer 1), and one serial. The 8052 variant adds a sixth for Timer 2.
What is the difference between RET and RETI?
Both pop the return address, but RETI also clears the interrupt-in-progress flip-flop so the priority logic will accept the same or lower-level interrupts again. Using RET to leave an ISR leaves that latch set and silently blocks future interrupts.
Why does the serial ISR need to check flags manually?
TI and RI share one vector and are not auto-cleared. The ISR must test which one fired, service it, and clear it, or it will re-enter immediately.
Can a low-priority interrupt pause a high-priority ISR?
No. A high-priority ISR runs to completion (its RETI) before any low-priority request is served. Only a higher level preempts a running ISR.
Ready to go from theory to a blinking, byte-pumping board? Explore the hands-on 8051 and embedded C track on CourseTron courses and write your first interrupt-driven UART driver this week.
Related reading: master the peripherals that fire most of these interrupts in our 8051 timers and counters guide, and see how the shared serial interrupt is actually used in 8051 serial communication. For teams building custom silicon around an 8051 or RISC core, our sister brand offers professional VLSI design services.