• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
Resource icon

Simple interrupts on the 8051 2014-01-29

Following on from the Simple Interrupts on the mid range PIC's found here..
http://www.electro-tech-online.com/articles/simple-interrupts-on-mid-range-pics.640/
(Notice the title change )

I have done the similar article on the humble 8051... I've kept it generic so the code will work on every variation...

So you can get started there is an IDE that I use as a test bed.. Its quite a good IDE / Simulator for the 8051.. you can download it here.. http://mcu8051ide.sourceforge.net/

The C compiler I use for the 8051 is SDCC ( Small Device C Compiler ).. Again you can download it here..
http://sdcc.sourceforge.net/

You can use Kiel free version to compile these small code snippets. There are other free compilers, but I haven't used them... MPU8051IDE compiles the C code as well..

We start with timer 0 as I did with the pic example, I'll show you in ASM and in C how to setup and use the interrupts so you can use them in your code... As with the PIC the 8051 has registers that need attention to get your interrupts up and working..

The IE register is that register...

ie reg.png


As you can see Timer 0 is bit 1 ET0.. Set this bit to logic 1 and the interrupt will fire when timer 0 overflows... Bit 5 and bit 6 are not used on the basic 8051..

There is also a global interrupt EA that controls all the interrupts!!

Now! Unlike the PIC's the 8051 has several interrupt vectors instead of the single vector on the mid range PIC.. Vector is the name given to jump position allocated to each interrupt... For example here are the 8051 interrupt vectors..

0x00 = Reset vector... You can insert a AJMP ( absolute jump ) to the beginning of your main code routine..
0x03 = EXO vector.. Jump to the code that deals with an external change on the INT0 ( pin 12 )..
0x0B = ETO vector.. Jump to the code that deals with an overflow on the timer 0 register..
0x13 = EX1 vector.. Jump to the code that deals with an external change on the INT1 ( pin 13 )..
0x1B = ET1 vector.. Jump to the code that deals with an overflow on the timer 1 register..
0x23 = ES vector.. Jump to the code that deals with a character received or transmitted on the serial port..

Heres the code for setting up and using timer 0 as an interrupt.
Code:
$mod51

ISRvar    equ    0x30        ; Reserve a byte to hold a count

    org    0x0
    sjmp    Main        ; Short jump to our main code

    org    0x0B
    ajmp    ISR        ; Absolute jump to the ISR
Main:
    mov    TMOD,#0x03    ; 8 bit counter no reload
    mov    TH0,#0x00    ; Clear
    mov    TL0,#0x0    ; timer regs
    setb    TR0        ; start timer 0
    setb    ET0        ; set timer 0 interrupt
    setb    EA        ; Set global interrupts
    clr    ISRvar        ; clear count byte

while:
    mov    P0, ISRvar    ; Put the count
    sjmp    while        ; On PORT 0

ISR:
    mov    A, ISRvar    ; Get variable into Acc
    inc    Acc        ; inrease by one
    mov    ISRvar,Acc    ; stick it back

    reti

    end
A couple of points to go over here! I have used the TMOD register..
The TMOD register controls the way the timer is implemented..

M01 and M00.. ( bits 1 and 0 ) Mode.
00 = 8 bit Timer with pre-scaler (TLO = pre-scale)
01 = 16 bit timer.
10 = 8 bit timer with re-load. (TH0 = reload value )
11 = 8 bit timer with no pre-scaler.

CT0.. ( bit 2 ) Counter / timer .
1 = increment timer on pulses on the T0 ( pin 14).
0 = increment timer from system clock.

G0.. ( bit 3 ) Gate control.
1 = INT0 and TR0 controls timer..
0 = TR0 controls timer.

Bits 4~7 are the same but for timer 1..

Here is the C equivalent...
C:
#include <mcs51reg.h>

volatile int ISRvar;    // ISR counter variable.

void Timer0_ISR(void) __interrupt (1)
    {
    ISRvar++;        // Increment counter variable.
    }

void main(void)
    {
    TMOD = 0x3;        // Timer mode.
    TL0 = 0;        // Clear
    TH0 = 0;        // Reg's.
    TR0 = 1;        // Set timer to run.
    ET0 = 1;        // Set interrupt.
    EA = 1;            // Set global interrupt.
    while (1)
        {
        P0 = ISRvar;    // P0 display's counter.
       }
    }
With C you need to specify the interrupt number.. Here I have used __interrupt (1)
This can be found in the C documentation....


There are priority settings... You can select each interrupt to a high or low setting.. High priority take precedent over the low priority interrupts. This can be found in the IP0 register..

1p0 reg.png


1 = High priority
0 = low priority

The precedence of importance ( if they are all set high / low ) is as the register itself. EX0 is the highest and ES is the lowest.

As with the other tutorial I will do the external interrupt.

Here is the asm code.
Code:
    org    0x0
    sjmp    Main        ; Short jump to our main code

    org    0x03
    ajmp    ISR        ; Absolute jump to the ISR
Main:
    setb    EX0        ; set INT0 interrupt
    setb    EA        ; Set global interrupts
    clr    ISRvar        ; clear count byte

while:
    mov    P0, ISRvar    ; Put the count
    sjmp    while        ; On PORT 0

ISR:
    mov    A, ISRvar    ; Get variable into Acc
    inc    Acc        ; increase by one
    mov    ISRvar,Acc    ; stick it back

    reti

    end
And of course for completeness here is the C version
C:
#include <mcs51reg.h>

volatile int ISRvar;    // ISR counter variable.

void INT_ISR(void) __interrupt (0)
    {
    ISRvar++;        // Increment counter variable.
    }

void main(void)
    {
    EX0 = 1;        // Set interrupt.
    EA = 1;            // Set global interrupt.
    while (1)
        {
        P0 = ISRvar;    // P0 display's counter.
       }
    }
Finally we put them together to have two interrupts running at the same time.
Code:
$mod51

ISRvar    equ    0x30        ; Reserve a byte to hold a count

    org    0x0
    sjmp    Main        ; Short jump to our main code

    org    0x03
    ajmp    ISRint        ; Absolute jump to the ISR for int0

    org    0x0B
    ajmp    ISRtim        ; Absolute jump to the ISR for timer
Main:
    mov    TH0,#0x00       ; Clear
    mov    TL0,#0x0       ; timer regs
    setb    TR0           ; start timer 0
    setb    ET0           ; set timer 0 interrupt
    setb    ET0        ; set Tmer interrupt
    setb    EX0        ; set INT0 interrupt
    setb    EA        ; Set global interrupts
    clr    ISRvar        ; clear count byte

while:
    mov    P0, ISRvar    ; Put the count
    sjmp    while        ; On PORT 0

ISRint:
    clr    ISRvar
    reti

ISRtim:
    mov    A, ISRvar    ; Get variable into Acc
    inc    Acc        ; increase by one
    mov    ISRvar,Acc    ; stick it back

    reti

    end
And the same again in C...

C:
#include <mcs51reg.h>

volatile int ISRvar;    // ISR counter variable.

void int_ISR(void) __interrupt (0)
    {
    ISRvar = 0;        // Reset counter variable.
    }

void Timer0_ISR(void) __interrupt (1)
    {
    ISRvar++;        // Increment counter variable.
    }

void main(void)
    {
    TMOD = 0x3;        // Timer mode 3
    TH0 = 0;        // Clear
    TL0    = 0;        // registers
    TR0    = 1;        // Start timer
    ET0 = 1;        // Set timer interrupt
    EX0 = 1;        // Set int0 interrupt.
    EA = 1;            // Set global interrupt.
    while (1)
        {
        P0 = ISRvar;    // P0 display's counter.
       }
    }
Notice that in C, the level precedence is 0 ( highest )
Also remember that there is no debounce function on the INT0 pin so if this were to be used in a real device, this must be taken into account..

This concludes this little example... I am going to do more tutorials for the 8051 in a similar fashion as this..

If you have any questions, or you would like me to concentrate on a specific piece of code then leave a comment and I'll reply as soon as I can.

Cheers
Ian
  • Like
Reactions: RonaldB

Latest reviews

Nice tutorial. Started late on 8051, but I'll give it a try. Good thing the C code was included...bit readable than the ASM.

Latest threads

EE World Online Articles

Loading
Top