Discussion in "8051 Discussion Forum" started by    DavesGarage    Nov 14, 2009.
Sat Nov 14 2009, 04:39 AM
#1
A system tick is a regular event, much like a heart beat, that can be used for a variety of things like delays, reading and writing I/O at regular intervals, checking for error conditions, etc.

More advanced uses might include things like a cooperative scheduler in a multitasking environment.

Getting your first piece of code running on a new target system is always a challenge, and even the simplest program (flashing an LED) requires a delay function.
Sat Nov 14 2009, 05:07 AM
#2
So, where to start?

Firstly, we make a couple of assumptions about our target system:

The crystal frequency will be 12Mhz, and the processor will be a 12-clock/instruction processor.

so, here is the first part of the software:
//=====================================================================
// simple example software for testing system ticker...                
//=====================================================================
#include "AT89X51.H"


We include a header that has our special function registers defined for us. I'm using the Keil development environment, and this header came with it...

Next, we make a few definitions:
// get high order byte from word
#define High(X) ((unsigned char)((X&0xFF00)>
>
8))
 
// get low order byte from word
#define Low(X)  ((unsigned char)(X&0x00FF))        

// 1 millisecond
#define Msec1   64536
                         
// counter for T1 interrupt
volatile unsigned long Ticker;                  


The first two ( High() and Low() ) are macros. High() returns the uppermost 8-bits from a 16-bit value, and Low() returns the lowermost 8-bits from a 16-bit value.

The next value is Msec1, which stands for the timer value that will result in "1 millisecond" interrupts.

Remember, our clock frequency is 12Mhz, and it takes 12 clocks for a single instruction ( as well as a single timer count to occur ), so this means the timer will increment at a rate of 1Mhz, or every microsecond. Since the timer is a 16-bit timer, it can only count up to 65535 ( 0xFFFF in hexadecimal). The next increment (65536) will roll the count over back to zero. So, 1 millisecond worth of timer counts (1000) subtracted from the roll over amount (65536) is 64536.


Finally, we declare our global ticker value, "Ticker"
Sat Nov 14 2009, 05:13 AM
#3
Next, we define a function to initialize our system ticker interrupt...

//=====================================================================
// init routine for ISR handler...                                    
//=====================================================================
void InitISR()
   {
   Ticker      = 0;
   EA          = 0;
   TH1         = High(Msec1);
   TL1         = Low(Msec1);   // load initial values for timer
   TMOD        = (TMOD & 0x0F) | 0X10; // sets timer1 to Mode 1, a 16-bit non-reload
   ET1         = 1;                    // enable timer 1 interrupt
   TR1         = 1;                    // turns on timer 1
   EA          = 1;                    // enable interrupts
   }


We initialize Ticker to zero, disable interrupts, load the hi order register and low order register of timer 1 with our "1 millisecond" value, and set the mode for the timer as a16-bit non-auto-reload timer. Then we enable the timer, turn on the timer, and re-enable the interrupts.



[ Edited Sat Nov 14 2009, 08:26 PM ]
Sat Nov 14 2009, 05:17 AM
#4
Now we need to define the actual interrupt service routine...

//=====================================================================
// Programmable Timer 1 Interrupt Service Routine                      
//=====================================================================
void ProgrammableTimer1_ISR() interrupt 3 using 1
   {
   TH1 = High(Msec1);  // Reset the clock for next interrupt
   TL1 = Low(Msec1);
   Ticker++;                  // bump ticker count...
   }


Since this routine is being executed EVERY millisecond, all it needs to do is reload the timer, and increment the Ticker value...

The routine is identified as"interrupt 3", which is the proper interrupt for timer 1, and is defined as using register set 1. For more information on register sets, you can read the "8052 bible" documents, listed at the end of this thread.


[ Edited Sat Nov 14 2009, 08:27 PM ]
Sat Nov 14 2009, 05:20 AM
#5
We're almost done now...

We need a delay function...

//=====================================================================
// delay routine...                                                    
//=====================================================================
void Delay( unsigned int NumMillisecs )
   {
   unsigned long DelayTickValue;

   DelayTickValue = Ticker + NumMillisecs;
   while( Ticker < DelayTickValue );
   }


All this routine does is take the passed argument (which is how many milliseconds you want to delay), add it to the system ticker value, and then wait for the ticker to increment it's way past the target value. Since the ticker increments every millisecond, all we have to do is wait for it...
Sat Nov 14 2009, 05:26 AM
#6
Finally, we need the main() function. I've written a simple main() that will utilize our initialization function and our delay function, and it will toggle a bit. If this bit happened to be connected to an LED drive circuit, the LED would blink ON and OFF twice per second...

//=====================================================================
// main function to test ISR above...                                  
//=====================================================================
void main()
   {
   InitISR();

   while(1)
      {
      P3_0 = 1;
      Delay(250);   // wait for 250 milliseconds
      P3_0 = 0;
      Delay(250);   // wait for 250 milliseconds
      }
   }


This concludes my cursory example of how to implement a system ticker on a typical 8052...

I hope this helps
Sat Nov 14 2009, 05:37 AM
#7
Here are the links to the "8052 bible":

http://www.nxp.com/acrobat_download/various/80C51_FAM_ARCH_1.pdf
http://www.nxp.com/acrobat_download/various/80C51_FAM_PROG_GUIDE_1.pdf
http://www.nxp.com/acrobat_download/various/80C51_FAM_HARDWARE_1.pdf
Fri Nov 20 2009, 07:17 AM
#8
I added a simple function to wait for the next tick, and consolidated all of the above into one file. Here it is:

//=====================================================================
// simple example software for testing system ticker...                
//=====================================================================
#include "AT89X51.H"

typedef unsigned long ULONG;
typedef unsigned int  WORD;
typedef unsigned char BYTE;

// get high order byte from word
#define High(X) ((BYTE)((X&0xFF00)>
>
8))
 
// get low order byte from word
#define Low(X)  ((BYTE)(X&0x00FF))        

// 1 millisecond
#define Msec1   64536
                         
// counter for T1 interrupt
volatile ULONG Ticker;                  

//=====================================================================
// init routine for ISR handler...                                    
//=====================================================================
void InitISR()
   {
   Ticker      = 0;
   EA          = 0;
   TH1         = High(Msec1);
   TL1         = Low(Msec1);   // load initial values for timer
   TMOD        = (TMOD & 0x0F) | 0X10; // sets timer1 to Mode 1, a 16-bit non-reload
   ET1         = 1;                    // enable timer 1 interrupt
   TR1         = 1;                    // turns on timer 1
   EA          = 1;                    // enable interrupts
   }

//=====================================================================
// Programmable Timer 1 Interrupt Service Routine                      
//=====================================================================
void ProgrammableTimer1_ISR() interrupt 3 using 1
   {
   TH1 = High(Msec1);  // Reset the clock for next interrupt
   TL1 = Low(Msec1);
   Ticker++;                  // bump ticker count...
   }


//=====================================================================
// wait for the ticker to increment...                                 
//=====================================================================
void WaitForTicker()
   {
   volatile ULONG DelayTickValue;

   DelayTickValue = Ticker;
   while( Ticker == DelayTickValue );
   }

//=====================================================================
// delay routine...                                                    
//=====================================================================
void Delay( unsigned int NumMillisecs )
   {
   volatile ULONG DelayTickValue;

   DelayTickValue = Ticker + NumMillisecs;
   while( Ticker < DelayTickValue )
      WaitForTicker();
   }

//=====================================================================
// main function to test ISR above...                                  
//=====================================================================
void main()
   {
   InitISR();

   while(1)
      {
      P3_0 = 1;
      Delay(250);   // wait for 250 milliseconds
      P3_0 = 0;
      Delay(250);   // wait for 250 milliseconds
      }
   }


Here is the output from the logic analyzer in Keil's debugger:



 kennedyugo like this.
Thu Dec 24 2009, 02:56 PM
#9
hello sir... i went thr this thread ...its right as u got the proper output...bt can i ask u ma doubt here???????In isr routine why u hav nt used TF=0? Bcz as per ma knowelged when u dnt clear TF then u block any new interrupt since the pin status indicate that interupt is still being serviced.....we hv RETI instruction in assembly to do d same job...i refered c programs from mazidi also,there also i found that they hvnt cleared timer flag.
Why it is so?? i m nt getting it....
Thu Dec 24 2009, 06:38 PM
#10
The TF flag is automatically reset when an interrupt service routine is enabled, and used to respond to the flag. When there is no ISR, the flag must be manually reset.

If you read the sections on interrupt handling in the bible documents, you will discover this fact...

Use this bible: http://www.nxp.com/acrobat_download/various/80C51_FAM_HARDWARE_1.pdf

refer to page 7, and look at the description for the TCON register. Below it, you should read the definition for TF1 and TF0


I hope this helps,


[ Edited Thu Dec 24 2009, 07:53 PM ]

Get Social

Information

Powered by e107 Forum System

Conversation

ExperimenterUK
Thu Mar 14 2019, 08:44 PM
We don't send code,but you can ask for help in the 8051 forum
Thu Mar 14 2019, 11:00 AM
Jui Sanjay Kapare
Hello sir, I want code of interfacing DS18B20 with 8051.plz send the code as early as possible
ExperimenterUK
Mon Jan 07 2019, 03:31 AM
@REVOCATUS please post in the AVR forum
Mon Dec 24 2018, 09:25 AM
REVOCATUS MATEMU
sorry I mean referee boards for player substitution
Mon Dec 24 2018, 09:24 AM
REVOCATUS MATEMU
hi am.looking how to build referee by using Atmega 328 and its codes
Sat Dec 15 2018, 01:45 PM
Arslan ayoub
Hii ,, can I get the simulation of numeric keypad lock on proteus
ExperimenterUK
Mon Dec 03 2018, 05:17 PM
Please post questions in the forum. The chat box is for chat
Mon Dec 03 2018, 06:43 AM
help!me!
help! I don't understand busy flag!
Sun Dec 02 2018, 08:01 PM
ile
hello
Mon Nov 12 2018, 05:58 AM
Pavan_user
i have seen your replica of I2C programming using AT89C51 but i am unable to understand the "ack_bit" variable usage ...looks like it is always 1...can you elaborate how acknowledgment is working....

Downloads

Comments

tutu10
Tue Mar 12 2019, 07:11 AM
Raj243
Fri Mar 08 2019, 02:08 AM
bharatsb
Thu Mar 07 2019, 04:34 PM
Yass7
Thu Mar 07 2019, 03:55 PM
mashabed
Mon Mar 04 2019, 11:08 PM
AccelMotion
Tue Feb 26 2019, 06:06 PM
turbovps
Mon Feb 25 2019, 06:26 AM
the_Doker
Thu Feb 14 2019, 02:21 PM

Online

Guests: 33, Members: 0 ...

most ever online: 182184
(Members: , Guests: 182184) on 06 Aug 2010: 05:37 AM

Members: 38052
Newest member: tutu10
Forum Activity
ExperimenterUK Avatar
Posted By ExperimenterUK
Fri Mar 22 2019, 09:10 PM
Using the external interrupt on pin B0 is the best...
Ansh12 Avatar
Posted By Ansh12
Fri Mar 22 2019, 03:45 PM
I have pic16f877a and MPLABX8 and I want to count ...
ExperimenterUK Avatar
Posted By ExperimenterUK
Wed Mar 13 2019, 02:32 AM
HiI looked at" Atmel AVR042: AVR Design Considera...
tutu10 Avatar
Posted By tutu10
Tue Mar 12 2019, 07:13 AM
Hi...My firmware upgradable code lock seems to be ...
Yass7 Avatar
Posted By Yass7
Sat Mar 09 2019, 12:52 AM
It's exactly that ! it's my teacher who asked me t...
ExperimenterUK Avatar
Posted By ExperimenterUK
Sat Mar 09 2019, 12:27 AM
As I understand it, you want to use a P89LPC952 /...
ExperimenterUK Avatar
Posted By ExperimenterUK
Sat Mar 09 2019, 12:21 AM
After you get the string what do you want to do wi...
bharatsb Avatar
Posted By bharatsb
Thu Mar 07 2019, 04:40 PM
help me to write code for 8051 to receive string ...
Yass7 Avatar
Posted By Yass7
Thu Mar 07 2019, 03:59 PM
Hello everyone,here I made a 3-axis CNC with 3 ste...
ExperimenterUK Avatar
Posted By ExperimenterUK
Sat Jan 26 2019, 07:19 PM
Yes that helps a lot.At first sight I can't see th...