![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
jaethelegend Guest
|
Timer and Internal oscillator |
Posted: Fri Jun 05, 2009 5:58 am |
|
|
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();
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
Posted: Fri Jun 05, 2009 8:27 am |
|
|
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? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Fri Jun 05, 2009 8:38 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
![](templates/subSilver/images/spacer.gif) |
jaethelegend Guest
|
Thank you |
Posted: Fri Jun 05, 2009 5:06 pm |
|
|
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? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sat Jun 06, 2009 4:31 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|