View previous topic :: View next topic |
Author |
Message |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
need help-timer0 interrupt does not run for second time |
Posted: Wed Aug 05, 2009 6:36 am |
|
|
Hello guys I'm writing a timer for my fan using 12F675. In this code initially I disable timer0 interrupt then at some point I enable it and execute a code part and then disable it again. Then I enable timer0 interrupt for the second time at another point. But problem is after enabling it for second time timer0 interrupt does not happen. Timer0_isr code does not run after this second time of enabling it.
I'm posting my total code here. Its pretty rough code I'm still try to fix basic stuff. I have added comments in places where timer0 interrupt enable and disable.
Can someone point me the error?
Code: |
#include "C:\Documents and Settings\Aruna\My Documents\fan project\adding timer\main.h"
int speed=0;
int count=0;
int k=0;
int timer0_on=0;
int timer_mode=0;
int16 timer0_count=0;
int timer_set=0;
int time_min=0;
int timer_det_mode = 0;
int timer_set_mode = 0;
int second=0;
int minute=0;
int quater_mili=0;
int x=0;
void set_timer();
void finalize_timer();
VOID chk_ir ()
{
IF ( ! input (PIN_A3) &&k == 0)
{
count++;
delay_ms (1000);
k = 1;
IF (speed != 5 &&count <= 5)
{
output_low (PIN_A1);
output_high (PIN_A5);
delay_ms (100);
output_low (PIN_A5);
speed++;
}
else IF (count == 6)
{
speed = 0;
timer_det_mode = 1;
enable_interrupts (INT_TIMER0); //eneabling for first time;
timer0_on = 1;
output_high (PIN_A1);
//delay_ms (50);
//output_low (PIN_A5);
//output_high (PIN_A4);
//delay_us (100);
//output_low (PIN_A4);
//speed = 0;
//speed++;
}
else IF (count >= 7)
{
count = 0;
IF (timer_mode == 0)
{
output_low (PIN_A1);
disable_interrupts (INT_TIMER0);
output_high (PIN_A4);
delay_us (100);
output_low (PIN_A4);
speed = 0;
}
//output_high (PIN_A5);
//delay_ms (50);
//output_low (PIN_A5);
}
k = 0;
}
}
#INT_EXT
void EXT_isr(VOID)
{
chk_ir ();
IF (speed == 0)
{
output_low (PIN_A0);
}
else IF (speed == 1)
{
delay_ms (8);
output_high (PIN_A0);
delay_us (100);
output_low (PIN_A0);
}
else IF (speed == 2)
{
delay_ms (6);
output_high (PIN_A0);
delay_us (100);
output_low (PIN_A0);
}
else IF (speed == 3)
{
delay_ms (4);
output_high (PIN_A0);
delay_us (10);
output_low (PIN_A0);
}
else IF (speed == 4)
{
delay_ms (2);
output_high (PIN_A0);
delay_us (10);
output_low (PIN_A0);
}
else IF (speed == 5)
{
delay_us (1500);
output_high (PIN_A0);
delay_us (10);
output_low (PIN_A0);
//delay_ms (500);
}
}
#INT_TIMER1
void TIMER1_isr(VOID)
{
quater_mili++;
IF (quater_mili == 4)
{
quater_mili = 0;
second++;
IF (second == 60)
{
second = 0;
minute++;
IF (minute == time_min)
{
output_low (PIN_A0);
minute = 0;
time_min = 0;
disable_interrupts (INT_TIMER1);
}
}
}
}
#INT_TIMER0
void TIMER0_isr(VOID)
{
IF (timer_det_mode == 1)
{
IF (timer0_count < 5000)
{
timer0_count++;
}
else IF (timer0_count >= 5000)
{
//timer mode on
timer_mode = 1;
disable_interrupts (INT_TIMER0);
timer0_count = 0;
set_timer ();
}
}
IF (timer_set_mode == 1)
{
output_low (PIN_A1);
//delay_ms (50);
IF (timer0_count < 3000)
{
timer0_count++;
}
else IF (timer0_count >= 3000)
{
disable_interrupts (INT_TIMER0);
timer0_count = 0;
finalize_timer () ;
//set_timer ();
}
}
}
void finalize_timer() // this code does not run
{
output_high (PIN_A5);
delay_ms (50);
output_low (PIN_A5);
delay_ms (50);
output_high (PIN_A5);
delay_ms (50);
output_low (PIN_A5);
delay_ms (50);
output_high (PIN_A5);
delay_ms (50);
output_low (PIN_A5);
output_high (PIN_A4);
delay_us (100);
output_low (PIN_A4);
//timer mode on
timer_mode = 0;
timer_set = 1;
timer_set_mode = 0;
enable_interrupts (INT_TIMER1);
}
void set_timer() // this code runs
{
disable_interrupts (INT_EXT);
timer_det_mode = 0;
output_high (PIN_A5);
delay_ms (50);
output_low (PIN_A5);
delay_ms (50);
output_high (PIN_A5);
delay_ms (50);
output_low (PIN_A5);
output_high (PIN_A4);
delay_us (100);
output_low (PIN_A4);
timer0_count=0;
timer_set_mode = 1;
x=1;
enable_interrupts (INT_TIMER0);// eneabling for second time
time_min = 0;
WHILE ( ! timer_set)
{
output_high (PIN_A1);
IF (! input (PIN_A3))//time_min should be<270----- need to add
{
delay_ms (500);
output_low (PIN_A1);
timer0_count = 0;
time_min = time_min + 30;
output_high (PIN_A5);
delay_ms (100);
output_low (PIN_A5);
}
}
}
void main()
{
setup_adc_ports (NO_ANALOGS|VSS_VDD);
setup_adc (ADC_OFF);
setup_timer_0 (RTCC_INTERNAL|RTCC_DIV_4);
setup_timer_1 (T1_INTERNAL|T1_DIV_BY_4);
setup_comparator (NC_NC);
setup_vref (FALSE);
output_low (PIN_A5);
output_high (PIN_A4);
delay_ms (10);
output_low (PIN_A4);
delay_ms (1000);
enable_interrupts (INT_EXT);
disable_interrupts (INT_TIMER1);
disable_interrupts (INT_TIMER0);
enable_interrupts (GLOBAL);
// TODO: USER CODE!!
WHILE (1)
{
chk_ir ();
}
}
|
|
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Aug 05, 2009 7:04 am |
|
|
Your problem most likely is to do with the fact that
set_timer is called from within your interrupt, during set_timer you have a loop which relies on a variable being changed outside the loop (from within another/same interrupt)
Code: |
WHILE ( ! timer_set)
{
output_high (PIN_A1);
IF (! input (PIN_A3))//time_min should be<270----- need to add
{
delay_ms (500);
output_low (PIN_A1);
timer0_count = 0;
time_min = time_min + 30;
output_high (PIN_A5);
delay_ms (100);
output_low (PIN_A5);
}
}
|
timer_set will always be false as the code that sets it can't run because you are curently inside an interrupt routine, only 1 int at a time.
That is appart from the fact the the routine which changes that variable is the same interrupt routine which you are curently in!
This is a bit of a mess and needs a lot of work. |
|
|
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Wed Aug 05, 2009 7:40 am |
|
|
ok I got it. Anyway can you suggest an alternative method?
thanks |
|
|
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Wed Aug 05, 2009 7:45 am |
|
|
Wayne_ wrote: | Your problem most likely is to do with the fact that
set_timer is called from within your interrupt, |
Code: | WHILE ( ! timer_set)
{
output_high (PIN_A1);
IF (! input (PIN_A3))//time_min should be<270----- need to add
{
delay_ms (500);
output_low (PIN_A1);
timer0_count = 0;
time_min = time_min + 30;
output_high (PIN_A5);
delay_ms (100);
output_low (PIN_A5);
} |
this part is running.i add a led to see whether its running. how ever shouldent timer0 interrupt navigate execution from above code part to timer0_isr? (if interrupts are occuring) it seems there are no interrupts are generating
Last edited by aruna1 on Wed Aug 05, 2009 7:48 am; edited 1 time in total |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Aug 05, 2009 7:47 am |
|
|
Your main loop isn't doing much!
You can probably put the
Code: |
WHILE ( ! timer_set)
{
output_high (PIN_A1);
IF (! input (PIN_A3))//time_min should be<270----- need to add
{
delay_ms (500);
output_low (PIN_A1);
timer0_count = 0;
time_min = time_min + 30;
output_high (PIN_A5);
delay_ms (100);
output_low (PIN_A5);
}
}
|
in there
Code: |
while (1)
{
chk_ir ();
if( ! timer_set)
{
output_high (PIN_A1);
IF (! input (PIN_A3))//time_min should be<270----- need to add
{
delay_ms (500);
output_low (PIN_A1);
timer0_count = 0;
time_min = time_min + 30;
output_high (PIN_A5);
delay_ms (100);
output_low (PIN_A5);
}
}
}
|
you may have to remove the delays, depends on how often you need to run chk_ir.
A counter flag depending on how acurate the delays need to be.
Also not sure what you are toggling A5, A1, A4 etc. Is it infared ? |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Aug 05, 2009 7:48 am |
|
|
Quote: | set_timer is not called inside a interrupt routine. |
Code: |
#INT_TIMER0
void TIMER0_isr(VOID)
{
IF (timer_det_mode == 1)
{
IF (timer0_count < 5000)
{
timer0_count++;
}
else IF (timer0_count >= 5000)
{
//timer mode on
timer_mode = 1;
disable_interrupts (INT_TIMER0);
timer0_count = 0;
set_timer (); <-----------------What is this then ?
}
}
IF (timer_set_mode == 1)
{
output_low (PIN_A1);
//delay_ms (50);
IF (timer0_count < 3000)
{
timer0_count++;
}
else IF (timer0_count >= 3000)
{
disable_interrupts (INT_TIMER0);
timer0_count = 0;
finalize_timer () ; <---------------------AND this is where your timer_set flag gets set
//set_timer ();
}
}
} |
|
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Aug 05, 2009 7:54 am |
|
|
You edited your post and removed that comment!
Anyway, imagine this
Code: |
-->Timer0 Interrupts
|---->Call Set_timer
|--------Enters loop and waits for timer_set flag
(Loop never exits because we are already processing an interrupt, another interrupt cannot trigger ESPECIALLY the same one we are curently processing, which is required to set the timer_set flag)
|
|
|
|
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Wed Aug 05, 2009 7:59 am |
|
|
Wayne_ wrote: | You edited your post and removed that comment!
|
Ya I was having trouble understanding your first post. I have understand it incorrectly. As soon as I figred it I removed the comment
It seems working now. Thank you very much for helping |
|
|
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Wed Aug 05, 2009 8:00 am |
|
|
Wayne_ wrote: | Your main loop isn't doing much!
you may have to remove the delays, depends on how often you need to run chk_ir.
A counter flag depending on how acurate the delays need to be.
Also not sure what you are toggling A5, A1, A4 etc. Is it infared ? |
delays are for debouncing A5,A4 are for 7-segment drive.A1 for a led |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Aug 05, 2009 8:02 am |
|
|
Glad to be of help. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Aug 05, 2009 9:03 am |
|
|
one other item I see in your ISR's which are regularly frowned on in the world of programming:
Don't use delay's inside ISR's. (delay_ms, delay_us)... especially long ones.
Debounce switches OUTSIDE the ISR.
Set a flag inside the ISR that is monitored OUTside the ISR and then run when the flag is set.
Cheers,
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
|