|
|
View previous topic :: View next topic |
Author |
Message |
Ringo42
Joined: 07 May 2004 Posts: 263
|
timer0 overflow |
Posted: Wed May 14, 2008 8:23 pm |
|
|
I use timer0 to see when an event times out. It is setup so 1 tick is .4us.
right now I time out at 25ms which is 62,500 ticks, so it is within 16bits. What I would like to do is count to 100,000 ticks. I don't want to change the timer setting. What is the best way to do this? Is there an easy way to tell when timer0 overflows, or do I just keep checking to see if the next number is lower than the previous one??
Here is my current code.
Thanks
Ringo
Code: |
set_timer0(0); // timer0 is .4us per timer tick
while(input(ccs_echo)==1)
{
RawData = get_timer0();
//timeout after 25ms
if(RawData > 62500) // .4*62500=25ms
return(0);
}
|
_________________ Ringo Davis |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: timer0 overflow |
Posted: Wed May 14, 2008 8:33 pm |
|
|
Although it is not the most efficient, if you have nothing else to do, polling the timer and checking to see if it is higher or lower than the previous value is nice and simple. Make sure you declare the values to be unsigned int16. But if you want a method that does not require storing the previous timer reading, then use the timer interrupt flag that gets sets when the timer overflows to 0. By the way, timer0 is only 8 bits on midrange PICs. Which PIC are you using?
Robert Scott
Real-Time Specialties |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed May 14, 2008 8:36 pm |
|
|
Thanks, I'm using an 18f452, so it is 16 bits.
How do I read the timer interrupt flag?
Ringo _________________ Ringo Davis |
|
|
Ttelmah Guest
|
|
Posted: Thu May 15, 2008 2:50 am |
|
|
For your application, given the count will be under 131072 (where the timer would wrap a second time), the timer flag is the best solution. effectively it means you have a 17bit counter available:
Code: |
#byte PIR1=0xF9E
#bit TMR1IF=PIR1.0
#byte T1CON=0xFCD
#bite TMR1ON=T1CON.0
int 32 RawData;
set_timer0(0); // timer0 is .4us per timer tick
TMR1IF=0; //clear the flag - must be after setting the count=0
TMR1ON=TRUE; //enable the timer
while(input(ccs_echo)==1)
{
TMR1ON=FALSE; //stop the timer
RawData = get_timer0();
//Now add in the 17th bit
if (TMR1IF) bit_set(RawData,16);
if(RawData > 100000) // .4*62500=25ms
return(0);
}
|
Now, this shows two things. First, I stop the timer before read it. This prevents the possibility of the first read getting (say) FFFF, and then when the flag is accessed, it'll just have wrapped, to give 1FFFF when the interrupt flag is added, rather than the correct 10000. All I have done, is make your 'RawData' value into a 32bit value, read in the count from the timer, and then if the flag is set, set the extra bit.
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu May 15, 2008 5:35 am |
|
|
I spotted two problems in Ttelmah's code:
1) The timer is stopped in the loop but never enabled again.
2) Stopping/starting the timer in such a tight loop slows down the timer considerably.
I tried to modify the code to solve the mentioned problems but I'm not really happy with it: Code: | #byte PIR1=0xF9E
#bit TMR1IF=PIR1.0
#byte T1CON=0xFCD
#bit TMR1ON=T1CON.0
int32 RawData;
set_timer0(0); // timer0 is .4us per timer tick
TMR1IF=0; // clear the flag - must be after setting the count=0
TMR1ON=TRUE; // enable the timer
while(input(ccs_echo)==1)
{
if (TMR1IF) // timer overflowed?
{
TMR1IF = 0; // reset overflow flag
RawData += 0x10000; // increment counter
}
if ((RawData + get_timer0()) > 100000) // .4*100,000=40ms
return(0);
} | Note that I do not disable the timer between testing TMRIF and the get_timer_0, this introduces a risk of executing the loop 1 time too many. I'm not sure how bad this is for the application but I considered it better than slowing down the timer0.
An advantage of the chosen approach is that the timing now allows very large delays, up to 2^32 ticks.
Another approach that makes me feel more comfortable is to forget about the 0.4us resolution. Why not double the timer0 prescaler and set the resolution to 0.8us? Than for counting to 50000 the 16-bit timer0 counter will fit. |
|
|
|
|
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
|