Interrupt Functions

The 8051 and its derivatives provide a number of hardware interrupts that may be used for counting, timing, detecting external events, and sending and receiving data using the serial interface. The standard interrupts found on an 8051 are listed in the following table:

Interrupt Number

Interrupt Description

Address

0

EXTERNAL 0

0003h

1

TIMER/COUNTER 0

000Bh

2

EXTERNAL 1

0013h

3

TIMER/COUNTER 1

001Bh

4

SERIAL PORT

0023h

The C51 compiler provides you with a method of calling a C function when an interrupt occurs. This support allows you to create interrupt service routines in C. You need only be concerned with the interrupt number and register bank selection. The compiler automatically generates the interrupt vector and entry and exit code for the interrupt routine. The interrupt function attribute, when included in a declaration, specifies that the associated function is an interrupt function. For example:
unsigned int interruptcnt;
unsigned char second;

void timer0 (void) interrupt 1 using 2
{
if (++interruptcnt == 4000) /* count to 4000 */
{
second++; /* second counter */
interruptcnt = 0; /* clear int counter */
}
}

The interrupt attribute takes as an argument an integer constant in the value range 0 to 31. Expressions with operators are not allowed, and the interrupt attribute is not allowed in function prototypes. The interrupt attribute affects the object code of the function as follows:

    The contents of the Special Function Registers ACC, B, DPH, DPL, and PSW, when required, are saved on the stack at the function invocation time.

    All working registers that are used in the interrupt function are stored on the stack if a register bank is not specified with the using attribute.

    The working registers and special registers that were saved on the stack are restored before exiting the function.

    The function is terminated by the 8051 RETI instruction.

The following sample program shows you how to use the interrupt attribute and what the code generated to enter and exit the interrupt function looks like. The using function attribute is also used in the example to select a register bank different from that of the non-interrupt program code. However, because no working registers are needed in this function, the code generated to switch the register bank is eliminated by the optimizer.

.
.
.
stmt level source
1 extern bit alarm;
2 int alarm_count;
3
4
5 void falarm (void) interrupt 1 using 3 {
6 1 alarm_count *= 2;
7 1 alarm = 1;
8 1 }
.
.
.
ASSEMBLY LISTING OF GENERATED OBJECT CODE
; FUNCTION falarm (BEGIN)
0000 C0E0 PUSH ACC
0002 C0D0 PUSH PSW
; SOURCE LINE # 5
; SOURCE LINE # 6
0004 E500 R MOV A,alarm_count+01H
0006 25E0 ADD A,ACC
0008 F500 R MOV alarm_count+01H,A
000A E500 R MOV A,alarm_count
000C 33 RLC A
000D F500 R MOV alarm_count,A
; SOURCE LINE # 7
000F D200 E SETB alarm
; SOURCE LINE # 8
0011 D0D0 POP PSW
0013 D0E0 POP ACC
0015 32 RETI
; FUNCTION falarm (END)
.
.
.

In the example above, note that the ACC  and PSW  registers are saved at offset 0000h  and restored at offset 0011h. Note also the RETI  instruction generated to exit the interrupt.

The following rules apply to interrupt functions.