Why LED is not turning OFF - 8051 Timers

JohnInTX

Joined Jun 26, 2012
4,787
Why do you think that led doesn't toggle approx 40 ms time?
Because I did the math for calculating TH0. You missed subtracting 256-29
AND even if the timer had a 1ms period, you are only counting 29 of them, not 40.
AND you are not reloading the timer after an overflow so it will run at the full 8.88ms period after the first time
AND you are manually setting TF0 just before you test for the first overflow so whatever you set the timer to the first time is ignored anyway
So.. that’s why I don’t think it’s toggling at 40ms intervals.

Personally, I would have re-checked my work before asking a question and waiting hours or days for a clarification. If you are going to survive your year end project, you need to do that.

Anyway, you can do a rough time time test by using a stopwatch (smartphone) and timing some number of counts - 20 or more. You can also take a smartphone video of the flashing. Replay the video. Stop and slide through the replay and observe the timeline values between flashes. If your IDE has a simulator, you can use it to time program execution between breakpoints. Lot of options to try..
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Anyway, you can do a rough time time test by using a stopwatch (smartphone) and timing some number of counts - 20 or more. You can also take a smartphone video of the flashing. Replay the video. Stop and slide through the replay and observe the timeline values between flashes. If your IDE has a simulator, you can use it to time program execution between breakpoints. Lot of options to try..
40 ms is very short time to observe so I took 10 seconds and I have observed with clock. LED turn ON for 10 seconds and turn OFF for 10 seconds
C:
#include<reg51.h>

sbit LED =  P2^0;  /* LED connected to Port P2.0 */


void main (void)  /* Program start */
{
  int Counter = 0; 

  TMOD = 0x00;         /*Timer mode0 */
  TH0 = 227;           /* Load 8-bit in TH0 */
  TL0 = 0;            /* Load 5-bit in TL0 */
  TR0 = 1;             /* Start timer0 */
  TF0 = 0;             /* Enable Timer0 overflow flag TF0 */

    while(1)
    {
       if (TF0 == 1)   /* check Timer0 overflow flag */
        {                               
           Counter++;  /* Increment counter */
                    
           TH0 = 227;         /* Reload Load 8-bit in TH0 */
           TL0 = 0;          /* Reload Load 5-bit in TL0 */    
                    
             if (Counter == 10000 )
             {
                 LED =~ LED;               // Toggle LED //
                             
                 Counter = 0;
             }                        
                         
             TF0 = 0;             /* clear Timer0 overflow flag */    
              }
        }
    }
Thanks for giving idea of clock, Now I understood how to set timer for specific delays.
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
I'm happy you got something working.

Here are a couple of things to think about that apply to Mode 0, Mode 1 and some PIC timers too:
  • When you are working with a timer that has to be reloaded each cycle, reload it as soon as possible after it rolls over to minimize lost counts. The timer is running while you do Counter++ and you will lose the counts accumulated when you reload the timer.
  • You don't want to reload the prescaler on each cycle. It is accumulating counts since TF0 and you don't want to lose them.
  • Consider ADDING the timer value to TH0 so that you don't lose any accumulated counts there.
BUT!
Now that you understand the basics, why not use Mode 2? Once you set it up, it automatically reloads the timer so you never lose any counts at all.

Ultimately, you want to use a timer that interrupts the processor at regular intervals to generate delays etc. 8051 Mode 2 and PIC Timer2/PR2 is the preferred method to do that.

Have fun!

EDIT: removed incorrect description of Mode 2
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Now that you understand the basics, why not use Mode 2? Once you set it up, it automatically reloads the timer so you never lose any counts at all. TL0 is the counter. Load TH0 once with the number of counts to do, clear TL0 and TF0. When TL0 counts up to the value in TH0, TF0 will be set and TH0 will automatically be reset to 0 to count again. Note that in this mode, the timer counts up from 0 to some count so your math to set TH0 doesn't require subtracting the counts from 256. In a PIC, you use Timer 2 and PR2 to do the same thing.
Have fun!
Let's say that the TH0 hold 0H and it is in timer0 mode2 , only TL0 Do count, the count range is 0~255 The value of TH0 does not change but the original value is kept. After TL0 overflows, then TF1 will be directly set and the original value of TH0 is directly assigned to TL0, and then TL0 starts counting from the newly assigned value

When TL0 run from 0 to 255 it takes 256* 1.085 =277.76 uSec

1S = 1000000 USec
10 S = 10000000 USec

10000000 / 277.76 =36002. 30

C:
#include<reg51.h>

sbit LED =  P2^0;  /* LED connected to Port P2.0 */

void main (void)  /* Program start */
{
  int Counter = 0;

  TMOD = 2;         /*Timer mode0 */
  TH0 = 00;           /* Load 8-bit in TH0 */

  TR0 = 1;             /* Start timer0 */
  TF0 = 1;             /* Enable Timer0 overflow flag TF0 */

    while(1)
    {
       if (TF0 == 1)   /* check Timer0 overflow flag */
        {                          
           Counter++;  /* Increment counter */
                               
             if (Counter == 36002 )
             {
                 LED =~ LED;               // Toggle LED //
                        
                 Counter = 0;
             }                   
                    
             TF0 = 0;             /* clear Timer0 overflow flag */           
         }
       }
    }
When I run the code LED only blink for short time Code not working as it suppose to do ?

I am trying to understand What's wrong with code or calculation ?
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
Try setting TH0 = 1 in the initialization.
Line 13 should say:
TF0 = 0. Also, Remove the comment, it is incorrect.

if (Counter == 36002)...
If 'Counter' is a signed integer (default), it can't have a value that big, yes?
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
@Djsarakar
Note the later comment about the counter.
Did the compiler issue a warning about this?
Compiler doesn't show any warning. When I run below code LED only turn on/off for very short time and after that its turning off
C:
#include<reg51.h>

sbit LED =  P2^0;  /* LED connected to Port P2.0 */


void main (void)  /* Program start */
{
long int Counter = 0;

  TMOD = 2;         /*Timer mode0   <<<---- IT'S MODE 2!! */
  TH0 = 1;           /* Load 8-bit in TH0 */
 
  TR0 = 1;             /* Start timer0 */
  TF0 = 0;         

    while(1)
    {
       if (TF0 == 1)   /* check Timer0 overflow flag */
        {                            
           Counter++;  /* Increment counter */
                                 
            if (Counter == 36002 )
             {
                 LED =~ LED;               // Toggle LED //                     
                 Counter = 0;
             }                                        
         TF0 = 0;             /* clear Timer0 overflow flag */ 
          }// if TF0
  }// while
}//main
Mod edit: fixed bracket lost during reformatting - JohnInTX
 
Last edited by a moderator:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Seems like it should work.
i got some code on internet so i have modified it little bit so when I run following code I get led toggle at every 7 seconds

C:
 // Use of Timer mode 2 for blinking LED with polling method
// XTAL frequency 11.0592MHz
#include<reg51.h>

sbit led = P2^0; // LED connected to 1st pin of port P1void delay();

void delay()
{
TMOD = 0x02; // Mode1 of Timer0
TH0= 0x01; // Initial value loaded to Timer
TR0 = 1; // Start Timer
while(TF0 == 0); // Polling for flag bit
TR0 = 0; // Stop Timer
TF0 = 0; // Clear flag
}


main()
{
long unsigned int i;
while(1)
{
led=~led; // Toggle LED
for(i=0;i<20850;i++)
delay(); // Call delay
}
}
 

trebla

Joined Jun 29, 2019
547
In you #52 posting the last code line what i can see is 29. After that must be at least one line with closing curly bracket for main() function. Is that pesent in your code and you mistakenly not copied it there?
 

JohnInTX

Joined Jun 26, 2012
4,787
In you #52 posting the last code line what i can see is 29. After that must be at least one line with closing curly bracket for main() function. Is that pesent in your code and you mistakenly not copied it there?
That's probably my fault. I edited the source formatting to check for that very thing on an iPad. Not the best editing tool and I should have known better.
Good catch!
Thanks.
 

JohnInTX

Joined Jun 26, 2012
4,787
FWIW, I ran up the code in #52 in a simulator after correcting the bracket mistake noted by @trebla and declaring Counter as unsigned int. It toggles the LED bit every 9.961490 seconds as predicted by the calculations. TF0 is set every 276.692uS so that too is as expected.
The exercise in #52 using Mode 2 should work on your board.

Rather than burning time scouting around for MORE non-relevent code on the internet, you should invest that time learning to use the Debug/Simulator in the Keil uVision IDE. It will show you how the code works - or doesn't and allow you to confirm your calculations. If you move to PIC or ARM, you need to learn those simulators as well. You have a license built PK3. It should function as a hardware debugger under MPLABX. Learn to use that too.

I think I'm done. That's about all I have to offer on this one.

Have fun going forward.

C:
#include<reg51.h>

sbit LED =  P2^0;  /* LED connected to Port P2.0 */
unsigned int Counter = 0;

void main (void)  /* Program start */
{
  TMOD = 2;         /*Timer mode0   <<<---- IT'S MODE 2!! */
  TH0 = 1;           /* Load 8-bit in TH0 */

  TR0 = 1;             /* Start timer0 */
  TF0 = 0;
    
  while(1)
  {
       if (TF0 == 1)   /* check Timer0 overflow flag */
        {                         
           Counter++;  /* Increment counter */
                              
            if (Counter == 36002 )
             {
                 LED =~ LED;               // Toggle LED //                   
                 Counter = 0;
             }                                     
         TF0 = 0;             /* clear Timer0 overflow flag */
         }// if TF0
  }// while
}//main
Edit: it works with the original counter as a long int too.
 
Last edited:

BobaMosfet

Joined Jul 1, 2009
2,113
I have studied but do not know much in deep, I completed 20 experiments in lab. I focused more on theoretical subjects because if I failed I would have ruined year. Now I understand that my approach to solving the problem was wrong. I should have written my own code instead of looking code on the internet.

I have time to cover the basic, so I have restarted the programming of 8051. When I get confidence that I know a l
something, I will start with advance microcontroller
Learn to flow-chart. Seriously. Amateurs don't do it, professionals do. Fastest way to analyze any logic problem.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
After many attempts, Following code is working for me

So problem was with initlization. I just initlized ports and my problem was solved

C:
#include<reg51.h>

sbit LED =  P2^0;  /* LED connected to Port P2.0 */
unsigned int Counter = 0;

void main (void)  /* Program start */
{
    P0 = 0;
    P1 = 0;
    P2 = 0;
    P3 = 0;
   
  TMOD = 2;         /*Timer mode0   <<<---- IT'S MODE 2!! */
  TH0 = 1;           /* Load 8-bit in TH0 */

  TR0 = 1;             /* Start timer0 */
  TF0 = 0;
   
  while(1)
  {
       if (TF0 == 1)   /* check Timer0 overflow flag */
        {                        
           Counter++;  /* Increment counter */
                             
            if (Counter == 36002 )
             {
                 LED =~ LED;               // Toggle LED //                  
                 Counter = 0;
             }                                    
         TF0 = 0;             /* clear Timer0 overflow flag */
         }// if TF0
  }// while
}//main
 
Last edited:
Top