|
|
View previous topic :: View next topic |
Author |
Message |
powerpurzel Guest
|
detect a timer overflow during ISR execution |
Posted: Fri Jul 23, 2004 1:43 pm |
|
|
Hi!
I have the following problem:
My InterruptServiceRoutine for timer0 overflows is not quite short...
So it happens, that the timer1-overflow-ISR cannot be executed.
But in this case, the timer0-ISR has to know, THAT THERE WAS a timer1 overflow!
How can I check this in the timer0-ISR???
Is there a flag I can simply read to see, if there was an overflow?
Thanx in advance!
[PIC16F628 @ 20Mhz] |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Jul 23, 2004 2:20 pm |
|
|
You should keep you ISR's short as possible. If possible, set a flag and handle in the main loop.
To answer your question, you can look at the PIR1 register and the TMR1IF flag bit. |
|
|
Guest
|
|
Posted: Fri Jul 23, 2004 4:39 pm |
|
|
Thanks.
okay, I tried to keep the ISR short, but in this case it is not possible to put the code into main().
The execution of the code in the ISR is time-critical and has to be a direct reaction on the timer0 overflow.
In main() it would not be possible to react on the incoming event directly, since heavy floating point math is done there, so hundreds of instructions could pass, before the flag (which was set in the ISR before) can be read.
this is the routine:
(counter, c2, timerval are int32, numimps is byte)
Code: |
#bit Timer1IF = 0xC.0
#int_RTCC
RTCC_isr()
{
timerval = get_timer1();
if(Timer1IF)timerval+=65536; //NEW: check the overflow flag
counter*=65536;
counter+=timerval;
if(counter>15000)
{
if(numimps!=0)
c2+=counter;
numimps++;
}
counter =0;
set_timer1(0);
set_timer0(255); //cause an interrupt on next signal-change
}
#int_TIMER1
TIMER1_isr()
{
counter++;
}
|
as you can see, i added the TMR1IF flag test to compensate missed timer overflows.
Could that work this way? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Jul 23, 2004 5:37 pm |
|
|
After checking the Timer1 overflow flag you need to reset it too.
Code: | if(Timer1IF)
{
timerval+=65536; //NEW: check the overflow flag
clear_interrupt( INT_TIMER1 );
} |
Also consider to change your code and getting rid of the 32-bit couters, they require a lot of code, for example:
This is a 32 bit x 32 bit multiplication and requires a lot of code space! Much more efficient is:
Or even better, split your counters in two 16 bit parts, counter_high and counter_low. |
|
|
powerpurzel
Joined: 23 Jul 2004 Posts: 6 Location: Germany
|
|
Posted: Fri Jul 23, 2004 6:49 pm |
|
|
okay, I'll try the thing with clearing the flag after processing it tomorrow.
btw:
counter*=65536 and counter<<=16 produce exactly the same code, so I kept this for better readability ('cause I normally need some time to realize what happens when i do bitshifting )
and:
yes, the 32-bit-counters need much code space but the pic still has some space left, so there was no need for changing that. The 32-bit counter values are later conversed into floats and I was too lazy to code the extra math funcs myself...
thanks for your help so far... |
|
|
Ttelmah Guest
|
|
Posted: Sat Jul 24, 2004 8:42 am |
|
|
powerpurzel wrote: | okay, I'll try the thing with clearing the flag after processing it tomorrow.
btw:
counter*=65536 and counter<<=16 produce exactly the same code, so I kept this for better readability ('cause I normally need some time to realize what happens when i do bitshifting )
and:
yes, the 32-bit-counters need much code space but the pic still has some space left, so there was no need for changing that. The 32-bit counter values are later conversed into floats and I was too lazy to code the extra math funcs myself...
thanks for your help so far... |
I'd suggest doing some of your operations with a union. If you have something like:
union time {
int16 word[2];
int32 full;
} counter;
You can then have the timer1 interrupt, just increment counter.word[1].
Accessing a variable in an array using a fixed subscript, is as fast as directly accessing a normal variable.
In the RTCC, you then code as you show, except the timer value is directly transferred into word[0], and no multiplications or additions are needed.
So:
Code: |
counter.word[0]=get_timer1();
if (Timer1IF) {
counter.word[1]++;
Timer1IF=0;
}
|
The only problems, are if timer1, can wrap, between the 'get', and checking the interrupt flag, or if it can increment when being read (remember that the processor only transfers a byte at a time, for the 16bit transfer...).
The comparison, is then done on counter.full.
This saves a lot of time.
Best Wishes |
|
|
|
|
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
|