![]() |
||
![]()
MISC
SKILLS
HARDWARE
SCIENCE |
Timers for Microcontrollers
To introduce delays in an application, the CCSC macro delay_ms() and delay_us() can be used. These macros provide an ability to block the MCU until the specified delay has elapsed. But what if you instead want to determine elapsed time for say a PID controller, or a data logger? For tasks that require the ability to measure time, it is possible to write code that uses the microcontroller timers.
The Timer
These timers are essentially counters that increment based on the clock cycle and the timer prescaler. An application can monitor these counters to determine how much time has elapsed. On the PIC16F877, Timer0 and Timer2 are 8-bit counters whereas Timer1 is a 16-bit counter. Individual timer counters can be set to an arbitrary value using the CCSC macro set_timer0, set_timer1, or set_timer2. When the counter reaches its limit (255 for 8-bit and 65535 for 16-bit counters), it overflows and wraps around to 0. Interrupts can be generated when wrap around occurs, allowing you to count these resets or initiate a timed event. Timer1 is normally used for PWM or capture and compare functions. Each timer can be configured with a different source (internal or external) and a prescaler. The prescaler determines the timer granularity (resolution). A timer with a prescaler of 1 increments its counter every 4 clock cycles - 1,000,000 times a second if using a 4 MHz clock. A timer with a prescaler of 8 increments its counter every 32 clock cycles. It is recommended to use the highest prescaler possible with your application.
Calculating Time Passed
for example . . . Assume that Timer1 is set up with a prescaler of 8 on a MCU clocked at 20 MHz. Assume that a total of 6250 clicks were counted. then . . .
delay (in ms) = (6250) / 625 = 10 ms
Code in C
setup_timer_0(T0_INTERNAL | T0_DIV_BY_8); //Set Timer0 prescaler to 8 now put this code in your main loop:
printf("I eat bugs for breakfast."); //do something that takes time
//calculate elapsed time in ms, use it for something like PID
//or print out data and put a time stamp on it for data logging
Note that it is very important that you do not call the get_timer0() command until exactly when it is needed. In the above example I call the timer in my printf() statement - exactly when I need it.
Timer Overflow
In CCSC, interrupt service routines are functions that are preceded with #int_xxx. For instance, a Timer1 interrupt service routine would be declared as follows:
//timer1 has overflowed
To enable interrupts, the global interrupt bit must be set and then the specific interrupt bits must be set. For instance, to enable Timer0 interrupts, one would program the following lines right after the timer is initialized:
If you want to stop the application from processing interrupts, you can disable the interrupts using the disable_interrupts(INT_TIMER0) CCSC macro. You can either disable a specific interrupt or all interrupts using the GLOBAL define.
Timer Delay
set_timer0(0); //reset timer
|
|
Has this site helped you with your robot? Give us credit -
link back, and help others in the forums! Society of Robots copyright 2005-2014 |