Check this post, If you want to understand what is an interrupt.
Interrupt handling in 8051 is very simple. To learn about interrupts in the 8051 microcontrollers; first of all, we must understand what different types of interrupts are available in the 8051 microcontrollers.
Types of interrupts in 8051
- External hardware interrupt – INT0
- External hardware interrupt – INT1
- Timer 0 overflow interrupt – TF0
- Timer 1 overflow interrupt – TF1
- Serial communication interrupt – RI/TI
Timer and serial interrupts are internally generated by the inbuilt timer and USART peripherals modules.
External interrupts are generated by external interfacing devices such as switches, number pad, RTC etc.
When an interrupt occurs, the microcontroller first finishes the instruction that it is executing and then jumps to the memory location corresponding to the interrupt. This memory location is also known as an interrupt vector. 8051 microcontroller has fixed interrupt vectors for each interrupt as shown in the below table.
|Interrupt number||Description||Memory Address|
|0||External hardware interrupt INT0||0003h|
|1||Timer/Counter 0 interrupt||000Bh|
|2||External hardware interrupt INT1||0013h|
|3||Timer/Counter 1 interrupt||001Bh|
|4||Serial communication interrupt||0023h|
In 8051, each interrupt can have either high priority or low priority. The priority level of an interrupt can be set to high by setting the corresponding bit in Interrupt Priority (IP) resister or it can be set to low by clearing the corresponding bit in the Interrupt Priority (IP) register.
|(MSB) IP.7||IP.6||IP.5||IP.4||IP.3||IP.2||IP.1||(LSB) IP.0|
|Direct Address B8H||–||–||PT2||PS||PT1||PX1||PT0||PX0|
|Bit 5: PT2||0: Low priority for Timer 2 interrupt|
1: High priority for Timer 2 interrupt
|Bit 4: PS||0: Low priority for Serial interrupt|
1: High priority for Serial interrupt
|Bit 3: PT1||0: Low priority for Timer 1 interrupt|
1: High priority for Timer 1 interrupt
|Bit 2: PX1||0: Low priority for External interrupt INT1|
1: High priority for External interrupt INT1
|Bit 1: PT0||0: Low priority for Timer 0 interrupt|
1: High priority for Timer 0 interrupt
|Bit 0: PX0||0: Low priority for External interrupt INT0|
1: High priority for External interrupt INT0
If multiple interrupts of different priority level are received simultaneously then high priority interrupt is serviced first. If requests of the same priority level are received simultaneously, an internal polling sequence determines which request is to be serviced, Thus within each priority level is a second priority structure determined by the polling sequence. Polling sequence is shown in table below.
|Source||Priority within Level|
|1||External hardware interrupt INT0||Highest|
|2||Timer/Counter 0 interrupt|
|3||External hardware interrupt INT1|
|4||Timer/Counter 1 interrupt|
|5||Serial communication interrupt||Lowest|
A combination of Interrupt Priority (IP) register and polling sequence gives unique priorities to all 5 interrupts in the 8051 microcontrollers. If all bits in Interrupt Priority (IP) register are cleared then external interrupt INT0 will have highest priority, timer 0 will be next and serial communication interrupt will have lowest priority. If multiple interrupts are triggered at same time, then the interrupts are serviced according to priority. For instance, if external hardware interrupt INT1 and external hardware interrupt INT0 are triggered at exactly the same time, then external hardware interrupt INT0 will be serviced first.
Upon reset, all interrupts are disabled (masked), meaning that the microcontroller will respond to none if any activated. The interrupts must be enabled by software in order for the microcontroller to respond to them. There is a register called IE (interrupt enable) that is responsible for enabling (unmasking) and disabling (masking) the interrupts.
In the 8051 microcontroller, interrupts can be enabled or disabled by setting or clearing corresponding bits in Interrupt Enable (IE) Register. Also all interrupts can be enabled or disabled globally using EA bit in Interrupt Enable (IE) register.
|(MSB) IE.7||IE.6||IE.5||IE.4||IE.3||IE.2||IE.1||(LSB) IE.0|
|Direct Address A8H||EA||–||ET2||ES||ET1||EX1||ET0||EX0|
|Bit 7: EA||0: Disable all interrupts|
1: Enable all interrupts according to individual enable bits
|Bit 5: ET2||0: Disable Timer 2 interrupt|
1: Enable Timer 2 interrupt
|Bit 4: ES||0: Disable Serial interrupt|
1: Enable Serial interrupt
|Bit 3: ET1||0: Disable Timer 1 interrupt|
1: Enable Timer 1 interrupt
|Bit 2: EX1||0: Disable External interrupt INT1|
1: Enable External interrupt INT1
|Bit 1: ET0||0: Disable Timer 0 interrupt|
1: Enable Timer 0 interrupt
|Bit 0: EX0||0: Disable External interrupt INT0|
1: Enable External interrupt INT0
Timer Control Register (TCON)
|(MSB) TCON.7||TCON.6||TCON.5||TCON.4||TCON.3||TCON.2||TCON.1||(LSB) TCON.0|
|Direct Address 88H||TF1||TR1||TF0||TR0||IE1||IT1||IE0||IT0|
|Bit 7: TF1||Timer 1 overflow bit set by the controller when timer 1 overflows.|
Cleared when processor vectors to execute interrupt service routine located at program address 001Bh.
|Bit 6: TR1||0: Turn Off Timer 1|
1: Turn On Timer 1
|Bit 5: TF0||Timer 0 overflow bit set by controller when timer 0 overflows.|
Cleared when processor vectors to execute interrupt service routine located at program address 000Bh.
|Bit 4: TR0||0: Turn Off Timer 0|
1: Turn On Timer 0
|Bit 3: IE1||External interrupt 1 Edge flag. Set to 1 when a high-to-low edge signal is received on port 3.3 (INT1).|
Cleared when processor vectors to interrupt service routine at program address 0013h. Not related to timer operations.
|Bit 2: IT1||0: External interrupt INT1 triggered on low level|
1: External interrupt INT1 triggered on falling edge
|Bit 1: IE0||External interrupt 0 Edge flag. Set to 1 when a high-to-low edge signal is received on port 3.2 (INT0).|
Cleared when processor vectors to interrupt service routine at program address 0003h. Not related to timer operations.
|Bit 0: IT0||0: External interrupt INT0 triggered on low level|
1: External interrupt INT0 triggered on falling edge
ON) Register Bits
TF0 and TF1 bits of the TCON register are set by the controller when all bits of timer 0 or timer 1 rollover from 1 to 0. TF0 and TF1 bits can be polled to detect timer overflow event. These bits are automatically cleared when the processor executes the interrupt service routine (ISR) located at the respective timer vector address.
TR0 and TR1 bits are used to run or stop timer 0 and timer 1 respectively.
IT0 and IT1 bits are used for external interrupts. An external interrupt will be triggered on the low level of signal if IT0/IT1 bit is set to 0. An external interrupt will be triggered on the falling edge of the signal if IT0/IT1 is set to 1.
IE0 and IE1 bits are external interrupt flags. These bits are set to 1 if the falling edge is received on external interrupt pins.
Interrupt flags (TF0, TF1, IE0, IE1) are set by the controller when the respective interrupt event is received and these bits are cleared automatically when the respective ISR is executed by the controller. If interrupts are disabled and interrupt flags are polled through the program, then the program must take care of clearing respective flags.
Other Related Registers
Timer 0 Registers – TH0 and TL0 are timer high byte and timer low byte. TH0 and TL0 are byte-addressable registers. TH0 and TL0 together make a 16-bit timer register. Since 8051 is an 8-bit controller; the timer register is accessed in two bytes, one byte for TH0 and one for TL0.
Timer 1 Registers – TH1 and TL1 are timer high byte and timer low byte. These are byte-addressable registers.
Timer Mode Register (TMOD) – TMOD is used to set timer mode. 8051 controller supports 4 timer modes.
- 13-bit timer
- 16-bit timer
- 8-bit Auto reload
- Split timer mode
|(MSB) TMOD.7||TMOD.6||TMOD.5||TMOD.4||TMOD.3||TMOD.2||TMOD.1||(LSB) TMOD.0|
|Direct Address 89H||GATE1||C/T1||M1||M0||GATE0||C/T0||M1||M0|
|TMOD is not bit Address|
|Bit 7: GATE1||0: Timer 1 runs regardless of state of INT1|
1: Timer 1 runs when INT1 P3.3 is high
|Bit 6: C/T1||0: Timer 1 incremented every machine cycle|
1: Timer 1 incremented every falling edge on INT1 P3.3 (event counter)
|Bit 5: M1||Timer 1 Mode bits|
0 0 : Timer 1 mode 0 – 13 bit timer
0 1 : Timer 1 mode 1 – 16 bit timer
1 0 : Timer 1 mode 2 – 8 bit auto reload
1 1 : Timer 1 mode 3 – Spilt timer mode
|Bit 4: M0|
|Bit 3: GATE0||0: Timer 0 runs regardless of state of INT0|
1: Timer 0 runs when INT0 P3.2 is high
|Bit 2: C/T0||0: Timer 0 incremented every machine cycle|
1: Timer 0 incremented every falling edge on INT1 P3.3 (event counter)
|Bit 1: M0||Timer 0 Mode bits|
0 0 : Timer 0 mode 0 – 13 bit timer
0 1 : Timer 0 mode 1 – 16 bit timer
1 0 : Timer 0 mode 2 – 8 bit auto reload
1 1 : Timer 0 mode 3 – Spilt timer mode
|Bit 0: M1|
Serial Control Register (SCON) – The SCON register is used for serial communication.
|(MSB) SCON.7||SCON.6||SCON.5||SCON.4||SCON.3||SCON.2||SCON.1||(LSB) SCON.0|
|Direct Address 98H||SM0||SM1||SM2||REN||TB8||RB8||TI||RI|
|TMOD is not bit Address||9F||9E||9D||9C||9B||9A||99||98|
|Bit 7: SM0||Serial mode select bits|
0 0 : mode 0 – Half duplex with fixed baud rate
0 1 : mode 1 – full duplex with variable baud rate (1 start bit, 8 data bits, 1 stop bit)
1 0 : mode 2 – full duplex 11 bit serial communication
1 1 : Mode 3 – Dull duplex with variable baud rate
|Bit 6: SM1|
|Bit 5: SM2|| Set to 0 in mode 0.|
Used to store stop bit in mode 1.
Used for multiprocessor communication in mode 2 and 3.
|Bit 4: REN||0: Disable serial communication|
1: Enable serial communication
|Bit 3: TB8||Used in mode 2 and 3|
|Bit 2: RB8||Used in mode 2 and 3|
|Bit 1: TI||Transmit interrupt flap set by microcontroller when one character transmission is complete.|
|Bit 0: RI||RI is Receive Interrupt flag, When 8051 receive data via RxD pin|
Serial Buffer (SBUF) – This register is used for transmitting or receiving data serially. We put data in it that we want to transmit, it also contains the data which is transmitted from other peripherals like personal computers (PC) to the 8051 microcontrollers. It is not a bit addressable.
Interrupt Handling in 8051
Most instructions in 8051 take 1 machine cycle to complete. Some instructions take 2 or 3 machine cycles. One machine cycle consists of 6 states S1 to S6 and every state has 2 pulses P1 and P2. So a machine cycle takes 12 pulses of the clock to execute.
The interrupt flags are sampled at P2 of S5 of every instruction cycle. The samples are polled during the next instruction cycle. If one of the flags was set at S5P2 of the preceding machine cycle, the polling detects it and the microcontroller generates an interrupt by generating a long call (LCALL) to the appropriate vector address. When an equal or a higher priority interrupt is already being serviced then the microcontroller does not generate LCALL. While the instruction in progress is RETI or any write to IE or IP registers then the microcontroller does not generate LCALL. If the interrupt is blocked because of the above-mentioned reasons then the interrupt will be serviced after the removal of blocking conditions only if the interrupt flap is still active.
When an interrupt occurs and the program is directed to the interrupt vector address, the Program Counter (PC) value of the interrupted program is stored (pushed) on the stack. The required Interrupt Service Routine (ISR) is executed. At the end of the ISR, the instruction RETI returns the value of the PC from the stack and the originally interrupted program is resumed.
Steps in executing interrupts:
- The microcontroller finishes the instruction it is executing and saves the address of the next instruction (PC) on the stack.
- Jump to a fixed location in memory called the interrupt vector table that holds the address of the interrupt service routine.
- 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, that is RETI (return from interrupt).
- 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.
Programmers must be careful while manipulating data on the stack during ISR execution. In ISR number of PUSH and POP must be the same.
How to write ISR
ISR is like any other subroutine in the program, except that it must end with RETI instruction and not with RET instruction. The first line of ISR must begin from the corresponding vector address. In some cases, ISR will be very long and it may not be practical to write all code starting from the vector address. So ISR is kept at some other location in the program memory and an unconditional jump to the starting address of ISR must be provided from the corresponding vector address.
Whenever a triggered interrupt is acknowledged and the processor branches to its corresponding vector address, it automatically disables the interrupt in the Interrupt Enable (IE) register. This disabled interrupt would only be re-enabled upon executing the RETI instruction placed inside the ISR.
Example: ISR for INT0
ORG 0H ; Power on ROM reset location
LJMP MAIN ; bypass all the interrupt vector locations
ORG 0003H ; ISR for INT0 beginning from its vector address
LJMP ISR_INT0 ;unconditional jump from 0003H to the starting
address of ISR
MAIN: SETB IT0 ; configure interrupt 0 for falling edge on INT0
SETB EX0 ; enable external interrupt INT0
SETB EA ; enable global interrupt flag
HERE: SJMP HERE
; ISR for INT0
SETB P0.0 ; turn on some output
SETB P0.1 ; turn on some output
Below is the alternate C code for same ISR. The compiler itself handles the address mapping. You only have to write the ISR function with the corresponding “interrupt number”.
IT0 = 1; // configure interrupt 0 for falling edge on INT0
EX0 = 1; // enable external interrupt INT0
EA = 1; // enable global interrupt flag
// ISR for INT0 beginning from its vector address
void ISR_INT0(void) interrupt 0
P0.0 = 1; // turn on some output
P0.1 = 1; // turn on some output
Software Interrupts in 8051
Software interrupts are generated by the program itself inside the controller. Generating software interrupt in the 8051 microcontrollers is tricky. When an external interrupt is received at INT0 pin TCON.0 bit (IT0) would be set automatically and the processor generates an interrupt. If the TCON.0 bit is set in the program, the microcontroller immediately acknowledges it as an interrupt and branches to the corresponding ISR of INT0. As a result, 8051 Microcontroller executes software interrupt exactly the same as normal ISR.