MODULE – 4
Interrupt Programming
Basics of Interrupts
An interrupt is a mechanism by which a microcontroller's normal execution flow is
temporarily paused to respond to important events. After handling the event called the
Interrupt Service Routine (ISR), the processor resumes its previous task.
Polling is a technique where the microcontroller continuously checks (or polls) the status of a
device or flag to determine if an event (like data arrival or timer overflow) has occurred. It is
a software-based mechanism for managing events.
Interrupt vs Polling – 8051 Microcontroller
Feature Interrupt Polling
Definition CPU is notified when an event CPU constantly checks (polls)
occurs via an interrupt signal status flags of devices
CPU Passive until event occurs; active Actively checks devices all the
Involvement only during ISR time
Efficiency High – CPU can perform other tasks Low – CPU time is wasted
in the meantime during waiting
Complexity More complex – requires ISR and Simple to implement
configuration
Response Time Fast – immediate response to event Slow – delay depends on polling
frequency
Power Lower – CPU can enter low-power Higher – CPU stays active and
Consumption modes until needed checks continuously
Best Used For Real-time and asynchronous events Simple, regular, or time-
insensitive events
Example in 8051 Serial data arrival triggers an CPU checks RI flag in a loop to
interrupt (RI flag) see if data is received
Code Overhead Slightly higher – need ISR and Lower – simple loops and flag
registers setup (IE, IP) checking
Steps in executing an interrupt
Upon activation of an interrupt, the microcontroller goes through the following steps.
1. It finishes the instruction it is executing and saves the address of the next instruction (PC)
on the stack.
2. It also saves the current status of all the interrupts internally (i.e., not on the stack).
3. It jumps to a fixed location in memory called the interrupt vector table that holds the
address of the interrupt service routine.
4. The microcontroller gets the address of the ISR from the interrupt vector table and jumps
to it. It starts to execute the interrupt service subroutine until it reaches the last instruction
of the subroutine, which is RETI (return from interrupt).
5. Upon executing the RETI instruction, the microcontroller returns to the place where it
was interrupted. First, it gets the program counter (PC) address from the stack by popping
the top two bytes of the stack into the PC. Then it starts to execute from that address.
Notice from Step 5 the critical role of the stack. For this reason, we must be careful in
manipulating the stack contents in the ISR. Specifically, in the ISR, just as in any CALL
subroutine, the number of pushes and pops must be equal.
Six interrupts in the 8051
In reality, only five interrupts are available to the user in the 8051, but many manufacturers’
data sheets state that there are six interrupts since they include reset. The six interrupts in the
8051 are allocated as follows.
1. Reset. When the reset pin is activated, the 8051 jumps to address location 0000.
2. Two interrupts are set aside for the timers: one for Timer 0 and one for Timer 1. Memory
locations 000BH and 001BH in the interrupt vector table belong to Timer 0 and Timer 1,
respectively.
3. Two interrupts are set aside for hardware external hardware interrupts. Pin numbers 12
(P3.2) and 13 (P3.3) in port 3 are for the external hardware interrupts INT0 and INT1,
respectively. These external interrupts are also referred to as EX1 and EX2. Memory
locations 0003H and 0013H in the interrupt vector table are assigned to INT0 and INT1,
respectively.
4. Serial communication has a single interrupt that belongs to both receive and transmit. The
interrupt vector table location 0023H belongs to this interrupt.
Interrupt Vector Table
When an interrupt occurs, the 8051 automatically jumps to a fixed memory location (called
the vector address) to execute the corresponding Interrupt Service Routine (ISR).
Interrupt Source Type Vector Priority Level Trigger Condition
Address
(Hex)
Reset System 0000H Highest Power-on or external reset
External Interrupt 0 Externa 0003H Programmable Falling edge / level on INT0
l (P3.2)
Timer 0 Overflow Internal 000BH Programmable Timer 0 overflows
External Interrupt 1 Externa 0013H Programmable Falling edge / level on INT1
l (P3.3)
Timer 1 Overflow Internal 001BH Programmable Timer 1 overflows
Serial Internal 0023H Programmable RI (Receive) or TI
Communication (Transmit)
Note:
The vector address is where the ISR should begin.
After the ISR finishes, it must end with the RETI instruction to return to the main
program.
The IE (Interrupt Enable) and IP (Interrupt Priority) registers are used to manage
these interrupts.
IE (Interrupt Enable) Register
The IE (Interrupt Enable) register is an 8-bit special function register (SFR) at address
A8H. It is used to enable or disable individual interrupts and globally enable/disable all
interrupts.
Steps in enabling an interrupt: To enable an interrupt, we take the following steps:
1. Bit D7 of the IE register (EA) must be set to high to allow the rest of the register to take
effect.
2. If EA = 1, interrupts are enabled and will be responded to if their corresponding
bits in IE are high. If EA = 0, no interrupt will be responded to, even if the associated bit in
the IE register is high.
Show the instructions to (a) enable the serial interrupt, Timer 0 interrupt, and external
hardware interrupt 1 (EX1), and (b) disable (mask) the Timer 0 interrupt, then (c) show
how to disable all the interrupts with a single instruction.
Solution:
(a) MOV IE,#10010110B ; enable serial, Timer 0, EX1
Since IE is a bit-addressable register, we can use the following instructions to access
individual bits of the register.
(b) CLR IE.1 ; mask (disable) Timer 0 interrupt only
(c) CLR IE.7 ; disable all interrupts
Another way to perform the “MOV IE, #10010110B” instruction is by using single-bit
instructions as shown below.
SETB IE.7 ; EA=1, Global enable
SETB IE.4 ; enable serial interrupt
SETB IE.1 ; enable Timer 0 interrupt
SETB IE.2 ; enable EX1
Programming Timer Interrupts
The 8051 has two timers: Timer 0 and Timer 1. These timers can be configured to generate
interrupts when they overflow, allowing precise timing without constantly polling flags.
Figure: TF Interrupt
Write a program that continuously gets 8-bit data from P0 and sends it to P1 while
simultaneously creating a square wave of 200 μs period on pin P2.1. Use Timer 0 to create
the square wave. Assume that XTAL = 11.0592 MHz.
Solution:
We will use Timer 0 in mode 2 (auto-reload). TH0 = 100/1.085 μs = 92.
Upon wake-up go to main, avoid using memory space allocated to Interrupt Vector Table
ORG 0000H
LJMP MAIN ;bypass interrupt vector table
ISR for Timer 0 to generate square wave
ORG 000BH ;Timer 0 interrupt vector table
CPL P2.1 ;toggle P2.1 pin
RETI ;return from ISR
The main program for initialization
ORG 0030H ;after vector table space
MAIN: MOV TMOD,#02H ;Timer 0, mode 2(auto-reload)
MOV P0,#0FFH ;make P0 an input port
MOV TH0,#-92 ;TH0=A4H for -92
MOV IE,#82H ;IE=10000010(bin) enable Timer 0
SETB TR0 ;Start Timer 0
BACK: MOV A,P0 ;get data from P0
MOV P1,A ;issue it to P1
SJMP BACK ;keep doing it loop unless interrupted by TF0
END
1. We must avoid using the memory space allocated to the interrupt vector table.
Therefore, we place all the initialization codes in memory starting at30H. The LJMP
instruction is the first instruction that the 8051 executes when it is powered up. LJMP
redirects the controller away from the interrupt vector table.
2. The ISR for Timer 0 is located starting at memory location 000BH since it is small
enough to fit the address space allocated to this interrupt.
3. We enabled the Timer 0 interrupt with “MOV IE,#10000010B” in MAIN.
4. While the P0 data is brought in and issued to P1 continuously, whenever Timer 0 is
rolled over, the TF0 flag is raised, and the microcontroller gets out of the “BACK”
loop and goes to 0000BH to execute the ISR associated with Timer 0.
5. In the ISR for Timer 0, notice that there is no need for a “CLR TF0” instruction
before the RETI instruction. This is because the 8051 clears the TF flag internally
upon jumping to the interrupt vector table.
External interrupts INT0 and INT1
INT0 (P3.2) and INT1 (P3.3) are two pins on the 8051 microcontroller used to receive
asynchronous external signals that trigger interrupt service routines (ISRs) when activated.
There are two types of activation for the external hardware interrupts: (1) level triggered and
(2) edge triggered.
Level-Triggered Interrupt: In the level-triggered mode, INT0 and INT1 pins are
normally high (just like all I/O port pins) and if a low-level signal is applied to them, it
triggers the interrupt. Then the microcontroller stops whatever it is doing and jumps to the
interrupt vector table to service that interrupt. This is called a level-triggered or level-
activated interrupt and is the default mode upon reset of the 8051. The low-level signal at the
INT pin must be removed before the execution of the last instruction of the interrupt service
routine, RETI; otherwise, another interrupt will be generated. In other words, if the low-level
interrupt signal is not removed before the ISR is finished, it is interpreted as another interrupt
and the 8051 jumps to the vector table to execute the ISR again.
Trigger Condition: Interrupt is activated as long as the external pin is held low.
TCON Register Bit: IT0 = 0 (for INT0), IT1 = 0 (for INT1)
Behavior:
o As long as the pin (P3.2/P3.3) remains low, the interrupt is active.
o Multiple entries into the ISR are possible if the signal stays low.
o Must manually clear the interrupt flag in software.
In this program, the microcontroller is looping continuously in the HERE loop. Whenever the
switch on INT1 (pin P3.3) is activated, the microcontroller gets out of the loop and jumps to
vector location 0013H. The ISR for INT1 turns on the LED, keeps it on for a while, and turns
it off before it returns. If by the time it executes the RETI instruction the INT1 pin is still low,
the microcontroller initiates the interrupt again. Therefore, to end this problem, the INT1 pin
must be brought back to high by the time RETI is executed.
Sampling the low-level triggered interrupt: Pins P3.2 and P3.3 are used for normal I/O
unless the INT0 and INT1 bits in the IE registers are enabled. After the hardware interrupts in
the IE register are enabled, the controller keeps sampling the INTn pin for a lowlevel signal
once each machine cycle. According to one manufacturer’s data sheet, “the pin must be held
in a low state until the start of the execution of ISR. If the INTn pin is brought back to a logic
high before the start of the execution of ISR there will be no interrupt.” However, upon
activation of the interrupt due to the low level, it must be brought back to high before the
execution of RETI. Again, according to one manufacturer’s data sheet, “If the INTn pin is left
at a logic low after the RETI instruction of the ISR, another interrupt will be activated after
one instruction is executed.” Therefore, to ensure the activation of the hardware interrupt at
the INT pin, make sure that the duration of the low-level signal is around 4 machine cycles,
but no more. This is due to the fact that the level-triggered interrupt is not latched. Thus the
pin must be held in a low state until the start of the ISR execution.
Edge-triggered interrupts
As stated before, upon reset the 8051 makes INT0 and INT1 lowlevel triggered interrupts. To
make them edge-triggered interrupts, we must program the bits of the TCON register. The
TCON register holds, among other bits, the IT0 and IT1 flag bits that determine level- or
edge-triggered mode of the hardware interrupts. IT0 and IT1 are bits D0 and D2 of the TCON
register, respectively. They are also referred to as TCON.0 and TCON.2 since the TCON
register is bit-addressable. Upon reset, TCON.0 (IT0) and TCON.2 (IT1) are both 0s,
meaning that the external hardware interrupts of INT0 and INT1 pins are low-level triggered.
By making the TCON.0 and TCON.2 bits high with instructions such as “SETB TCON.0”
and “SETB TCON.2”, the external hardware interrupts of INT0 and INT1 become edge-
triggered. For example, the instruction “SETB CON.2” makes INT1 what is called an edge-
triggered interrupt, in which, when a high-to-low signal is applied to pin P3.3, the controller
will be interrupted and forced to jump to location 0013H in the vector table to service the ISR
(assuming that the interrupt bit is enabled in the IE register).
Trigger Condition: Interrupt is activated on the falling edge (high-to-low transition) of the
signal.
TCON Register Bit: IT0 = 1 (for INT0), IT1 = 1 (for INT1)
Behavior:
Interrupt is triggered only once when the signal transitions from high to low.
8051 hardware automatically clears the interrupt flag after ISR execution.
When the falling edge of the signal is applied to pin INT1, the LED will be turned on
momentarily. The LED’s on-state duration depends on the time delay inside the ISR for
INT1. To turn ON the LED again, another high-to-low pulse must be applied to pin 3.3. In
Example, due to the level-triggered nature of the interrupt, as long as INT1 is kept at a low
level, the LED is kept in the ON state. But in this example, to turn ON the LED again, the
INT1 pulse must be brought back high and then forced low to create a falling edge to activate
the interrupt.
Sampling the edge-triggered interrupt: In edge-triggered interrupts, the external source
must be held high for at least one machine cycle, and then held low for at least one machine
cycle to ensure that the transition is seen by the microcontroller. The falling edge is latched
by the 8051 and is held by the TCON register. The TCON.1 and TCON.3 bits hold the
latched falling edge of pins INT0 and INT1, respectively. TCON.1 and TCON.3 are also
called IE0 and IE1, respectively. They function as interrupt-in-service flags. When an
interrupt-in-service flag is raised, it indicates to the external world that the interrupt is being
serviced and no new interrupt on this INTn pin will be responded to until this service is
finished. This is just like the busy signal you get if calling a telephone number that is in use.
Regarding the IT0 and IT1 bits in the TCON register, the following two points must be
emphasized.
1. The first point is that when the ISRs are finished (i.e., upon execution of instruction
RETI), these bits (TCON.1 and TCON.3) are cleared, indicating that the interrupt is
finished and the 8051 is ready to respond to another interrupt on that pin. For another
interrupt to be recognized, the pin must go back to a logic high state and be brought back
low to be considered an edge-triggered interrupt.
2. The second point is that while the interrupt service routine is being executed, the INTn
pin is ignored, no matter how many times it makes a high-to-low transition. In reality, one
of the functions of the RETI instruction is to clear the corresponding bit in the TCON
register (TCON.1 or TCON.3). This informs us that the service routine is no longer in
progress and has finished being serviced. For this reason, TCON.1 and TCON.3 in the
TCON register are called interrupt-in-service flags. The interrupt-in-service flag goes
high whenever a falling edge is detected at the INT pin, and stays high during the entire
execution of the ISR. It is only cleared by RETI, the last instruction of the ISR. Because
of this, there is no need for an instruction such as “CLR TCON.1” (or “CLR TCON.3” for
INT1) before the RETI in the ISR associated with the hardware interrupt INT0. As we
will see in the next section, this is not the case for the serial interrupt.
The TCON (Timer Control) register is an 8-bit Special Function Register (SFR) at address
88H. It controls timer/counter start, external interrupt triggering, and interrupt flags.
Timer Bits
TF1 / TF0: Set when the respective timer overflows.
TR1 / TR0: Used to start/stop Timer 1 and Timer 0.
�External Interrupt Bits
IE1 / IE0: Set when INT1 or INT0 occurs.
IT1 / IT0: Configure INT1/INT0 as level or edge triggered.
IT0 and IT1
TCON.0 and TCON.2 are referred to as IT0 and IT1, respectively. These two bits set the low-
level or edge-triggered modes of the external hardware interrupts of the INT0 and INT1 pins.
They are both 0 upon reset, which makes them low-level triggered. The programmer can
make either of them high to make the external hardware interrupt edge-triggered. In a given
system based on the 8051, once they are set to 0 or 1 they will not be altered again since the
designer has fixed the interrupt as either edge- or level-triggered.
IE0 and IE1
TCON.1 and TCON.3 are referred to as IE0 and IE1, respectively. These bits are used by the
8051 to keep track of the edge-triggered interrupt only. In other words, if the IT0 and IT1 are
0, meaning that the hardware interrupts are low-level triggered, IE0 and IE1 are not used at
all. The IE0 and IE1 bits are used by the 8051 only to latch the high-to-low edge transition on
the INT0 and INT1 pins. Upon the edge transition pulse on the INT0 (or INT1) pin, the 8051
marks (sets high) the IEx bit in the TCON register, jumps to the vector in the interrupt vector
table, and starts to execute the ISR. While it is executing the ISR, no H-to-L pulse transition
on the INT0 (or INT1) is recognized, thereby preventing any interrupt inside the interrupt.
Only the execution of the RETI instruction at the end of the ISR will clear the IEx bit,
indicating that a new H-to-L pulse will activate the interrupt again.
TR0 and TR1
These are the D4 (TCON.4) and D6 (TCON.6) bits of the TCON register. They are used to
start or stop timers 0 and 1, respectively. Although we have used syntax such as “SETB TRx”
and “CLR Trx”, we could have used instructions such as “SETB TCON.4” and “CLR
TCON.4” since TCON is a bit-addressable register.
TF0 and TF1
These are the D5 (TCON.5) and D7 (TCON.7) bits of the TCON register. They are used by
timers 0 and 1, respectively, to indicate if the timer has rolled over. Although we have used
the syntax “JNB TFx,target” and “CLR Trx”, we could have used instructions such as “JNB
TCON.5,target” and “CLR TCON.5” since TCON is bit-addressable.
Programming The Serial Communication Interrupt: The 8051 microcontroller
supports serial communication via its UART (Universal Asynchronous Receiver
Transmitter) and allows the use of an interrupt when data is transmitted or received.
RI and TI flags and interrupts
The SCON register is an 8-bit register used to program the start bit, stop bit, and data bits of
data framing. TI is bit D1 of the SCON register, and RI is the D0 bit of the SCON register. TI
(transmit interrupt) is raised when the last bit of the framed data, the stop bit, is transferred,
indicating that the SBUF register is ready to transfer the next byte. RI (receive interrupt) is
raised when the entire frame of data, including the stop bit, is received. In other words, when
the SBUF register has a byte, RI is raised to indicate that the received byte needs to be picked
up before it is lost (overrun) by new incoming serial data. As far as serial communication is
concerned, all the above concepts apply equally when using either polling or an interrupt. The
only difference is in how the serial communication needs are served. In the polling method,
we wait for the flag (TI or RI) to be raised; while we wait we cannot do anything else. In the
interrupt method, we are notified when the 8051 has received a byte, or is ready to send the
next byte; we can do other things while the serial communication needs are served. In the
8051, only one interrupt is set aside for serial communication. This interrupt is used to both
send and receive data. If the interrupt bit in the IE register (IE.4) is enabled, that is, when RI
or TI is raised, the 8051 gets interrupted and jumps to memory address location 0023H to
execute the ISR. In that ISR, we must examine the TI and RI flags to see which one caused
the interrupt and respond accordingly.
Example: Write a program in which the 8051 reads data from P1 and writes it to P2
continuously while giving a copy of it to the serial COM port to be transferred serially.
Assume that XTAL = 11.0592 MHz. Set the baud rate at 9600.
Solution:
ORG 0000H
LJMP MAIN
ORG 23H
LJMP SERIAL ;jump to serial interrupt ISR
ORG 30H
MAIN: MOV P1, #0FFH ;make P1 an input port
MOV TMOD, #20H ;timer 1, mode 2(auto-reload)
MOV TH1, #0FDH ;9600 baud rate
MOV SCON, #50H ;8-bit, 1 stop, REN enabled
MOV IE, #10010000B ;enable serial interrupt
SETB TR1 ;start timer 1
BACK: MOV A, P1 ;read data from port 1
MOV SBUF, A ;give a copy to SBUF
MOV P2, A ;send it to P2
SJMP BACK ;stay in loop indefinitely
Serial Port ISR
ORG 100H
SERIAL: JB TI, TRANS ;jump if TI is high
MOV A, SBUF ;otherwise due to receive
CLR RI ;clear RI since CPU does not
RETI ;return from ISR
TRANS: CLR TI ;clear TI since CPU does not
RETI ;return from ISR
END
In the above program, notice the role of TI and RI. The moment a byte is written into SBUF
it is framed and transferred serially. As a result, when the last bit (stop bit) is transferred the
TI is raised, which causes the serial interrupt to be invoked since the corresponding bit in the
IE register is high. In the serial ISR, we check for both TI and RI since both could have
invoked the interrupt. In other words, there is only one interrupt for both transmit and receive.
Example: Write a program in which the 8051 gets data from P1 and sends it to P2
continuously while incoming data from the serial port is sent to P0. Assume that XTAL=
11.0592 MHz. Set the baud rate at 9600.
Solution:
ORG 0000H
LJMP MAIN
ORG 23H
LJMP SERIAL ;jump to serial ISR
ORG 30H
MAIN: MOV P1, #0FFH ;make P1 an input port
MOV TMOD, #20H ;timer 1, mode 2(auto-reload)
MOV TH1, #0FDH ;9600 baud rate
MOV SCON, #50H ;8-bit,1 stop, REN enabled
MOV IE, #10010000B ;enable serial interrupt
SETB TR1 ;start Timer 1
BACK: MOV A, P1 ;read data from port 1
MOV P2, A ;send it to P2
SJMP BACK ;stay in loop indefinitely
SERIAL PORT ISR
ORG 100H
SERIAL: JB TI, TRANS ;jump if TI is high
MOV A, SBUF ;otherwise due to receive
MOV P0, A ;send incoming data to P0
CLR RI ;clear RI since CPU doesn’t
RETI ;return from ISR
TRANS: CLR TI ;clear TI since CPU doesn’t
RETI ;return from ISR
END
Interrupt Priority in the 8051
When multiple interrupts occur simultaneously, the 8051 microcontroller uses a priority
mechanism to determine which one to handle first. This is controlled using the Interrupt
Priority (IP) Register.
Figure: Interrupt Priority Register (Bit-addressable)
Triggering the interrupt by software
There are times when we need to test an ISR by way of simulation. This
can be done with simple instructions to set the interrupts high and thereby cause the 8051 to
jump to the interrupt vector table. For example, if the IE bit
for Timer 1 is set, an instruction such as “SETB TF1” will interrupt the 8051 in
whatever it is doing and force it to jump to the interrupt vector table. In other
words, we do not need to wait for Timer 1 to roll over to have an interrupt. We
can cause an interrupt with an instruction that raises the interrupt flag.
Example: Assume that after reset, the interrupt priority is set by the instruction “MOV IP,
#00001100B”. Discuss the sequence in which the interrupts are serviced.
Solution:
The instruction “MOV IP, #00001100B” (B is for binary) sets the external interrupt 1 (INT1)
and Timer 1 (TF1) to a higher priority level compared with the rest of the interrupts.
Highest Priority - External Interrupt 1 (INT1)
Timer Interrupt 1 (TF1)
External Interrupt 0 (INT0)
Timer Interrupt 0 (TF0)
Lowest Priority - Serial Communication (RI + TI)
Example: Timer1 > INT0 Priority
ORG 0000H
AJMP MAIN
Interrupt Vector Table
ORG 0003H ; External Interrupt 0
AJMP EXT0_ISR
ORG 001BH ; Timer 1 Interrupt
AJMP TIMER1_ISR
MAIN PROGRAM
MOV TMOD, #10H ; Timer 1, Mode 1
MOV TH1, #0FCH ; Load timer value (arbitrary)
MOV TL1, #0FCH
SETB TR1 ; Start Timer 1
Enable interrupts
MOV IE, #88H ; EA = 1, ET1 = 1, EX0 = 1
MOV IP, #08H ; PT1 = 1 (Timer 1 high priority)
Configure INT0
CLR TCON.0 ; IT0 = 0 (level-triggered)
CLR TCON.1 ; Clear IE0
HERE: SJMP HERE ; Endless loop
EXT0_ISR:
CLR P1.0 ; Example action: Clear bit
CLR TCON.1 ; Clear interrupt flag (IE0)
RETI
TIMER1_ISR:
SETB P1.0 ; Example action: Set bit
CLR TF1 ; Clear Timer 1 overflow flag
RETI