Why LED is not turning OFF - 8051 Timers

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Hi
I want to ON/OFF LED for 500 ms. I have written a program that suppose to ON/OFF LED for 500 ms

Environment : AT89C51, Keil,

C:
#include<reg51.h>

sbit LED   = P2^0;    /*LED connected at output Pin P2.0 */

#define LED_ON   1     // LED Turn ON
#define LED_OFF  0     // LED Trn OFF

/* Function to generate Delay*/
void Delay(DelayTime)
{
    unsigned int count;
    
    for ( count = 0; count < DelayTime; count)

       {
            
             }             
}

int main ()
{
     LED = LED_ON;  //LED Turn On
     Delay(5000000);     //Wait 500 millisecond
     LED = LED_OFF; //LED Trn OFF
     Delay(5000000);   // Wiat 500 millisecond

    return 0;
}
When I compile code, LED turn on/off once for very short time and then goes off for forever. I don't have any idea why code it not working as it suppose to do ?

Edit, at the movement I do not want to use nested loop in delay function
 
Last edited:

MrChips

Joined Oct 2, 2009
30,709
5000000 is a very large number.
What is the largest number that can be represented in unsigned int count?

Line 9 is missing a type declaration.

You also have an error in line 13.
count never gets incremented.

Your program ends after line 27.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
5000000 is a very large number.
What is the largest number that can be represented in unsigned int count?

Line 9 is missing a type declaration.

You also have an error in line 13.
count never gets incremented.

Your program ends after line 27.
@MrChips Thanks for point out errors in program. Problem has been solved
C:
#include<reg51.h>

sbit LED   = P2^0;    /*LED connected at output Pin P2.0 */

#define LED_ON   1     // LED Turn ON
#define LED_OFF  0     // LED Trn OFF

/* Function to generate Delay*/
void Delay(unsigned int DelayTime)
{
    unsigned int count;
     
    for ( count = 0; count < DelayTime; count++)
 
       {
             
             }              
}
int main ()
{
 
     LED = LED_OFF; //LED Trn OFF
     Delay(65535);     //Wait
   LED = LED_ON;  //LED Turn On
     Delay(65535);   // Wiat
 
    return 0;
}
External crystal 11.952 Mhz is connected to AT89C51. I want 500ms Delay, How much time delay generate by 65535 counts ?
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
External crystal 11.952 Mhz is connected to AT89C51. I want 500ms Delay, How much time delay generate by 65535 counts ?
You can't know what you set delay value to unless you inspect the code generated by the C compiler and know how many instruction cycles are in each loop. Different instructions take 1, 2 or 3 cycles. Each cycle is typically 12 clocks but some 8051 variants can run at 4X or 12X speed depending on the firmware settings. It's not an easy task and requires detailed knowledge of the chip's instruction set and internal timing. I think most programmers just try various values to see what to use.

I can tell you that 500ms from one 16 bit integer is a stretch. You'll need to nest loops or write a routine that delays 1ms and call it 500 times. The time won't be exact but at least you'll get there.
You should realize that long blocking delays will become a problem as your programs get more complex.

Also, your code should use a while(1) loop around the LED program to keep it from returning from main. Embedded systems do not have a place to return to. It only works because the C startup code the Keil provides will loop around for you.
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
How to get delay for 50 ms?

IMG_20200831_173443.jpg

There are three methods
1. Software delay time
2. Polling method
3. Timer interttupt

We can't find the exact delay with software delay , so I will use the Polling method.

I do not understand how much value need to load in the timer register to get required delay time ( timer mode 0 with 00 bits)

Page 87 Timer mode register
Timer 0 mode 00
8 bit Timer/ counter with 5 bit prescaler

How much delay time can we get in mode 0 ?

For timer interttupt I have gone through datasheet but I don't find global interrupt in datasheet Where is the global interrupt given in datasheet?
 

Attachments

Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
For timer interttupt I have gone through datasheet but I don't find global interrupt in datasheet Where is the global interrupt given in datasheet?
The IE register is actually not described in that datasheet. I don't know why. You might need to find a Programmer's Reference from Microchip. While you look for that, here's the original Intel 8051 datasheet that describes the missing registers.

To find how much delay you can get from a timer you need to know the frequency into the timer and how many bits, including any prescalers, the timer has. The timer times by simply counting up the input frequency. Add all of that up and you'll know how much time you can get.
 

Attachments

JohnInTX

Joined Jun 26, 2012
4,787
The timers are thoroughly discussed beginning on page 3-9 of the Intel document I posted. Figure 7 shows how it is all organized. Why not try a sample calculation on your own?
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
The timers are thoroughly discussed beginning on page 3-9 of the Intel document I posted. Figure 7 shows how i. Why not try a sample calculation on your own?
Timer Calculation

1 megahertz = 1 000 000 hertz
Fosc = 11.0592Mhz = 11059200 hertz

Tick = (1/(Fosc/12)
Tick = 12/Fosc
For Fosc = 11059200 hertz

The tick time will be Tick = 12/ 11059200 hertz = 1.085069444us = 1.085us

Mode 0 13 bit timer
2^13 = 8192 maximum counts

8192 *1.085 / one tick = 8,888.32 us

Required Delay = 1ms = 1000 us

Now the Timer value for the required delay can be calculated as below.

Delay = TimerCount * tick
Count = (Delay/tick)
Count = 1000 us /1.085us = 921.658986

Register Value = Timer Maximum- Count

Register Value = Timer Maximum - (Delay/tick)

Register Value = 8192 - (1000/1.085us)

Register Value = 8192 - 921.658 = 7270
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
You have the basic idea but you are treating the prescaler as if it were part of the count setting. In mode 0, the prescaler just reduces the input frequency to the 8 bit timer by 2^5. So your calculations would be:

  • Freq into the 8 bit timer = 11.059MHz /12 /32 (prescaler) = 28800Hz. The input period to the 8 bit timer is 34.7222 uSec. So 34.7222 uSec/count.
  • 1msec / 34.7222 uSec/count = 28.8 counts.
  • The timer runs from its preset count and rolls over when it goes from 255->0 (FFh -> 00h) so to get 28.8 counts you have to subtract it from the terminal count:
  • 256 - 28.8 = 227.2
  • Round to 227 and that's your preset for the 8 bit timer.
  • To make a period timer, you must reset the 8 bit timer each time it rolls over. Take a look at Mode 2.

Note that Mode 0 is there for backwards compatibility with the earlier MCS-48 controllers. If you use Mode 1, then you get a full 16 bit timer instead of an 8 bit timer with a 5 bit prescaler. The arithmetic is similar but you can get closer to the exact value. Mode 2 uses 8 bits but has an auto-reload so you don't have to reload the timer each time it runs out.

Either way, that's how it works.
Good job.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
[*]Freq into the 8 bit timer = 11.059MHz /12 /32 (prescaler) = 28800Hz. The input period to the 8 bit timer is 34.7222 uSec. So 34.7222 uSec/count.
[*]1msec / 34.7222 uSec/count = 28.8 counts.
[*]The timer runs from its preset count and rolls over when it goes from 255->0 (FFh -> 00h) so to get 28.8 counts you have to subtract it from the terminal count:
[*]256 - 28.8 = 227.2
[*]Round to 227 and that's your preset for the 8 bit timer.
[*]To make a period timer, you must reset the 8 bit timer each time it rolls over. Take a look at Mode 2.
[/LIST]
For the 5ms time delay

5000/ 34.7222 uSec/count = 144.0counts.

256-144= 112

TH0 = 0x70 = 0b01110000 High to Low bit
TL0 = 0xF8 = 0b11111000 High to Low

Is this the way we load values into the timer register?
 

JohnInTX

Joined Jun 26, 2012
4,787
What is wrong with it?
8 bit timer with 5 bit prescaler
In Mode 0 you don't load anything into the prescaler (TL0). The prescaler just reduces the frequency to the 8 bit TH0.
Your values would be correct in Mode 1 (16bit) IF you swap them around.
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
My teacher had suggested me stm32f407 microcontroller. I have to make project in final year. The project has not been decided yet but she said that in my project I have to use STM32 microcontroller so I have to practice it
So... like @jpanhalt , I am wondering why you are not studying the ARM. It also puzzles me that you said you had done everything in your 8051 syllabus but you didn't use the timers?
Hmm..
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
So... like @jpanhalt , I am wondering why you are not studying the ARM. It also puzzles me that you said you had done everything in your 8051 syllabus but you didn't use the timers?
Hmm..
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
 
Top