View previous topic :: View next topic |
Author |
Message |
Vamsi Guest
|
INT_EXT |
Posted: Thu Oct 11, 2007 9:42 am |
|
|
Hi.. I am trying to use external interrupts on PIC18F4520..
RB0/INT0 is pulled high. when i press a switch it will be pulled down and an interrupt should be generated.
FOllowing is my code Code: | #include<18F4520.h>
#device ICD=TRUE
#use delay(clock=4000000)
int value=0;
void main()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
SET_TRIS_B(0xFF);
SET_TRIS_D(0x00);
while(1);
}
#INT_EXT
PORTB_INTERRUPT()
{
delay_ms(100);
OUTPUT_TOGGLE(PIN_D2);
}
|
I should be able to toggle PIN D2 when i press the swtich.. but i am not able to do so.. i.e. an interrupt is not generated....
Please help me |
|
![](templates/subSilver/images/spacer.gif) |
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Thu Oct 11, 2007 10:51 am |
|
|
You need to set the edge that is going to trigger the external interrupt.
Only use your ISR to set a flag that will be referenced in your mainline code.
Look at the 18F4520.h file to see the correct 'terminology' for setting the edge trigger.
Don't use delays in an ISR.
Try these suggestions and return with your results and somebody will help with the next set of questions.
John |
|
![](templates/subSilver/images/spacer.gif) |
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Thu Oct 11, 2007 11:02 am |
|
|
You didn't post your #FUSE statements so I'll post a suggestion for them here.
#FUSES XT // osc <= 4MHZ
#FUSES NOWDT // no watchdog
#FUSES PUT // power up timer
#FUSES NOLVP // no Low Voltage Programming (almost standard fuse)
#FUSES NOPBADEN // make portb pins to be digital inputs and not analog
You don't need to set the tris unless you're using fast_io
When enabling interrupts, enable each individual interrupt and THEN enable the global interrupt
In normal practice, make your ISR as short as possible. NEVER put a delay inside. Something like this would have a flag set, inside the ISR, and then evaluate that flag somewhere else (most likely in main() ).
You might want to look at ext_int_edge() to determine which edge you want the interrupt to trigger on.
Hope this helps.
Ronald |
|
![](templates/subSilver/images/spacer.gif) |
Vamsi Guest
|
INT_EXT |
Posted: Thu Oct 11, 2007 12:24 pm |
|
|
I have tried as suggested.. but still i am not able to toggle PIN_D2.... please suggest me something so that it works
the new code is
Code: |
#include<18F4520.h>
#device ICD=TRUE
#use delay(clock=4000000)
#FUSES XT // osc <= 4MHZ
#FUSES NOWDT // no watchdog
#FUSES PUT // power up timer
#FUSES NOLVP // no Low Voltage Programming (almost standard fuse)
#FUSES NOPBADEN // make portb pins to be digital inputs and not analog
int value=0;
void main()
{
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
EXT_INT_EDGE(L_TO_H);
while(1);
}
#INT_EXT
PORTB_INTERRUPT()
{
OUTPUT_TOGGLE(PIN_D2);
}
|
thank you |
|
![](templates/subSilver/images/spacer.gif) |
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Thu Oct 11, 2007 12:55 pm |
|
|
I think this should work:
Code: | #include<18F4520.h>
#device ICD=TRUE
#use delay(clock=4000000)
#FUSES XT // osc <= 4MHZ
#FUSES NOWDT // no watchdog
#FUSES PUT // power up timer
#FUSES NOLVP // no Low Voltage Programming (almost standard fuse)
#FUSES NOPBADEN // make portb pins to be digital inputs and not analog
int1 ext_int_flag = false;
#INT_EXT
PORTB_INTERRUPT()
{
ext_int_flag = true;
}
void main()
{
EXT_INT_EDGE(L_TO_H);
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1);
{
if(ext_int_flag)
{
ext_int_flag = false;
OUTPUT_TOGGLE(PIN_D2);
}
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Vamsi Guest
|
INT_EXT |
Posted: Thu Oct 11, 2007 1:08 pm |
|
|
I am sorry it doesnt work...
any other suggestions ?? |
|
![](templates/subSilver/images/spacer.gif) |
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Oct 11, 2007 1:23 pm |
|
|
Code: |
void main()
{
EXT_INT_EDGE(L_TO_H);
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1); // !!!! DELETE THE SEMICOLON
{
if(ext_int_flag)
{
ext_int_flag = false;
OUTPUT_TOGGLE(PIN_D2);
delay_ms(200); // I would add this delay
}
}
}
|
Hope it should work.
Humberto
Last edited by Humberto on Thu Oct 11, 2007 1:26 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Thu Oct 11, 2007 1:26 pm |
|
|
Change:
Code: | EXT_INT_EDGE(L_TO_H); |
to
Code: | EXT_INT_EDGE(H_TO_L); |
Quote: | RB0/INT0 is pulled high. when i press a switch it will be pulled down and an interrupt should be generated.
|
Either should work, but the second is more correct for what you intend to do.
General approach for debugging should be:
Get a basic program written and loaded to confirm hardware. Can you toggle an LED successfully with the hardware?
Check each pin for your functionality one at a time (if you're working on a board you've assembled.)
Sequentially add features/parts. |
|
![](templates/subSilver/images/spacer.gif) |
Vamsi Guest
|
INT_EXT |
Posted: Thu Oct 11, 2007 1:59 pm |
|
|
I tried all this but still it doesnt work.... yes i also tried toggling LED at PIN_D2 it works otherwise...
again the code is
Code: |
#include<18F4520.h>
#device ICD=TRUE
#use delay(clock=4000000)
#FUSES XT // osc <= 4MHZ
#FUSES NOWDT // no watchdog
#FUSES PUT // power up timer
#FUSES NOLVP // no Low Voltage Programming (almost standard fuse)
#FUSES NOPBADEN // make portb pins to be digital inputs and not analog
int1 ext_int_flag = false;
#INT_EXT
PORTB_INTERRUPT()
{
ext_int_flag = true;
}
void main()
{
EXT_INT_EDGE(L_TO_H); //also tried H_TO_L
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1)
{
if(ext_int_flag)
{
ext_int_flag = false;
delay_ms(100);
OUTPUT_TOGGLE(PIN_D2);
}
}
}
|
Any suggestions?? |
|
![](templates/subSilver/images/spacer.gif) |
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Thu Oct 11, 2007 2:07 pm |
|
|
I would add a 'heart beat' LED flash to the program to ensure that it's not hanging somewhere.
What board are you using?
Do you have a scope available? |
|
![](templates/subSilver/images/spacer.gif) |
vamsi Guest
|
INT_EXT |
Posted: Thu Oct 11, 2007 2:33 pm |
|
|
yes i do have a scope and i am using PICDEM2 PLUS with PIC18F4520 |
|
![](templates/subSilver/images/spacer.gif) |
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
INT_EXT |
Posted: Thu Oct 11, 2007 2:39 pm |
|
|
This code should do the test,
I still do not know how to post code correct but here is what I have.
Also do NOT do several other things while doing a post .
tom
#include<18F4520.h>
#device ICD=TRUE
#use delay(clock=4000000)
#FUSES XT // osc <= 4MHZ
#FUSES NOWDT // no watchdog
#FUSES PUT // power up timer
#FUSES NOLVP // no Low Voltage Programming (almost standard fuse)
#FUSES NOPBADEN // make portb pins to be digital inputs and not analog
int1 ext_int_flag = false;
#int_ext
void PB0_isr (void) ()
{
ext_int_flag = true;
}
void main(void) ()
{
output_low (PIN_D2);
clear_interrupt(INT_EXT);
EXT_INT_EDGE (H_TO_L);
enable_interrupts (INT_EXT);
enable_interrupts(GLOBAL);
do {
if(ext_int_flag)
{
ext_int_flag = false;
output_toggle (PIN_D2);
}
}
while(1);
}
Last edited by w2drz on Fri Oct 12, 2007 2:18 pm; edited 4 times in total |
|
![](templates/subSilver/images/spacer.gif) |
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Thu Oct 11, 2007 4:09 pm |
|
|
Well.....
I pulled out my PICDem2+ and dusted off.
This is what I've learned. It doesn't look as though you can use the LEDs at the same time as the pushbutton. Look at the signal on B0 with the button pushed and not. I then pulled one lead of the RB0 LED and got the interrupt signal to look good.
From there I've got no idea why the INT_EXT won't fire.
PCM_Programmer to the white courtesy phone.
BTW - I tried disabling the portb pullups and reading pin_b0 to ensure that it was configured as an input.
UPDATE: The INT_EXT bit is getting set but the ISR isn't happening.
It looks as though it can never get to the point where it checks the EXT0IF bit in line 0054. There is never a GOTO 0054 called in the rest of the program.
Code: | 004A: MOVFF 04,13
004E: BTFSS FF2.4
0050: GOTO 005A
0054: BTFSC FF2.1
0056: GOTO 00A0
005A: MOVFF 0F,00 |
And I can confirm the EXT0IF never gets cleared, so the ISR must not get called.
************************
Take out the ICD declaration. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Fri Oct 12, 2007 2:38 am |
|
|
There would not be a goto anywhere in the program. The lines above, drop through to this, if FF2.4 is set. This is the intrrupt _enable_ bit. The sequence is:
Interrupt triggers.
If GIE is set, the chip performs an automatic 'call' to address 8 (or 18, fo a low priority interrupt if interrupt priorities are enabled). At this point, all the registers are saved.
Then, working in the order that the interrupt handlers are defined (or in the order set in a #priority statement if present), the code tests each interrupt enable bit in turn, and then the corresponding interrupt flag bit. Only if _both_ are set for a particular interrupt, is the handler called.
The code you show, is the correct handler for this interrupt, and will work.
As posted, your code is either massively faulty, or just the posting screws it up. You have several lines :
Code: |
output_low (PIN_D2);
clear_interrupt(INT_EXT);
EXT_INT_EDGE (H_TO_L);
enable_interrupts (INT_EXT);
enable_interrupts(GLOBAL);
|
Which as shown, are never executed...
Try:
Code: |
#include<18F4520.h>
#device ICD=TRUE
#use delay(clock=4000000)
#FUSES XT // osc <= 4MHZ
#FUSES NOWDT // no watchdog
#FUSES PUT // power up timer
#FUSES NOLVP // no Low Voltage Programming (almost standard fuse)
#FUSES NOPBADEN // make portb pins to be digital inputs and not analog
int1 ext_int_flag = false;
#int_ext
void PB0_isr (void) {
ext_int_flag = true;
}
void main(void) {
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
do {
if(ext_int_flag) {
ext_int_flag = false;
output_toggle (PIN_D2);
}
} while(TRUE);
}
|
This exceutes correctly as posted, and toggles pin D2, whenever an interrupt is received.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Fri Oct 12, 2007 2:59 am |
|
|
I could only get it to work after pulling the lead on R21 on the PICDem 2+ board (That's the RB0 LED current limit resistor) and removing the ICD=TRUE.
Ttelmah, will your code work without enabling the interrupts? (I'm not where I can test it, otherwise I would. |
|
![](templates/subSilver/images/spacer.gif) |
|