View previous topic :: View next topic |
Author |
Message |
Bryan
Joined: 23 Apr 2005 Posts: 73
|
External Interrupt Buffer? |
Posted: Thu May 10, 2007 4:54 pm |
|
|
I have a button connecting to the external interrupt on a PIC18F1320 and my debounce routine works great on the downpress - no detection of any bouncing. Unfortunately, the PIC is fast enough that it always seems to pick up the release of the button - even when I minimize clockspeed at 31kHz. The strange thing is that I have the external_edge set to H_TO_L since my button is active low so this should not detect the release... I only want detection of the downpress so this is incredibly frustrating. As you can see from the code I even set the interrupt to be off for ~250ms after each press - far longer than it should take the user to press and depress the button yet it STILL picks up the release :( and the update is really slow on the LCD like it actually is buffering the interrupts. So anyhow, any help would be greatly appreciated!
Here is my code:
Code: |
include <18F1320.h>
#device adc=10
#fuses NOWDT,NOPROTECT,NOLVP,NOMCLR,INTRC_IO //CCPBO
#use delay(clock=31000)
#include "LCDD.c"
boolean update = false;
boolean released = false;
boolean pressed = true;
boolean peakfound = true;
boolean firstread = false;
boolean debounced = false;
#int_ext
void move_down()
{
disable_interrupts(INT_EXT);
presses++;
update = true;
set_timer1(62000);
}
#int_timer1
void peak_finder()
{
enable_interrupts(INT_EXT);
}
void main()
{
lcd_init();
setup_timer_1(T1_INTERNAL);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_EXT);
ext_int_edge(H_TO_L);
enable_interrupts(global);
set_tris_b(11111111);
port_b_pullups(00000001);
while(1)
{
if (update)
{
printf(lcd_putc, "\fPresses: %Lu", presses);
update = false;
}
}
}
| |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 10, 2007 5:02 pm |
|
|
Clear the External interrupt flag before you enable (or re-enable) external interrupts.
Example:
Code: |
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
|
|
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Thu May 10, 2007 5:12 pm |
|
|
Thanks PCMProgrammer - Works better although still only about 95% effective. Once in awhile on the release it will still detect an interrupt. May this be unavoidable without a debounce circuitry on the port? |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu May 10, 2007 5:36 pm |
|
|
Firing the timer1 you are nulling only the first bounces, but not the bounces
generated when you release the pushbutton.
Try this:
Code: |
#int_ext
void move_down()
{
disable_interrupts(INT_EXT);
presses++;
update = true;
do{}while(!PIN_B0);
set_timer1(62000);
}
|
Humberto |
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Thu May 10, 2007 6:02 pm |
|
|
Thank you Humberto, I understand what you're going for but I tested it and this didn't work. I believe the reason to be that this while loop will be exited immediately upon the first bounce even before the timer has a chance to debounce. So, when the button is released it simply bounces again several times and the loop doesn't do it's trick. The problem here is that upon release we get several bounces and the first one triggers the ISR before the timer1 can debounce it. Seems like this situation is unfortunately unavoidable without a hardware debouncer since there is no way to know exactly how long the user will be pressing the button. Any other ideas? |
|
|
libor
Joined: 14 Dec 2004 Posts: 288 Location: Hungary
|
|
Posted: Thu May 10, 2007 7:29 pm |
|
|
If you can afford a 50 ms latency I suggest to retest the input after 50ms and neglect the change if the input is not still low after the bouncing ended. As a by-effect any press shorter than 50ms (glitch, interference, etc) will also be neglected.
If you cannot afford staying in the isr so long, you can also do the retest in the timer isr to let your main code run. You can tune the delay to any optimum value you need.
Code: | #int_ext
void move_down()
{
delay_ms(50);
if (PIN_B0) return;
presses++;
update = true;
} |
|
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu May 10, 2007 9:13 pm |
|
|
The bounce problem at release time can be cancelled in this way, it doesn´t need any timer.
Code: |
#int_ext
void move_down()
{
int bounces;
disable_interrupts(INT_EXT);
bounces = 250;
presses++;
update = true;
do
{ delay_us(400); // you can trimm this value
if(!PIN_B0)
{ bounces = 250;}
else
{ bounces--;}
} while(bounces);
}
// in main()
while(1)
{
if(update)
{
printf(lcd_putc, "\fPresses: %Lu", presses);
update = false;
delay_ms(200);
enable_interrupts(INT_EXT);
}
}
|
Not tested nor tunned, I´m not in my job right now.
Humberto |
|
|
|