View previous topic :: View next topic |
Author |
Message |
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
interrupts |
Posted: Mon Jan 02, 2012 12:06 pm |
|
|
here is the code:
Code: |
#include <16F873A.h>
#use delay(crystal=4M)
#fuses NOWDT,NOPROTECT,NOLVP
#int_rb
void button_isr()
{
output_high(pin_a0);
delay_ms(300);
output_low(pin_a0);
delay_ms(300);
}
void main ()
{
enable_interrupts(global);
enable_interrupts(int_rb);
while (1)
{
output_high(pin_a1);
delay_ms(300);
output_low(pin_a1);
delay_ms(300);
}
}
|
Why this loop
Code: |
#int_rb
void button_isr()
{
output_high(pin_a0);
delay_ms(300);
output_low(pin_a0);
delay_ms(300);
}
|
is repeating forever after interrupt occur?
And main function never execute again? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
the same lack of understanding again and again |
Posted: Mon Jan 02, 2012 1:40 pm |
|
|
i urge you to THINK about the BIG picture for your program.
what is happening when you execute TWO of these in your ISR??
delay_ms(300);
hit me with your best guess as to what havoc this can cause |
|
|
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
re interrupts |
Posted: Mon Jan 02, 2012 9:05 pm |
|
|
Men, I think I found solution for my problem.
Code: |
#int_rb
void button_isr()
{
if(input(pin_b4))
{
output_high(pin_a0);
delay_ms(300);
output_low(pin_a0);
delay_ms(300);
}
else ;
}
|
Now ISR loop is executed once.
THX! |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Mon Jan 02, 2012 9:45 pm |
|
|
Well it might be working for you but even a broken clock has the right time at least once per day. It is generally very bad practice to put delay_xx
in any isr. The delays are blocking and thus destroy much of the purpose of an isr. Sure it might work with delays but if you use this approach you will probably much regret it later,especially if you move on to more complex coding. |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Mon Jan 02, 2012 9:49 pm |
|
|
It is generally a poor idea to use ANY delay in an interrupt, especially a long delay.
Instead the interrupt should set a flag bit and exit quickly. The main loop will test this flag bit at its convenience, do the work required, clear the flag bit, and continue with its original work.
In your case the 300ms delay at the END of the ISR seems particularly pointless. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
#int_rb |
Posted: Thu Jan 05, 2012 6:41 am |
|
|
I can see how and why you took time to get there. The CCS compiler usually clears the flag which caused an interrupt. #int_rb is one the exceptions. I spent a while figuring that one out, it's not well documented in the CCS manual. You have to go to the PIC data sheet for song and verse.
Regarding your original problem, the 300ms delay was a red herring. I do however endorse other's comments that it's very bad news to include it inside a interrupt routine. As suggested set a flag, then main() turns the ports on and off. Get your timing(s) by using one of the built-in timers to generate say 1ms ticks. You can have a universal ms_counter and poll that. I create a separate ms_delay_xx counter for each required delay. Main() sets each ms_delay_xx to the required interval, a 1ms interrupt routine decrements all the ms_delay_xx's, then main() polls each one and takes action when they reach zero or go negative. I can have lots of delays going on at the same time, all independant of one another.
CCS (and others) don't set a good example. They insist on using some form of software delay routine in their sample programmes. CCS even uses a delay_ms(xx) in an interrupt routine, though (to be fair) they do point out that it's not reccomended.
Mike |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9255 Location: Greensville,Ontario
|
|
Posted: Thu Jan 05, 2012 6:53 am |
|
|
You have to remember that software delays( delay_ms(xxx) ) 'twiddle your thumbs' loops are UNIVERSAL and are NOT dependent on 'special 'processor resources ( timers,etc.). As such they get the job done ( time wasters), rude and crude.
I've got products in the field with 20 year old 16C84s in them with inline delays running 24/7 since 85. No reason to 'upgrade' the code to ISR based timers! |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Timers |
Posted: Thu Jan 05, 2012 9:17 am |
|
|
Quote: |
I've got products in the field with 20 year old 16C84s in them with inline delays running 24/7 since 85. No reason to 'upgrade' the code to ISR based timers!
|
OK, if you don't need ISR based timers then yes use an inline version. For all but the simplest situations, it's difficult to justify including a long delay inside an interrupt routine.
Depends on what you're doing, how accurate timings have to be, how fast a response is required, how many simultaneous inputs you may get, etc. A case of horses for courses surely. Also what you're comfortable with. |
|
|
n-squared
Joined: 03 Oct 2006 Posts: 99
|
|
Posted: Thu Jan 05, 2012 12:56 pm |
|
|
Hi
The reason the ISR repeats forever is that you did not include an input_b() in the ISR to clear the interrupt flag.
BR
NN _________________ Every solution has a problem. |
|
|
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
re ISR |
Posted: Sun Jan 15, 2012 10:25 am |
|
|
Thanks guys! Next time I will avoid to use delay_xs. I will attempt with some of the embedded timers (timer_0(), timer_1()) instead. |
|
|
|