CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

set_timer0 confusion

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
djsb



Joined: 29 Jan 2011
Posts: 41

View user's profile Send private message

set_timer0 confusion
PostPosted: Sat Oct 24, 2015 11:14 am     Reply with quote

Hi,
I'm just trying to understand how the set_timer0 statement works in the code below

Code:

//Program to produce a 20 ms pulse state change by interrupt

#include <16F819.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,MCLR,NOBROWNOUT
#use delay(clock=4M)               //Set clock speed

#INT_TIMER0                //Timer1 Interrupt Label
void TIMER0_ISR(){         //Interrupt Service Request handling function
output_toggle(PIN_B1);     //Toggle Pin B1
set_timer0(100);            //Rollover every 20 mS (256-156 = 100)
}                          //Might have to adjust this value using a scope
                           //to compensate for command execution time
                           // 2 added to count (156) (please refer to page 178 (Design Tips)
                           // of http://ww1.microchip.com/downloads/en/DeviceDoc/33023a.pdf

void main(){
setup_timer_0(T0_INTERNAL|T0_DIV_128);   //Setup timer 0 with a 1/128 pre-scaler
enable_interrupts(INT_TIMER0);         //Enable Timer interrupt
enable_interrupts(GLOBAL);             //Enable selected interrupts

 while(1){            //Loop forever
                     //and do nothing
   }                 //processor is free...
}

// Results with above settings are
// Period: 40.046mS
// Pulse width; 20.023mS
// Freq: 24.971 Hz


As mentioned in the comment above I get a square wave output with a frequency of 24.97 Hz.

This is how I worked out

Timer rollover with 256 loaded = 32.768 mS
Each timer tick = 128uS
The required timing period is 20mS
So,

20E-3/128E-6 =156.25 (nearest integer value 156)

So I have worked on the assumption that the value of 156 is subtracted from 256 to give a value of 100. This value of 100 is pre-loaded into the TMR0 register using SET_TIMER0(100);

156 X 128E-6 = 0.019968 so that seems to make sense.

The results on my Oscilloscope verify this. However I do not understand one very simple thing. Why is it that I have to subtract the value I have worked out (156) from 256 to get the 100 that I must put into the above SET_TIMER0() statement. This seems counter intuitive. I do not understand how the figure of 100 relates to the actual timer count.
Could someone please explain this to me? Thanks.

PS Also what is the best and most accurate way of measuring any latency so that I can fine tune the code?
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Sat Oct 24, 2015 11:17 am     Reply with quote

why ?
because the timer counts UP to the overflow point and rollover.

it does NOT subtract from the value you calc'd as the 'register count.

latency from WHAT execution point??
You can easily toggle a pin inside the INT and see how much jitter you get when triggering on Fosc, using delayed sweep to hit the edge of the square wave produced against the master ( Fosc) clock reference ...
only if
Quote:

using an external clock.. like crystal or oscillator unit
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sat Oct 24, 2015 2:06 pm     Reply with quote

A short note on the 'latency'.

Whenever the interrupt is triggered it takes some time before your interrupt routine is entered. Most of this time is used by code inserted by the CCS compiler for saving many PIC registers and for determining which interrupt was triggered. The number of registers to be saved, and restored on interrupt exit, depends on the actual chip model you are using. I don't know for the v5 compiler, but in the past it used to be something like 40 instructions for the PIC16 and close to 100 for the PIC18.
This latency varies with compiler version and the actual chip you are using.

When you have multiple interrupts active it becomes a bit more complicated. When another interrupt is active when your timer interrupt triggers, the timer interrupt will have to wait for the first interrupt to finish. There is no way you can determine this delay beforehand.

The best, and actually easiest way to handle this is not doing any calculations yourself but have the PIC sort it out for you:
Code:
#define MS20   (256-156)    // Rollover every 20 mS: 20ms/128us per tick = 156
#define LED     PIN_B1

// Timer0 Interrupt Service Request handling function
// Is triggered every 20ms.
#INT_TIMER0
void TIMER0_ISR() {
  set_timer0(MS20 - get_timer0());            //Rollover every 20 mS
  output_toggle(LED);
}
Reading the timer value to adjust your offset value will correct for any latency value, even when the latency is variable.

Also note how I removed a lot of your comments and added a few defines, now the code is 'self documenting'. This saves you work and prevents the common error where code doesn't match the comments.
temtronic



Joined: 01 Jul 2010
Posts: 9247
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Oct 24, 2015 3:56 pm     Reply with quote

an 'also'....

Whenever using the internal clock be aware that the timing may not be precise or accurate when compared to an external crystal and 2 caps.
Each PIC will be slightly different so you might have to adjust the counter to get exactly 20ms( or whatever time you want).

It's a tradeoff, cheaper to use the internal but you need to tweak the software.

Jay
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group