8051 Interrupt and Timer Using C
8051 Interrupt and Timer Using C
com/site/enggprojectece
Note: It is a practical guide in which it is presumed that the reader has already learned about the
hardware architecture, programming model, and assembly language programming of 8051
microcontroller. In case you are totally new to 8051 microcontroller I recommend you to read the
8051 Tutorial available at:
https://sites.google.com/site/enggprojectece/my-reading-list
It has also been presumed that the reader has at least the beginner level knowledge of computer
programming in C language (user defined functions, data types, header files, loops and the flow of a C
program).
In this tutorial first an introduction to Embedded C is given. A few examples are shown. Then the
implementation of timer and interrupt are discussed.
(All programs shown here are compiled and executed using Keil Vision 3)
Pin Diagram of 8051
(please note the pins used for external interrupts INT0 & INT1, Serial Port Transmitter TxD,
Serial Port Receiver RxD, Counter input for Timer-0 T0 and Counter input for Timer-1 T1)
Embedded C
The syntax of embedded C is the same as the C language that we use for writing computer programs.
The only difference is the libraries and hence the functions. Particularly for 8051 based
microcontrollers, the header file <REGX51.H> has to be added. In this header file the addresses of all
the special function registers (SFRs) and other memory locations are defined. Hence we can access an
SFR by simply writing its name. We dont need to use the registers of the programming model (A, B,
R0, R1, R2, , R7) because when the compiler compiles the compiles the C program, it actually
converts the program into an equivalent assembly language program. In this process the compiler
itself uses the registers in an optimized manner to represent the variables that we define in the C
program.
Lets see a simple program to blink an LED at a fixed interval.
#include <REGX51.H>
sbit x=P0^0; //x is defined as a binary variable to represent bit-0 of
// port P0
void delay() //delay program
{
int i,j;
for(i=0;i<1000;i++)
for(j=0;j<1000;j++);
}
void main()
{
x=0; //This will define P0^0 as an output port.
while(1)
{
x=!x;
delay();
}
}
In the program we can see that the delay is achieved by running two nested empty loops to achieve
some fixed delay. It is assumed that the LED is connected to the bit 0 of port P0 (P0.0).
It is totally inconvenient to know the exact duration of the delay as we dont know what assembly
code is generated by the compiler to implement this C code. It may vary from compiler to compiler.
Even if we know, it requires lots of calculations. Another drawback is that the achieved delay must be
an integral multiple of the time required to execute one empty for-loop used in the program.
As we can see the entire processor remains busy in keeping track of whether the selected bit is set or
reset. We cannot risk including some additional task into the program because it may lead to miss
some event when it is busy in executing additional tasks.
TCON and TMOD registers are used for controlling the two timers. TH0 and TL0 jointly store the
current 16-bit (2 bytes) value of Timer 0. Similarly, TH1 and TL1 store the current value of Timer 1.
If we initialize the Timer register with some value then it will start counting up from that value. In this
way we can make the timer to reach its maximum value at the required instant of time. After reaching
this maximum value the timer will overflow, that is, it will start from zero (0000h).
TMOD Register
Bit
7
Name
GATE1
C/T1
5
4
3
T1M1
T1M0
GATE0
C/T2
1
0
T0M1
T0M0
Description
When this bit is set the timer will only run when INT1 (P3.3) is high.
When this bit is clear the timer will run regardless of the state of
INT1.
When this bit is set the timer will count events on T1 (P3.5). When
this bit is clear the timer will be incremented every machine cycle.
Mode select for Timer 1
When this bit is set the timer will only run when INT0 (P3.2) is high.
When this bit is clear the timer will run regardless of the state of
INT0.
When this bit is set the timer will count events on T0 (P3.4). When
this bit is clear the timer will be incremented every machine cycle.
Mode select for Timer 0
Timer
1
1
1
1
0
0
0
0
TxM0
0
1
0
1
Timer Mode
Mode 0
Mode 1
Mode 2
Mode 3
Description of Mode
13 - bit timer (0000h to 1FFFh)
16 - bit timer (0000h to FFFFh)
8 - bit (00h to FFh) auto reload
Split Timer Mode
*x can be either 0 or 1.
(Read the concepts of auto-reload and split timer from the 8051 Tutorial mentioned above or some
book)
As you may notice, weve only defined 4 of the 8 bits. Thats because the other 4 bits of the SFR dont have
anything to do with timers they have to do with Interrupts and they will be discussed in the chapter that
addresses interrupts.
Bit Address
9Fh
9Eh
9Dh
9Ch
9Bh
9Ah
99h
98h
Description
Serial port mode bit 0
Serial port mode bit 1
Multiprocessor communication enable
Receive Enable. This bit must be set to receive characters.
Transmit Bit 8. The 9th bit to transmit in mode 2 and mode 3
Receive Bit 8. The 9th bit to receive in mode 2 and mode 3
Transmit Flag. Set when a byte has been completely transmitted
Receive Flag. Set when a byte has been completely received
Timer 0 Overflow.
Timer 1 Overflow.
Reception/Transmission of Serial Character.
External Event 0.
External Event 1.
We need to be able to distinguish between various interrupts and executing different code depending
on what interrupt was triggered. This is accomplished by jumping to a fixed address (known as
interrupt vector) when a given interrupt occurs. These addresses are stored in a inbuilt table inside the
microcontroller called interrupt vector table.
The SFRs used for setting and controlling interrupts in 8051 are:
1. Interrupt Enable (IE) SFR: Address 0A8h
2. Interrupt Priority (IP) SFR: Address 0B8h
3. Lower 4 bits of the TCON SFR for external interrupt control
IE SFR
Bit
7
6
5
4
3
2
1
0
Name
EA
ES
ET1
EX1
ET0
EX0
Bit Address
AFh
AEh
ADh
Ach
ABh
AAh
A9h
A8h
Description
Global Interrupt Enable/Disable
Undefined
Undefined
Enable Serial Interrupt
Enable Timer 1 Interrupt
Enable External 1 Interrupt
Enable Timer 0 Interrupt
Enable External 0 Interrupt
Interrupt Priority
When more than one interrupts are enabled, it is necessary to set priority of interrupts. The priority of
an interrupt can be high or low. A high priority interrupt can interrupt the service routine of a low
priority interrupt.
So use of these bits can give more sophisticated control over external interrupt which may of use for
certain applications. However, we dont use these bits in our examples.
When external interrupt occurs, read the present value of port 0 and disable the interrupt.
Start timer to calculate 2 second elapse (calculation of time shown below).
Multiply the value with 2.
When 2 seconds are over, display the result at port 1 and enable the interrupt.
Calculation of time:
Let the clock frequency be 12 MHz. The number of machine cycles required for 2 sec is: 2106
With reference to example 1, if we set timer to be elapse at 50,000 machine cycles, then number of
times the timer needs to overflow is:
2,000,000
= 40
50,000
So here maximum value of counter will be 40. Let us use timer interrupt to increment counter.
Interrupt Table
The interrupt number is required to write the interrupt service routine in embedded C.
Program:
#include <REGX51.H>
int counter;
bit flag;
sbit ext_int=P3^2;
void timer0_isr (void) interrupt 1 //timer 0: serial no. 1 in table
{
TH0=0x3c;
TL0=0xaf; //initialize timer for next overflow
TR0=1; //start timer
counter++;
}
void extern0_isr (void) interrupt 0 //external 0: serial no. 0 in table
{
ext_int=1;