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

Timer and Internal oscillator

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







Timer and Internal oscillator
PostPosted: Fri Jun 05, 2009 5:58 am     Reply with quote

Hi, I tried to make timer using TMR0.

I used 1Mhz internal oscillator
assigned prescaler to WDT( so, it's 1:1 for timer0)

Since writing to TMR0 inhibits increment for 2 instruction cycle(written in data sheet), i set TMR0 = 256-250+2 = 8 every time overflow occured. That means overflow interrupt every

1ms. I used dummy counter to keep up with 1000 overflows.

Below is the code I wrote.

However, the timing is close, but not quite accurate enough. It lags by about 8 seconds per minute.
Is it coding or that internal oscillator is inaccurate?

I would appreciate any comments or tips.
Code:

#include<C:\Documents and Settings\Microsoft\My Documents\PIC\Header\16f886.h>
#include<C:\Documents and Settings\Microsoft\My Documents\PIC\Header\def_16f886.h>
#use delay(clock = 1000000)
#fuses INTRC_IO, DEBUG
#define LCD_PORT PORTA
#define LCD_TRIS TRISA

#include<C:\Documents and Settings\Microsoft\My Documents\PIC\Header\LCD4bit.h>

int8 sec_counter = 0;
int8 min_counter = 0;
int16 dummy_counter = 0;
int8 tenth_digit = 0;
int8 ones_digit = 0;

#int_timer0
timer0_isr(){
   tmr0 = 8;
   
   if(++dummy_counter == 1000){
     
      dummy_counter = 0;
      if(++sec_counter==60){
         sec_counter = 0;
         if(++min_counter == 60){
            min_counter = 0;
             }
           }
     }
}

void bcd_rtn(int8 number){
   tenth_digit = number/10;
   ones_digit = number - 10*tenth_digit;
}


void disp_rtn(void){
bcd_rtn(min_counter);
goto_xy(6,1);
send_char(tenth_digit+0x30);
send_char(ones_digit+0x30);

bcd_rtn(sec_counter);
goto_xy(9,1);
send_char(tenth_digit+0x30);
send_char(ones_digit+0x30);
}
     
     
void main(){
   osccon = 0b01001000; //Clock speed = 1MHz
   osctune = 0x00; //Tuning the HFINTOSC
   
   lcd_init(0b00101000);
   T0CS = 0;
   GIE = 1;
   T0IE = 1;
   
   OPTION_REG = 0b11001000;
   
   //Initialize tmr0
   tmr0 = 8;

   goto_xy(0,0);
   send_char("TMR0 Clock");
   goto_xy(0,1);
   send_char("MM:SS");
   goto_xy(8,1);
   send_char(":");
   send_cmd(CURSOR_OFF_BLINK_OFF);

   while(1){
   disp_rtn();
    }
}
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Fri Jun 05, 2009 8:27 am     Reply with quote

Did you trying playing around with a slightly larger or smaller value (like 7, or 9 or 10) while setting TMR0 and see what happens?
Ttelmah
Guest







PostPosted: Fri Jun 05, 2009 8:38 am     Reply with quote

Do a search here on the forum, for why setting a counter _to_ a value in an ISR, is almost certain to give errors. The prescaler is reset when you write a value, and the time to actually arrive in an ISR, _will_ vary according to what the main code was doing, when the ISR triggered. Then remember that it takes typically about 30 instructions to get to the interrupt handler, when an event occurs.
Also have a look at examples of how to give accurate times, with RTC's running using the default binary dividers (better solution...).

Best Wishes
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Fri Jun 05, 2009 9:03 am     Reply with quote

There is a very good example here for an accurate RTC:

http://www.ccsinfo.com/forum/viewtopic.php?t=26177&highlight=zero+drift
jaethelegend
Guest







Thank you
PostPosted: Fri Jun 05, 2009 5:06 pm     Reply with quote

Does this mean there is 30 instruction cycle delay between the overflow
actually happens and the interrupt service routine starts?

So, technically, i should think of counter as increasing upto 255+30 and
then going to ISR.
does 30 instruction delay different for each PIC family? but stay consistent for a single chip? ie, with different coding, i can assume about 30 cycle
delay?
Ttelmah
Guest







PostPosted: Sat Jun 06, 2009 4:31 am     Reply with quote

It is worse than that.
The delay is longer on PIC18 chips. It also varies according to what instruction the PIC was in, when the interrupt occurs. Interrupts are only serviced in the first cycle of an instruction. Instructions that take eight cycles (jumps, tests etc.), will slightly increase the delay. Also, some instructions themselves disable interrupts for their execution. Then the compiler, to avoid the re-entrancy limitations of the chip, will also disable interrupts round some parts of the code. It is basically impossible to guarantee just how long it'll actually take to get into the interrupt handler.
Look at the link posted by mkuang, and the posts by Neutone before this, which show how to give accurate times, without adjusting the timer.
Aternatives are to use a timer that supports hardware resetting of the count (timer2).

Best Wishes
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