We know we can generate delays with the help of loops and/or NOP instructions but we are talking today about 8051 timers. Although the accuracy of exact timings is compromised, yet it satisfies the needs so why are we talking about timer now specifically?
There are some scenarios where we need to do more complex timings tasks rather than a simple LED blink, think about multiplexing context switching or even more time critical applications like real time clock, Timely activated devices, Biomedical or some military applications.
So, in such time critical applications, or in case of such applications where timing events could not compromise, we need some reliable and accurate source to generate and/or handle timely events. Because embedded system is not to be real time it forces microcontroller manufactures and architectural designers to put special circuitry (peripheral) which could generate more a cure clock signals than some software dependent void loops. This end into the timers we are going to talk about in this chapter.
Although delay function we developed earlier seems easier to understand and satisfy our basic needs but we need to build lot more complex and more time critical applications when designing real time embedded system applications so having a dedicated circuit to handle the accuracy to generate clocks or to handle events where time is an important factor, definitely it will save us from lot of software dependent pro, which we may face if we try to do without timers.

8051 Timers

The 8051 microcontroller comes with two built-in timers called timer O and timer 1. These timers are 16-bit and could be used in 8-bit or 13-bit modes as well. We could use these timers for generating precise fixed rate clock pulses or set them to let us know (interrupt) when certain amount of time pass, or we can even use them to as counters to count some external event happening at dedicated pin preassigned to the timers.
See Them in Action.


If you are curious to see what they can do rather than how they do it here is a quick blinky example that we had seen before but modified to be used with timers.

We are going to make led blinking program in keil for 8051 microcontrollers. This program will focus on LED blinking using Timer 0 in the 8051 microcontrollers. We will use the timer0 to create 500 millisecond delay. With the use of that delay, we will blink the LED which is attached to the P2.0 pin in the 8051 microcontroller. The LED is attached in negative trigger or Common Anode mode. Which means when we will send negative to the pin the LED would light up. LED will turn off when we write logic high on the P2.0 pin of the 8051 microcontroller.

8051 microcontroller led blinking in proteus
8051 microcontroller LED blinking with Timer0

Why use Timers for LED Blinking Code

You may aware the LED blinking could be achieved with simply calling a delay function and then toggling the state of the LED. We used this approach in one of our previous posts where we explained the 8051-assembly based LED Blinking program. If you had checked that code, we explained the process of delay making and LED Blinking in assembly language of the 8051 microcontrollers. The problem with that approach is that the code get stuck until the delay is not done. Which means we cannot use the microcontroller in something useful until we are finished doing nothing which is called the delay. But it is waste of resources and the code is blocking in nature. But in real time we have some other things to do rather than just Waite for delay to finish so that we can toggle the LED state. The microcontroller provides built in timers for that specific task for creating timing-based delays.

Introduction to 8051 Timers

8051 microcontrollers normally have two 16-bit timers. These timers are called Timer0 and Timer1. There are some other modern variants of 8051 microcontrollers which also offer additional Timer2 with the same reasons, but we are only focusing on Timer0 in today’s example code. These both timers offer two kind of operations which could be configured using Special Function Registers associated with these timers respectively. These two operations are either to generate timing delays or in Counter based operation. When configured as timer, they will use oscillator to increment the registers and once it is reached the desired count it will update the timer flag. In counter mode external pin is used to get the pulses which these timers then count and thus this operation is known as Counter mode operation. To make the LED Blinking code we need to use the Timer0 in timer mode operation and we are using Mode 2 operation which is auto reload mode. We will talk about this later.

Understanding Timer 0 in 8051 Microcontrollers

In 8051 microcontroller, Timer 0 is built in for managing time-related functions in 8051 microcontrollers. It can be used to generate delays and trigger events also to time intervals. There are two 8-bit registers within Timer0. These registers are called `TH0` and `TL0` and in combination of these two 8bit registers the TIMER0 becomes 16bit Timer. There is another The control register called TCON which is used to configure Timer 0 and set its operating mode.

Timer 0 can operate in two modes: 13-bit and 16-bit. In 13-bit mode, only the lower 8 bits of TL0 are used for counting. In 16-bit mode, both TL0 and TH0 are used for counting, which allows Timer 0 to reach a higher maximum value.

Timer 0 is often used in conjunction with interrupts to manage precise timing events. When Timer 0 overflows, it generates an interrupt signal that can be used to trigger a specific function or task in the microcontroller.

it is very important to understand how Timer 0 works for writing such routines in 8051 microcontrollers which required precise timing operations. If you grab master timer 0 you can unlock a great potential to write complex precise timing programs like stopwatch, or a mini delay on timer-based projects. 

TMOD Register in 8051

TMOD Register in 8051 is a special function register (SFR) which is used to select the timer operation mode. Either it is counter or timer mode which could be selected with C/T bit. So if we write 0 to this bit it will be set in timer mode. This register address is 89H, so if you are accessing this register with direct address you can use this 89H address. But keep one thing in mind that this register is not bit addressable. So you need update the complete register at once. You cannot write individual bits. You can use bit masking techniques in C language. Here is how the TMOD register bits are assigned in the datasheet of the 8051 architecture.

Timer
Timer1 Mode
Timer0 Mode
Bit Details
Gate (G)
C/T
M1
M0
Gate (G)
C/T
M1
M0

LED Blinking using Timer0 Code

Here is the complete C code for LED blinking using Timer0 with interrupts. We intialzed the timer0 in mode 2 timer operation. This mode is auto reload which means we do not have to update the timer registers everytime we done in the interrupt. So we are free to just toggle our LED. But because we are creating delay in milliseconds we are creating a reference volatile variable to count how many times we entered into the interrupt. Based on that, we update the LED state from zero to one or from one to zero. Which in result, create a blinking effect on the P2.0 pin of the 8051 microcontroller. The code is written in Keil uVision 4 compiler. But could easily be adopted with any C compiler of the 8051 microcontroller.

    #include<reg51.h>


   /*

   A program to generate 200us time perriod square wave on P2.0
   Timer0 intterupt is used, 
   we will use timer zero in mode 2 (auto-reload) one half of 
   the period is 100us so, 
   
   100/1 = 100, and TH0 = 256-100 => 156 
   
   generate one mili second delay
   
   1000 us = 1ms so, 
   1000 us / 100 us = 10 times , 
   
   update: 
      in this programe the wave will blink after 500 ms mean half a second,    
   
   */

  sbit wave = P2^0;


unsigned char us_count=0,sec_count=0,min_count=0,hour_count=0;
unsigned int ms_count=0;

void timer0(void) interrupt 1
{
   us_count++;
   if(us_count>9)
    {
 us_count=0;
 ms_count++; 
 if(ms_count>499)
  {
  wave=~wave;
  ms_count=0;
  }
 
 }
 

}

void main()
{

 TMOD = 0x02 ;  
 TH0  = 156 ;
 IE  = 0x82 ;
 TR0  = 1 ;


 while(1);



}



Code language: C++ (cpp)

By Abdul Rehman

My name is Abdul Rehman and I love to do Reasearch in Embedded Systems, Artificial Intelligence, Computer Vision and Engineering related fields. With 10+ years of experience in Research and Development field in Embedded systems I touched lot of technologies including Web development, and Mobile Application development. Now with the help of Social Presence, I like to share my knowledge and to document everything I learned and still learning.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.