4.4 Interrupts in 8051
4.4 Interrupts in 8051
MICROCONTROLLER &
Embedded Systems
Muhammad Ali Mazidi, Janice Mazidi
& Rolin McKinlay
INTERRUPTS
PROGRAMMING
IN ASSEMBLY AND C
Chapter 11
Objectives
Upon completion of this chapter, you will be able to:
>> Contrast and compare interrupts versus polling
>> Explain the purpose of the ISR (interrupt service routine)
>> List the 6 interrupts of the 8051
>> Explain the purpose of the interrupt vector table
>> Enable or disable 8051/52 interrupts
>> Program the 8051/52 timers using interrupts
>> Describe the external hardware interrupts of the 8051/52
>> Contrast edge-triggered with level-triggered interrupts
>> Program the 8051 for interrupt-based serial communication
>> Define the interrupt priority of the 8051
>> Program 8051/52 interrupts in C
Objectives
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:
Write a program to generate a square wave of 50 Hz frequency on pin P1.2. This is similar to Example 9-12 except
that it uses an interrupt for Timer 0. Assume that XTAL = 11.0592 MHz.
Solution:
ORG 0
LJMP MAIN
ORG 000BH ;ISR for Timer 0
CPL P1.2 ;complement P1.2
MOV TL0,#00 ;reload timer values
MOV TH0,#0DCH
RETI ;return from interrupt
ORG 30H ;starting location for prog.
;------main program for initialization
MAIN: MOV TMOD,#00000001B ;Timer 0, Mode 1
MOV TL0,#00
MOV TH0,#0DCH
MOV IE,#82H ;enable Timer 0 interrupt
SETB TR0 ;start timer
HERE: SJMP HERE ;stay here until interrupted
END
Figure 11-4. Activation of INT0 and INT1
Example 11-5
Assume that the INT1 pin is connected to a switch that is normally high. Whenever it goes low, it should turn on
an LED. The LED is connected to P1.3 and is normally off. When it is turned on it should stay on for a fraction of a
second. As long as the switch is pressed low, the LED should stay on.
Solution:
ORG 0000H
LJMP MAIN ;bypass interrupt vector table Pressing the switch will
;--ISR for hardware interrupt INT1 to turn on the LED turn the LED on. If it
ORG 0013H ;INT1 ISR is kept activated, the
SETB P1.3 ;turn on LED LED stays on.
MOV R3,#255 ;load counter
BACK: DJNZ R3,BACK ;keep LED on for a while
CLR P1.3 ;turn off the LED
RETI ;return from ISR
;--MAIN program for initialization
ORG 30H
MAIN: MOV IE,#10000100B ;enable external INT1
HERE: SJMP HERE ;stay here until interrupted
END
Figure 11-5. Minimum Duration of the Low Level-Triggered Interrupt (XTAL = 11.0592 MHz)
Note: On RESET, IT0 (TCON.0) and IT1 (TCON.2) are both low, making
external interrupts level-triggered.
TF1 TCON.7 Timer 1 overflow flag. Set by hardware when timer/counter 1 overflows.
Cleared by hardware as the processor vectors to the interrupt service routine.
TR1 TCON.6 Timer 1 run control bit. Set/cleared by software to turn timer/counter 1 on/off.
TF0 TCON.5 Timer 0 overflow flag. Set by hardware when timer/counter 0 overflows.
Cleared by hardware as the processor vectors to the service routine.
TR0 TCON.4 Timer 0 run control bit. Set/cleared by software to turn timer/counter 0 on/off.
IE1 TCON.3 External interrupt 1 edge flag. Set by CPU when the external interrupt edge
Figure 11-6. TCON (H-to-L transition) is detected.
(Timer/Counter) Register Cleared by CPU when the interrupt is processed.
Note: This flag does not latch low-level triggered interrupts.
(Bit-addressable)
IT1 TCON.2 Interrupt 1 type control bit. Set/cleared by software to
specify falling edge/low-level triggered external interrupt.
IE0 TCON.1 External interrupt 0 edge flag. Set by CPU when external interrupt
(H-to-L transition) edge is detected. Cleared by CPU when interrupt is processed.
Note: This flag does not latch low-level triggered interrupts.
IT0 TCON.0 Interrupt 0 type control bit. Set/cleared by software to specify falling
edge/low-level triggered external interrupt.
Example 11-6
Assuming that pin 3.3 (INT1) is connected to a pulse generator, write a program in which the falling edge of the pulse will
send a high to P1.3, which is connected to an LED (or buzzer). In other words, the LED is turned on and off at the same rate
as the pulses are applied to the INT1 pin. This is an edge-triggered version of Example 11-5.
Solution:
ORG 0000H
LJMP MAIN
;--ISR for hardware interrupt INT1 to turn on the LED
ORG 0013H ;INT1 ISR
SETB P1.3 ;turn on the LED
MOV R3,#255
BACK: DJNZ R3,BACK ;keep the LED on for a while
CLR P1.3 ;turn off the LED
RETI ;return from ISR
;--MAIN program for initialization
ORG 30H
MAIN: SETB TCON.2 ;make INT1 edge-trigger interrupt
MOV IE,#10000100B ;enable External INT1
HERE: SJMP HERE ;stay here until interrupted
END
Minimum Pulse Duration to Detect Edge-triggered Interrupts. XTAL = 11.0592 MHz
Example 11-7
What is the difference between the RET and RETI instructions? Explain why we cannot use RET
instead of RETI as the last instruction of an ISR.
Solution:
Both perform the same actions of popping off the top two bytes of the stack into
the program counter, and making the 8051 return to where it left off. However,
RETI also performs an additional task of clearing the interrupt-in-service flag,
indicating that the servicing of the interrupt is over and the 8051 now can accept
a new interrupt on that pin. If you use RET instead of RETI as the last instruction
of the interrupt service routine, you simply block any new interrupt on that pin
after the first interrupt, since the pin status would indicate that the interrupt is
still being serviced. In the cases of TF0, TF1, TCON.1, and TCON.3, they are
cleared by the execution of RETI.
Figure 11-7. Single Interrupt for Both TI and RI
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.
Example 11-8 Assume that XTAL = 11.0592 MHz. Set the baud rate at 9600.
Solution:
ORG 0
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.
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.
Example 11-9 Assume that XTAL = 11.0592 MHz. Set the baud rate at 9600.
Solution:
ORG 0
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
Table 11-2: Interrupt Flag Bits for the 8051/52
Write a program using interrupts to do the following: (a) Receive data serially and send it to P0, (b)
Have port P1 read and transmitted serially, and a copy given to P2, (c) Make Timer 0 generate a square
Example 11-10 wave of 5 kHz frequency on P0.1. Assume that XTAL = 11.0592 MHz. Set the baud rate at 4800.
Solution:
ORG 0
LJMP MAIN
ORG 000BH ;ISR for Timer 0
CPL P0.1 ;toggle P0.1
RETI ;return from ISR
ORG 23H
LJMP SERIAL ;jump to serial int. ISR
ORG 30H
MAIN: MOV P1,#0FFH ;make P1 an input port
MOV TMOD,#22H ;timer 0&1,mode 2, auto-reload
MOV TH1,#0F6H ;4800 baud rate
MOV SCON,#50H ;8-bit, 1 stop, REN enabled
MOV TH0,#-92 ;for 5 KHz wave
MOV IE,#10010010B ;enable serial, timer 0 int.
SETB TR1 ;start timer 1
SETB TR0 ;start timer 0
BACK: MOV A,P1 ;read data from port 1
MOV SBUF,A ;give a copy to SBUF
MOV P2,A ;write 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 received
MOV P0,A ;send serial data to P0
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
Table 11-3: 8051/52 Interrupt Priority Upon Reset
Example 11-11
Discuss what happens if interrupts INT0, TF0, and INT1 are activated at the same
time. Assume priority levels were set by the power-up reset and that the external
hardware interrupts are edge-triggered.
Solution:
If these three interrupts are activated at the same time, they are latched and
kept internally. Then the 8051 checks all five interrupts according to the
sequence listed in Table 11-3. If any is activated, it services it in sequence.
Therefore, when the above three interrupts are activated, IE0 (external interrupt
0) is serviced first, then Timer 0 (TF0), and finally IE1 (external interrupt 1).
Figure 11-8. Interrupt Priority Register (Bit-addressable)
Priority bit = 1 assigns high priority. Priority bit = 0 assigns low priority.
-- IP.7 Reserved
-- IP.6 Reserved
PT2 IP.5 Timer 2 interrupt priority bit (8052 only)
PS IP.4 Serial port interrupt priority bit
PT1 IP.3 Timer 1 interrupt priority bit
PX1 IP.2 External interrupt 1 priority bit
PT0 IP.1 Timer 0 interrupt priority bit
PX0 IP.0 External interrupt 0 priority bit
User software should never write 1s to unimplemented bits, since they may be used in future
products.
Example 11-12
(a) Program the IP register to assign the highest priority to INT1 (external interrupt 1), then (b)
discuss what happens if INT0, INT1, and TF0 are activated at the same time. Assume that the
interrupts are both edge-triggered.
Solution
(b) The instruction in Step (a) assigned a higher priority to INT1 than the others; therefore, when
INT0, INT1, and TF0 interrupts are activated at the same time, the 8051 services INT1 first, then it
services INT0, then TF0. This is due to the fact that INT1 has a higher priority than the other two
because of the instruction in Step (a). The instruction in Step (a) makes both the INT0 and TF0 bits in
the IP register 0. As a result, the sequence in Table 11-3 is followed, which gives a higher priority to
INT0 over TF0.
Example 11-13
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. However, since they are
polled according to Table 11-3, they will have the following priority.
Write a C program that continuously gets a single bit of data from P1.7 and sends it to P1.0, while simultaneously creating a
square wave of 200 µs period on pin P2.5. 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). One half of the period is 100 µs.
100 /1. 085 ms = 92, and TH0 = 256 – 92 = 164 or A4H
#include <reg51.h>
sbit SW = P1^7;
sbit IND = P1^0;
sbit WAVE = P2^5;
200 µs / 2 = 100 µs
void timer0(void) interrupt 1
100 µs / 1.085 µs = 92
{
WAVE = ~WAVE; //toggle pin
}
void main()
{
SW = 1; //make switch input
TMOD = 0x02;
TH0 = 0xA4; //TH0 = -92
IE = 0x82; //enable interrupts for timer 0
while(1)
{
IND = SW; //send switch to LED
}
}
#include <reg51.h>
sbit SW = P1^7;
Solution: sbit IND = P1^0;
Example 11-15 sbit WAVE = P2^5;
void timer0(void) interrupt 1
{
WAVE = ~WAVE; //toggle pin
}
void serial0() interrupt 4
{
Write a C program that if(TI == 1)
{
continuously gets a single bit SBUF = 'A'; //send A to serial port
of data from P1.7 and sends TI = 0; //clear interrupt
}
it to P1.0 in the main, while We will use Timer else
simultaneously (a) creating a 0 in mode 2 {
(auto-reload). RI = 0; //clear interrupt
square wave of 200 µs period TH0 = 100/1.085 }
on pin P2.5, and (b) sending µs = –92, which is }
A4H void main()
letter ‘A’ to the serial port. {
Use Timer 0 to create the SW = 1; //make switch input
TH1 = -3; //9600 baud
square wave. TMOD = 0x22; //mode 2 for both timers
TH0 = 0xA4; //-92=A4H for timer 0
SCON = 0x50;
Assume that TR0 = 1;
TR1 = 1; //start timer
XTAL = 11.0592 MHz. IE = 0x92; //enable interrupt for T0
while(1) //stay here
{
Use the 9600 baud rate. IND = SW; //send switch to LED
}
}
#include <reg51.h>
sbit WAVE = P0^1;
Solution: void timer0() interrupt 1
Example 11-16 {
WAVE = ~WAVE; //toggle pin
}
void serial0() interrupt 4
{
Write a C program using if(TI == 1)
interrupts to do the {
TI = 0; //clear interrupt
following: }
else
{
(a) Receive data serially and P0 = SBUF; //put value on pins
RI = 0; //clear interrupt
send it to P0, }
}
void main()
(b) Read port P1, transmit {
data serially, and give a copy unsigned char x;
P1 = 0xFF; //make P1 an input
to P2, TMOD = 0x22;
TH1 = 0xF6; //4800 baud rate
SCON = 0x50;
(c) Make timer 0 generate a TH0 = 0xA4; //5 kHz has T = 200 µs
square wave of 5 kHz IE = 0x92; //enable interrupts
TR1 = 1; //start timer 1
frequency on P0.1. TR0 = 1; //start timer 0
while(1)
{
Assume that x = P1; //read value from pins
SBUF = x; //put value in buffer
XTAL = 11.0592 MHz. Set P2 = x; //write value to pins
the baud rate at 4800. }
}
Write a C program using interrupts to do the following: (a) Generate a 10000 Hz frequency on P2.1 using T0 8-bit
auto-reload, (b) Use timer 1 as an event counter to count up a 1-Hz pulse and display it on P0. The pulse is
Example 11-17 connected to EX1. Assume that XTAL = 11.0592 MHz. Set the baud rate at 9600.
Solution:
#include <reg51.h>
void main()
{
cnt = 0; //set counter to zero
TMOD = 0x42;
TH0 = 0x-46; //10000 Hz
IE = 0x86; //enable interrupts
TR0 = 1; //start timer 0
TR1 = 1; //start timer 1
while(1); //wait until interrupted
}