View previous topic :: View next topic |
Author |
Message |
pe1icq
Joined: 29 Aug 2005 Posts: 12
|
Enable Timer1 interrupt in another ISR? |
Posted: Fri Sep 29, 2006 10:41 am |
|
|
Hi,
Can I setup and enable a Timer1 interrupt in another ISR?
What I'm trying to accomplish is starting Timer1 in the ISR that handles the PortA change interrupts.
I've tried several things but I can't get it to work.
This is what I have:
Code: |
#define INTS_PER_MINUTE 114 // (4000000/(4*8*65536)) * 60
int8 minutes; // A running minutes counter
int8 int_count; // Number of interrupts left before a minute has elapsed
#PRIORITY TIMER1,RA
#INT_TIMER1 // This function is called every time
void clock_isr() // timer 1 overflows (65535->0), which is
{ // approximately 1.9 times per second for
// this program.
output_high(pin_a3); // Green LED
if(--int_count==0) {
++minutes;
int_count = INTS_PER_MINUTE;
}
if (minutes==2) {
output_high(pin_a5);
// delay_ms(1000);
// output_low(pin_a5);
}
}
#INT_RA
void porta_change_isr()
{
delay_us(250);
if (!input(PIN_A4)) {
disable_interrupts(INT_TIMER1);
output_low(pin_a5); // Red LED
}
if (input(PIN_A4)) {
int_count = INTS_PER_MINUTE;
minutes = 0;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
set_timer1(0);
enable_interrupts(INT_TIMER1);
output_high(pin_a5); // Red LED
}
#use fast_io(a)
input_a(); // dummy read
}
|
I can get in an out of the RA ISR. The LED on pin_a5 goes on and off. However Timer1 does not seem to be running, and I never get into the Timer1 ISR (I.e. the debug LED on pin_a3 never goes on)
What am I doing wrong?
BR. //Arno |
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Fri Sep 29, 2006 11:25 am |
|
|
Stupid question, but did you configure timer 1 to run? ie.
Code: | setup_timer_1(T1_INTERNAL|T1_DIV_BY_2); |
|
|
![](templates/subSilver/images/spacer.gif) |
pe1icq
Joined: 29 Aug 2005 Posts: 12
|
|
Posted: Fri Sep 29, 2006 12:28 pm |
|
|
Yes I did. It is in the #INT_RA ISR.
I also tried putting it in main() but that did not make a difference. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 29, 2006 1:20 pm |
|
|
What PIC are you using, and what's your compiler version ? |
|
![](templates/subSilver/images/spacer.gif) |
pe1icq
Joined: 29 Aug 2005 Posts: 12
|
|
Posted: Fri Sep 29, 2006 1:51 pm |
|
|
PIC16F684 and PCM compiler version 3.229 (Linux) |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 29, 2006 2:37 pm |
|
|
Can you post a main() function, with all of your setup code for the
timer, and the port i/o pins, comparators, etc., ?
Please show the #fuses, #use, and applicable #define statements.
In other words, I want to drop the code into MPLAB and have it compile
with no errors. Then I can look at it. |
|
![](templates/subSilver/images/spacer.gif) |
pe1icq
Joined: 29 Aug 2005 Posts: 12
|
|
Posted: Fri Sep 29, 2006 2:39 pm |
|
|
Well... it would help if I would select a port for the debug LED that actually can be used as an output. RA3 isn't one of those.
I swapped RA3 and RA4 and now everything is working fine.
I still have one question. Do I explicitely need to clear the interrupt flags, or does the compiler take care of that for me?
I now have some clear_interrupt() statements in the ISR as shown below. Are those really needed?
Code: |
#INT_RA
void porta_change_isr()
{
delay_ms(200);
if (!input(PIN_A3)) {
disable_interrupts(INT_TIMER1);
output_low(pin_a5); // Red LED
}
if (input(PIN_A3)) {
int_count = INTS_PER_MINUTE;
minutes = 0;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
set_timer1(0);
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
output_high(pin_a5); // Red LED
}
clear_interrupt(INT_RA);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Fri Sep 29, 2006 2:41 pm |
|
|
Clearing the interrupt is absolutely required. The compiler doesn't take care of that for you. If a timer is enabled, it will set its overflow flag when it overflows regardless of whether its interrupt is enabled.
Whoops - have to clarify. If you enable the timer interrupt, you must clear any outstanding timer interrupts. As PCM has said, no need to clear the other one - the compiler does that automatically.
Last edited by newguy on Fri Sep 29, 2006 3:19 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 29, 2006 2:55 pm |
|
|
You don't need to clear the RA interrupt flag at the end of the isr.
The compiler automatically puts in a line of ASM code to do that for you.
See the lines shown in bold below.
Quote: | .................... }
.................... clear_interrupt(INT_RA);
0088: BCF 0B.0.................... }
....................
....................
0089: BCF 0B.0
008A: BCF 0A.3
008B: GOTO 02B |
|
|
![](templates/subSilver/images/spacer.gif) |
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Fri Sep 29, 2006 5:09 pm |
|
|
You can turn on/off a timer from anywhere in your code, including an ISR. Simply set/clear the bit that enables the timer.
Ronald |
|
![](templates/subSilver/images/spacer.gif) |
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Sat Sep 30, 2006 5:12 pm |
|
|
pe1icq wrote: | Do I explicitely need to clear the interrupt flags, or does the compiler take care of that for me?
Code: |
set_timer1(0);
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
|
|
That first line of code will set the counter to zero
the second line will clear the interupt flag that may have already been set by an overflow of timer 1 counter.
The third line will enable interupt if the timer interupt flag is set.
If you dont clear the interupt flag before enabeling the interupt it might jump to the timer 1 interupt routine as soon as it leaves the RA interupt. |
|
![](templates/subSilver/images/spacer.gif) |
|