View previous topic :: View next topic |
Author |
Message |
fariq23
Joined: 29 Nov 2010 Posts: 8
|
INTERRUPTS |
Posted: Thu Dec 09, 2010 8:43 am |
|
|
Situation
1. Pic will continuously toggle LED at PORT RB1, RB2 and RB3, and toggle
buzzer ON and OFF in sequence every 1 sec.
2. When interrupt occur, ALL LED and buzzer will automatically turn
OFF, and only turn ON LED RB4.
3. After 2 sec, all sequence function back as normal.
Buzzer Q1-RD0
Buzzer GND-GND
Code: |
#include <16f877a.h>
#use delay(clock = 20000000)
#fuses hs, noprotect, nowdt, nolvp
#byte PORTB=6
#INT_EXT
void switch_isr(){
}
void main ()
{
set_tris_b(0b00000001);
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
ext_int_edge(H_TO_L);
portb=0b00010000;
output_bit(pin_D0,0);
delay_ms(2000);
loop: output_bit( PIN_B1 ,1);
delay_ms(1000);
output_bit( PIN_B2 ,1);
delay_ms(1000);
output_bit( PIN_B3 ,1);
delay_ms(1000);
output_bit( PIN_D0 ,1);
delay_ms(1000);
output_bit( PIN_D0 ,0);
delay_ms(1000);
Goto loop;
} |
|
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Thu Dec 09, 2010 9:51 am |
|
|
It's homework time again... _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
fariq23
Joined: 29 Nov 2010 Posts: 8
|
It's homework time again... |
Posted: Thu Dec 09, 2010 10:17 am |
|
|
hmm...i had a problem..that why i post in this forum..
i need and idea not a useless comment!!!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Dec 09, 2010 10:32 am |
|
|
Stop and think for a moment.
You want your interrupt to do something. So, why is there nothing in your interrupt handler?.
You need the handler to trigger the new operation you want.
Unfortunately, if you put a delay in your interrupt handler, the response to the button will become terrible (do a search here to find out 'why'.... :-(
Approach things differently:
Have a global 'state' variable.
Have a timer running. Have this incrementing or decrementing a tick variable, at some suitable interval (say 50*/sec).
Then in your main code, have a 'state machine'. The code sits looping _quickly_, without any delays. When the tick counter gets to a particular value, you increment to the next 'state', which changes the lights as required, and sets the new tick count required (so with a 50Hz tick, and wanting 1 second, 50 for example). When the state gets to the last normal state, you reset it, giving you your loop.
Then have your edge detector, change the state variable, to a new value beyond the normal range, and set a new tick. This works just like the main state machine, sequencing through the operations you want as a result of the interrupt, and when these have all finished, _resetting_ the state variable to the start of the main loop.
As a general comment, try to avoid 'goto' loops. While _occasionally_ useful, their operation can be done more safely, using a 'while', and with less likelyhood of getting confused....
Best Wishes |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Thu Dec 09, 2010 10:33 am |
|
|
Let's break this down step by step...
Setup stuff..
Code: | #include <16f877a.h>
#use delay(clock = 20000000)
#fuses hs, noprotect, nowdt, nolvp
#byte PORTB=6 |
Interrupt Service Routine -- what does this do exactly on interrupt?
Nothing. As there is nothing in the ISR.
Code: | #INT_EXT
void switch_isr(){
} |
Code: | void main () {
set_tris_b(0b00000001); // Setup TRIS for port B outputs. ok.
// Consider reversing the order of these.
// set up your stuff first (H_TO_L) and then enable the EXT and
// then GLOBAL maybe (although I don't think ultimately GLOBAL and EXT don't have a crucial order.
enable_interrupts(GLOBAL); // Enable Global IRQ's. Ok.
enable_interrupts(INT_EXT); // Enable EXT interrupt ok.
ext_int_edge(H_TO_L); // Set External INT's trigger edge.
portb=0b00010000; // PortB's default condition.
output_bit(pin_D0,0); // output PIN_D0 low.
delay_ms(2000); // Pause for 2 seconds.
// Ok, goto's in C are generally not recommended and typically
// should be replaced with a while (1) { ... }
// or a for (;;) { }
// to loop forever.
loop: output_bit( PIN_B1 ,1);
delay_ms(1000);
output_bit( PIN_B2 ,1);
delay_ms(1000);
output_bit( PIN_B3 ,1);
delay_ms(1000);
output_bit( PIN_D0 ,1);
delay_ms(1000);
output_bit( PIN_D0 ,0);
delay_ms(1000);
Goto loop;
} |
So WHERE in the code above do you see where the interrupt cause a throttle/pause/control effect of the main loop (goto's ignored)??
I don't see anything that would allow the interrupt to control anything in the main loop.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
fariq23
Joined: 29 Nov 2010 Posts: 8
|
|
Posted: Thu Dec 09, 2010 10:55 am |
|
|
#include <16f877a.h>
#use delay(clock = 20000000)
#fuses hs, noprotect, nowdt, nolvp
#byte PORTB=6
#INT_EXT
void switch_isr(){
portb=0b00010000;
output_bit(pin_D0,0);
delay_ms(2000);
}
void main ()
{
set_tris_b(0b00000001);
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
ext_int_edge(H_TO_L);
output_bit( PIN_B1 ,1);
delay_ms(1000);
output_bit( PIN_B2 ,1);
delay_ms(1000);
output_bit( PIN_B3 ,1);
delay_ms(1000);
output_bit( PIN_D0 ,1);
delay_ms(1000);
output_bit( PIN_D0 ,0);
delay_ms(1000);
}
}While(1);
am i right with this condition?? |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Thu Dec 09, 2010 11:01 am |
|
|
Well, yes and no.
It's bad form to use anything that purposefully passes time in an ISR (like delay_ms).
Not that it can't be done... but you will learn that optimally, it's best to set a flag in the ISR and then let main() see the flag change and then execute some commands based on that flag condition (resetting the flag at the end).
What you have would work -- but down the road is not a recommended method. (because of the delay_ms() in your ISR)
Did you try it? Does it work?
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Dec 09, 2010 11:02 am |
|
|
and, 'how long does it take to respond'.
Fourth line of my post....
Best Wishes |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Thu Dec 09, 2010 11:05 am |
|
|
Ha! Ttelmah and I posting at the same time.
When I was writing my post, you hadn't posted yet. _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
fariq23
Joined: 29 Nov 2010 Posts: 8
|
|
Posted: Thu Dec 09, 2010 11:11 am |
|
|
but my condition, i want interrupts take an action for 2 second..
and then continue back the main routine..i read the datasheet about interrupt.
it explain the another subroutine will take over when interrupts occur and after a few moment it will continue where it was stop..
i'm not try the coding yet because i'm do not have kit to test the program.. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Thu Dec 09, 2010 11:14 am |
|
|
fariq23 wrote: |
i'm not try the coding yet because i'm do not have kit to test the program.. |
Well, heck - you need to have a prototype to test this stuff. You could even use MPLAB's MPSIM (don't use PROTEUS!!!) to get an idea of how the software behaves.
But ultimately, test on real hardware -- period.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
fariq23
Joined: 29 Nov 2010 Posts: 8
|
|
Posted: Thu Dec 09, 2010 11:19 am |
|
|
thanks bkmen..i will try to test my program on hardware..
but i need your suggestion where the part of my coding is totally wrong and the part that best part to put and interrupts subroutine..
thank for your cooperation... |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Thu Dec 09, 2010 11:25 am |
|
|
As Ttelmah said, you need something like this:
Code: |
static unsigned int state=0;
#INT_EXT
void isr_ext ( void ) {
if (!state)
state = 1;
}
void main() {
// All your previous setup stuff.
while (1) {
// state == 0, spin in main "while" loop doing nothing.
if (state) { // state = 1, do some stuff
portb=0b00010000;
output_bit(pin_D0,0);
delay_ms(2000);
output_bit( PIN_B1 ,1);
delay_ms(1000);
output_bit( PIN_B2 ,1);
delay_ms(1000);
output_bit( PIN_B3 ,1);
delay_ms(1000);
output_bit( PIN_D0 ,1);
delay_ms(1000);
output_bit( PIN_D0 ,0);
delay_ms(1000);
state = 0;
}
}
}
|
_________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
fariq23
Joined: 29 Nov 2010 Posts: 8
|
|
Posted: Thu Dec 09, 2010 11:33 am |
|
|
thanks bkamen.. |
|
|
|