# 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...

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.. 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

org    0x03

org    0x0B
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
• 1.2 KB Views: 6,279
• 1.1 KB Views: 6,292
RonaldB
Author
Ian Rogers
Views
5,296
First release
Last update
Rating
1 ratings