Timers in 8051 - Notes
Timers in 8051 - Notes
8051 Clock
Every Timer needs a clock to work, and 8051 provides it from an external crystal which is the
main clock source for Timer. The internal circuitry in the 8051 microcontrollers provides a
clock source to the timers which is 1/12th of the frequency of crystal attached to the
microcontroller, also called Machine cycle frequency.
For example, suppose we have a crystal frequency of 11.0592 MHz then the microcontroller
will provide 1/12th i.e.
8051 Timer
8051 has two timers Timer0 (T0) and Timer1 (T1), both are 16-bit wide. Since 8051 has 8-bit
architecture, each of these is accessed by two separate 8-bit registers as shown in the figure
below. These registers are used to load timer count.
8051 has a Timer Mode Register and Timer Control Register for selecting a mode of
operation and controlling purpose.
TMOD register
TMOD is an 8-bit register used to set timer mode of timer0 and timer1.
Its lower 4 bits are used for Timer0 and the upper 4 bits are used for Timer1
1 = Enable Timer/Counter only when the INT0/INT1 pin is high and TR0/TR1 is set.
1 = Use as Counter
0 = Use as Timer
These are Timer/Counter mode select bit as per the below table
M1 M0 Mode Operation
0 0 0 (13-bit timer mode) 13-bit timer/counter, 8-bit of THx & 5-bit of TLx
M1 M0 Mode Operation
Split the 16-bit timer into two 8-bit timers i.e. THx and
1 1 3 (split timer mode)
TLx like two 8-bit timer
TCON Register
TCON is an 8-bit control register and contains a timer and interrupt flags.
1 = Timer1 overflow occurred (i.e. Timer1 goes to its max and roll over back to zero).
It is cleared through software. In the Timer1 overflow interrupt service routine, this bit will
get cleared automatically while exiting from ISR.
1 = Timer1 start.
0 = Timer1 stop.
1 = Timer0 overflow occurred (i.e. Timer0 goes to its max and roll over back to zero).
It is cleared through software. In the Timer0 overflow interrupt service routine, this bit will
get cleared automatically while exiting from ISR.
1 = Timer0 start.
0 = Timer0 stop.
Timers have their operation modes which are selected in the TMOD register using M0 & M1
bit combinations.
Example
Let's generate a square wave of 2mSec period using an AT89C51 microcontroller with timer0
in mode0 on the P1.0 pin of port1. Assume xtal oscillator frequency of 11.0592 MHz.
As the Xtal oscillator frequency is 11.0592 MHz we have a machine cycle of 1.085uSec.
Hence, the required count to generate a delay of 1mSec. is,
The maximum count of Mode0 is 2^13 (0 - 8191) and the Timer0 count will increment from
0 – 8191. So we need to load value which is 921 less from its maximum count i.e. 8191.
Also, here in the below program, we need an additional 13 MC (machine cycles) from call to
return of delay function. Hence value needed to be loaded is,
1C74 = 0001 1100 0111 0100 b, now load lower 5-bit in TL0 and next 8-bit in TH0
so here we get,
Example
Let’s generate a square wave of 2mSec time period using an AT89C51 microcontroller with
timer0 in mode1 on the P1.0 pin of port1. Assume Xtal oscillator frequency of 11.0592 MHz.
And mode1 has a max count is 2^16 (0 - 65535) and it increments from 0 to 65535 so we
need to load value which is 921 less from its max. count i.e. 65535. Also, here in the below
program, we need an additional 13 MC (machine cycles) from call to return of delay
function. Hence value needed to be loaded is,
So we need to load FC74 Hex value higher byte in TH0 and lower byte in TL0 as,
Example
Here we are generating a square wave on PORT1.0 with 200uSec. time period using Timer1
in mode2. We will use 11.0592 MHz Xtal oscillator frequency.
As Xtal is 11.0592 MHz we have a machine cycle of 1.085uSec. Hence, the required count to
generate a delay of 1mSec. is,
And mode2 has a max count is 2^8 (0 - 255) and it increment from 0 – 255 so we need to
load value which is 92 less from its max. count i.e. 255. Hence value need to be load is,
TH1 = 0xA4
Programming steps for delay function in
8051 MCU
1. Load Tmod register value i.e. TMOD = 0x20 for Timer1 mode2 (8-bit timer auto
reload mode).
2. Load calculated THx value i.e. here TH1 = 0xA4.
3. Load same value for TLx i.e. here TL1 = 0xA4.
4. Start the timer by setting a TRx bit. i.e. here TR1 = 1.
5. Poll TFx flag till it does not get set.
6. Clear timer flag TFx bit i.e. here TF1 = 0.
7. Repeat from step 5 and 6 for the delay again.
void main()
{
TMOD = 0x20; /* Timer1 mode2 (8-bit auto reload tim
er mode) */
TH1 = 0xA4; /* Load 8-bit in TH1 */
TL1 = 0xA4; /* Load 8-bit in TL1 once */
TR1 = 1; /* Start timer1 */
while(1)
{
test = ~test; /* Toggle test pin */
while(TF1 == 0); /* Wait until timer1 flag set */
TF1 = 0; /* Clear timer1 flag */
}
}
Timer interrupt in 8051 Microcontroller
8051 has two timer interrupts assigned with different vector address. When Timer count rolls
over from its max value to 0, it sets the timer flag TFx. This will interrupt the 8051
microcontroller to serve ISR (interrupt service routine) if global and timer interrupt is
enabled.
The timer overflow interrupt assigned with the vector address shown in the table. 8051
microcontroller jumps directly to the vector address on the occurrence of a corresponding
interrupt.
Example
Here we will generate a square wave of 10Hz on PORT1.0 using Timer0 interrupt. We will
use Timer0 in mode1 with 11.0592 MHz oscillator frequency.
As Xtal is 11.0592 MHz we have a machine cycle of 1.085uSec. Hence, the required count to
generate a delay of 50mSec. is,
Count =(50×10^(-3)) / (1.085×10^(-6) ) ≈ 46080
And mode1 has a max count is 2^16 (0 - 65535) and it increment from 0 – 65535 so we need
to load value which is 46080 less from its max. count i.e. 65535. Hence value need to be load
is,
So we need to load 4C00 Hex value in a higher byte and lower byte as,
Note that the TF0 flag no need to clear by software as a microcontroller clears it after
completing the ISR routine.
void Timer_init()
{
TMOD = 0x01; /* Timer0 mode1 */
TH0 = 0x4C; /* 50ms timer value */
TL0 = 0x00;
TR0 = 1; /* Start timer0 */
}
int main(void)
{
EA = 1; /* Enable global interrupt */
ET0 = 1; /* Enable timer0 interrupt */
Timer_init();
while(1);
}