| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| djsb 
 
 
 Joined: 29 Jan 2011
 Posts: 51
 
 
 
			    
 
 | 
			
				| set_timer0 confusion |  
				|  Posted: Sat Oct 24, 2015 11:14 am |   |  
				| 
 |  
				| 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
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Sat Oct 24, 2015 11:17 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Oct 24, 2015 2:06 pm |   |  
				| 
 |  
				| 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:
 Reading the timer value to adjust your offset value will correct for any latency value, even when the latency is variable. 	  | 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);
 }
 | 
 
 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: 9588
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Oct 24, 2015 3:56 pm |   |  
				| 
 |  
				| 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
 |  | 
	
		|  | 
	
		|  |