I am currently trying the following example
#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#INT_TIMER1
void TimerOverflow()
{
printf("Timer Overflowed\r\n");
}
void main()
{
long time;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER1);
set_timer1(8000); //count till 8000 then overflow
time = get_timer1();
while(1)
{
}
}
However the interrupt function is supposed to be called after ever (almost) 8 seconds but its being called as if the delay was 0 seconds. What am i doing wrong here?
-
\$\begingroup\$ Try to force the interrupt flag to be cleared. After banging my head several times on the wall I have learned that I cannot trust 100% on compilers :-) \$\endgroup\$Bruno Ferreira– Bruno Ferreira2012年09月03日 14:30:15 +00:00Commented Sep 3, 2012 at 14:30
-
\$\begingroup\$ I added some detail to my answer, how you get your actual 8 seconds delay. Hope it helps. \$\endgroup\$PetPaulsen– PetPaulsen2012年09月03日 14:58:13 +00:00Commented Sep 3, 2012 at 14:58
1 Answer 1
I think you missunderstood the timer-funtions. According to your comment you are assuming, that set_timer1
will set the value the timer counts to. But what realy happens is, that you set timer1 to the value 8000. The timer interrupt is triggered everytime the timer overflows.
Because timer1 is a 16 bit timer this happens when the counter reaches 65535.
So the first time the timer counts from 8000 to 65535, triggers the interrupt, resets the counter to 0 and counts again to 65535, triggers the interupt, and so on.
Let \$f\$ be the clock frequency, then is the time interval \$T\$ your interrupt is triggered: $$ T = \frac{4\cdot2^{16}}{f} $$ So for a 1Mhz clock frequency your interrupt is triggered every 262ms, for a 20Mhz it is triggered every 13ms.
What you need to do to get a bigger delay is to increase a software-counter in your interrupt routine. But with your 20Mhz clock you are getting these odd 13ms.
What you need to get a nice number like 10ms is to count to 50000 (rearrange the formula from above). So what you can do is initialize the timer not to 0 but to \2ドル^{16} - 50000 = 15536\$ (this time with the set_timer1
-function).
The last thing is to increase the mentioned software-counter everytime your interrupt triggers. When your variable hold a value of 8000 you know, that 8s elapsed.
You should read the datasheet for the pic, especially chapter 6 'Timer1 Module', to get a better understanding what is happening and how to use your pic microcontroller.
-
\$\begingroup\$ This is by far the best post I have read that's short and laconic. Thank you this definitely helped \$\endgroup\$MistyD– MistyD2012年09月03日 15:08:05 +00:00Commented Sep 3, 2012 at 15:08
-
\$\begingroup\$ By the way you stated "So for a 1Mhz clock frequency your interrupt is triggered every 265ms" I assume ms here is milliseconds right ? \$\endgroup\$MistyD– MistyD2012年09月03日 15:10:48 +00:00Commented Sep 3, 2012 at 15:10
-
\$\begingroup\$ @MistyD - Yes ms is milliseconds. I'm glad I could help. \$\endgroup\$PetPaulsen– PetPaulsen2012年09月03日 15:13:54 +00:00Commented Sep 3, 2012 at 15:13
-
\$\begingroup\$ You stated "So for a 1Mhz clock frequency your interrupt is triggered every 265ms" I guess you meant 262.144 Milliseconds right ? Since $${\frac{4\times 2^{16}}{1}=262,144}~Microseconds $$ so $$\frac{262144}{1000}=262.144~Milliseconds$$ Am I correct ? \$\endgroup\$MistyD– MistyD2012年09月03日 15:20:35 +00:00Commented Sep 3, 2012 at 15:20
-
\$\begingroup\$ @MistyD - Whoops, your right. I corrected it in the answer. \$\endgroup\$PetPaulsen– PetPaulsen2012年09月03日 15:26:27 +00:00Commented Sep 3, 2012 at 15:26