8051 – Interrupt Tutorial

In this post, we are going to discuss the 8051 Interrupts Tutorial. Before that, you should know about the Interrupt basics. For Basics, you can go here. Let’s start…

8051 Interrupts Tutorial

There are five interrupt sources for the 8051. Since the main RESET input can also be considered as an interrupt, six interrupts in the order of priority can be listed as follows:

Interrupt Flag Priority
Reset RST 0
External Interrupt 0 IE0 1
Timer/Counter 0 TF0 2
External Interrupt 1 IE1 3
Timer/Counter 1 TF1 4
Serial Interrupt RI or TI 5

When an interrupt is received, the controller stops after executing the current instruction. It transfers the content of the program counter into the stack. It also stores the current status of the interrupts internally but not on the stack.

RESET interrupt

This is also known as Power-on Reset (POR). When the RESET interrupt is received, the controller restarts executing code from the 0000H location. This is an interrupt that is not available to or, better to say, need not be available to the programmer.

Timer interrupts

Each Timer is associated with a Timer interrupt. A timer interrupt notifies the microcontroller that the corresponding Timer has finished counting.

External interrupts

There are two external interrupts EX0 and EX1 to serve external devices. Both these interrupts are active low. In AT89C51, P3.2 (INT0) and P3.3 (INT1) pins are available for external interrupts 0 and 1 respectively. An external interrupt notifies the microcontroller that an external device needs its service.

Serial interrupt

This interrupt is used for serial communication. When enabled, it notifies the controller whether a byte has been received or transmitted.

Before going into programming we have to go through the registers used in the Interrupt.

Registers used for Interrupt

  • IE Register (Interrupt Enable Register)
  • IP Register (Interrupt Priority Register)
  • TCON Register (Timer Control Register) – This is used for External Interrupts only.

IE Register (Interrupt Enable Register)

This register is responsible for enabling and disabling the interrupt. EA register is set to one for enabling interrupts and set to 0 for disabling the interrupts. Its bit sequence and its meanings are shown in the following figure.

EA ET2 ES ET1 EX1 ET0 EX0
EA It disables all interrupts. When EA = 0 no interrupt will be acknowledged and EA = 1 enables the interrupt individually.
Reserved for future use.
ET2 Enables/disables Timer 2 overflow interrupt.
ES Enables/disables the serial port interrupt.
ET1 Enables/disables Timer 1 overflow interrupt.
EX1 Enables/disables External interrupt1.
ET0 Enables/disables Timer 0 overflow interrupt.
EX0 Enables/disables External interrupt0.

To enable any of the interrupts, first, the EA bit must be set to 1. After that, the bits corresponding to the desired interrupts are enabled. ET0, ET1, and ET2 bits are used to enable the Timer Interrupts 0, 1, and 2, respectively. In AT89C51, there are only two timers, so ET2 is not used. EX0 and EX1 are used to enable the external interrupts 0 and 1. ES is used for the serial interrupt.

EA bit acts as a lock bit. If any of the interrupt bits are enabled but EA bit is not set, the interrupt will not function. By default, all the interrupts are in disabled mode.

Note that the IE register is a bit addressable and individual interrupt bits can also be accessed.

For example –

IE = 0x81; enables External Interrupt0 (EX0)

IE = 0x88; enables Serial Interrupt

IP (Interrupt Priority) Register

The 8051 offers two levels of interrupt priority: High and Low. By using interrupt priorities you may assign higher priority to certain interrupt conditions. We can change the priority levels of the interrupts by changing the corresponding bit in the Interrupt Priority (IP) register as shown in the following figure. 

  • A low priority interrupt can only be interrupted by the high priority interrupt, but not interrupted by another low priority interrupt.
  • If two interrupts of different priority levels are received simultaneously, the request of a higher priority level is served.
  • If the requests of the same priority levels are received simultaneously, then the internal polling sequence determines which request is to be serviced.
PT2 Ps PT1 PX1 PT0 PX0
Reserved for future use.
Reserved for future use.
PT2 It defines the Timer 2 interrupt priority level (8052 only). 
PS It defines the serial port interrupt priority level.
PT1 It defines the Timer 1 interrupt priority level.
PX1 It defines the external interrupt priority level.
PT0 It defines the Timer 0 interrupt priority level.
PX0 It defines the external interrupt 0 priority level.

TCON Register (Timer Control Register)

The external interrupts are the interrupts received from the (external) devices interfaced with the microcontroller. They are received at INTx pins of the controller. These can be level-triggered or edge-triggered. In level triggered, interrupt is enabled for a low at INTx pin; while in case of edge triggering, interrupt is enabled for a high to low transition at INTx pin. The edge or level trigger is decided by the TCON register. We have already discussed this register in our Timer/Counter session. The TCON register has the following bits:

TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0

Here MSB four bits are used for Timers. But LSB four bits are used for External Interrupts. We will see that bits.

IE1 External Interrupt 1 edge flag. Set by hardware when external interrupt edge is detected. Cleared by hardware when the interrupt is processed.
IT1 Interrupt 1 type control bit. Set/cleared by software to specify falling edge/low-level triggered external interrupts.
IE0 External Interrupt 0 edge flag. Set by hardware when external interrupt edge is detected. Cleared by hardware when the interrupt is processed.
IT0 Interrupt 0 type control bit. Set/cleared by software to specify falling edge/low-level triggered external interrupts.

Setting the IT0 and IT1 bits make the external interrupt 0 and 1 edge-triggered respectively. By default, these bits are cleared and so the external interrupt is level triggered. 

Note: For a level trigger interrupt, the INTx pin must remain low until the start of the ISR and should return to high before the end of the ISR. If the low at INTx pin goes high before the start of ISR, an interrupt will not be generated. Also if the INTx pin remains low even after the end of ISR, the interrupt will be generated once again. This is the reason why the level trigger interrupt (low) at the INTx pin must be four machine cycles long and not greater than or smaller than this.

So, these all are the registers used in the Interrupt. These registers are not enough for play with interrupt. We have to write the ISR or Interrupt Handler. 

ISR or Interrupt Handler – 8051 Interrupts

Setting the bits of IE register is necessary and sufficient to enable the interrupts. The next step is to specify to the controller what to do when an interrupt occurs. This is done by writing a subroutine or function for the interrupt. This is the ISR and gets automatically called when an interrupt occurs. It is not required to call the Interrupt Subroutine explicitly in the code.

An important thing is that the definition of a subroutine must have the keyword interrupt followed by the interrupt number. A subroutine for a particular interrupt is identified by this number.

0

External 0

EX0

1

Timer 0

IT0

2

External 1

EX1

3

Timer 1

IT1

4

Serial

ES

5

Timer 2

ET2

Example Template

ISR for External Interrupt 0/1

/* ISR for External Interrupt 0 */

Void ex0 (void) interrupt 0
{
    <Body of ISR>
}

/* ISR for External Interrupt 1 */

Void ex0 (void) interrupt 2
{
    <Body of ISR>
}

//Level trigger external interrupt 0

void main()
{
    IE = 0x81;
    while(1);
}

void ISR_ex0(void) interrupt 0
{
    <body of interrupt>
}

//Edge trigger external interrupt 1

void main()
{
    IE = 0x84;
    IT1 = 1;
    while(1);
}

void ISR_ex1(void) interrupt 2
{
    <body of interrupt>
}

ISR for Timer 0/1

/* ISR for Timer 0 */

Void timer0 (void) interrupt 1
{
    <Body of ISR>
}

/* ISR for Timer 1 */

Void timer1 (void) interrupt 3
{
    <Body of ISR>
}

ISR for Serial

/* ISR for Serial */

Void serial (void) interrupt 4
{
    <Body of ISR>
}

Programming (Timer 0 Interrupt) – 8051 Interrupts

Timer interrupts to blink an LED; Time delays in mode 1 using interrupt method.

#include<reg51.h>

sbit LED = P1^0;        //LED connected to P1.0

Void main()
{
    TMOD = 0x01;        // mode1 of Timer0
    TH0 = 0xFC;     // initial values loaded to timer
    TL0 = 0x66;
    IE = 0x82;      // enable interrupt
    TR0 = 1;        //start timer
    while(1);       // do nothing  
} 
void timer(void) interrupt 1        //interrupt no. 1 for Timer 0
{
    led=~led;       //toggle LED on interrupt
    TH0=0xFC;       // initial values loaded to timer
    TL0=0x66;
}

Programming (Serial Interrupt) – 8051 Interrupts

Send ‘A’ from the serial port when it receives anything via Rx.

#include<reg51.h>

void main()
{
    TMOD = 0x20;
    TH1 = TL1=0xfd;
    SCON = 0x50;
    TR1 = 1;
    IE = 0x90;
    while(1);
}


void ISR_sc(void) interrupt 4
{
    if(RI==1){
        SBUF = 'A';
        while(TI==0);
        TI = 0;
        RI = 0;
    }   
}

Programming multiple interrupts – 8051 Interrupts

Multiple interrupts can be enabled by setting more than one interrupts in the IE register. If more than one interrupts occurs at the same time, the interrupts will be serviced in order of their priority. The priority of the interrupts can be changed by programming the bits of the Interrupt Priority (IP) register.

Setting a particular bit in IP register makes the corresponding interrupt of the higher priority. For example, IP = 0x08; will make Timer1 priority higher. So the interrupt priority order will change. More than one bit in IP register can also be set. In such a case, the higher priority interrupts will follow the sequence as they follow in the default case.

For example,

IP = 0x0A; will make Timer0 and Timer1 priorities higher.

Note that in the below example external interrupt 1 is set to be a higher priority than the Timer 0 and external 0 in this case.

//Toggle LEDs by Timer and External Interrupt

#include<reg51.h>

void delay();

int i,a;

void main()
{
    P1=P2=P0=0x00;
    IP=0x04;
    EA=1;
    EX0=1;
    ET0=1;
    EX1=1;
    TMOD=0X01;
    TH0=0X4b;
    TL0=0Xfd;
    TR0=1;
    while(1);
}

void ex0() interrupt 0
{
    P0=0xff;
    delay();
    P0=0x00;
    delay();
}

void et0() interrupt 1
{
a++;
if(a==20)
{
    P1=~P1;
    a=0;
}
}

void ex1() interrupt 2
{
    P2=0x81;
    delay();
    P2=0x18;
    delay();
}

void delay()
{
    for(i=0;i<30000;i++);
}

I hope you have enjoyed this tutorial. Please comment below if you have any doubt. Thank you.

You can also read the below tutorials.

Linux Device Driver TutorialsC Programming Tutorials
FreeRTOS TutorialsNuttX RTOS Tutorials
RTX RTOS TutorialsInterrupts Basics
I2C Protocol – Part 1 (Basics)I2C Protocol – Part 2 (Advanced Topics)
STM32 TutorialsLPC2148 (ARM7) Tutorials
PIC16F877A Tutorials8051 Tutorials
Unit Testing in C TutorialsESP32-IDF Tutorials
Raspberry Pi TutorialsEmbedded Interview Topics
Reset Sequence in ARM Cortex-M4BLE Basics
VIC and NVIC in ARMSPI – Serial Peripheral Interface Protocol
STM32F7 Bootloader TutorialsRaspberry PI Pico Tutorials
STM32F103 Bootloader TutorialsRT-Thread RTOS Tutorials
Zephyr RTOS Tutorials - STM32Zephyr RTOS Tutorials - ESP32
AUTOSAR TutorialsUDS Protocol Tutorials
Product ReviewsSTM32 MikroC Bootloader Tutorial
VHDL Tutorials
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Table of Contents