Jump to content
43oh

Debouncing in external interrupts


Recommended Posts

I was working on a Simon Game which runs on LPM4 most of the time, and I was having some issues with bouncing. So I did waste a few CPU cycles for two specially placed delays. I have written the test code to light up two LEDs when a button is pressed and made it totally with external interrupts.

 

When I used to work with AVRs, I used timers to debounce, but here I thought I can save too much battery if I used a little CPU utilization. I could use the timer with external interrupts but that would waste my only timer, which I have to use other purposes. ;)

 

Here it goes,

 

Two LEDs are wired to P1.0, P1.1 (with 220 ohms in series) and the button is hooked between GND and P1.4. I had to use internal pull ups and make this work. It is working pretty fine.

 

#include

long a;
int counter = 0; //To check if the interrupt are working properly

void init();

int main(){
init();
_EINT();
LPM4;
while(1);
}

void init(){
// Stop watchdog timer to prevent time out reset
 	WDTCTL = WDTPW + WDTHOLD;
//Setting up the I/O
P1DIR = BIT0 + BIT1;
P1REN = BIT4;
P1IE = BIT4;
P1IES = BIT4;
P1OUT = BIT4;
P1IFG = 0x0;
}

#pragma vector = PORT1_VECTOR
__interrupt void button_handler(){
LPM4_EXIT;
_DINT();
P1OUT ^= BIT0 + BIT1;
for(a = 0; a <= 0x200; a++);
P1IES ^= BIT4;
counter++;
P1IFG = 0x0;
for(a = 0; a <= 0x200; a++);
_EINT();
LPM4;
}

 

I like LPM4. :)

 

I changed the PxIES register to toggle the edge selection of interrupts. And basically that did the trick. I had to write two little delays specially placed so no misleading edges are detected.

 

Usually I don't put a while loop there in the main when I go to LPMs, but I saw that after a few ISRs, it stops working, and at the debugger I saw that it got restarted. So I put this while loop. I used the counter variable to see if the ISRs are working properly.

 

I used some standard buttons (Those comes with LaunchPad, I dunno the names). :D

Link to post
Share on other sites

you could use the WDT timer or timer_A, depends on what you have available. the other option is turn off the interrupt for just that interrupt and re-enable it right before the interrupt returns. I think the best bet is to use the WDT timer for a delay instead of a SW delay. There are other ways for de-bouncing but this is just my opinion. :)

Link to post
Share on other sites

The way I am doing it for multiple switches is by using shift register to read the position and the timer to control frequency at which they are read. Also, I have two variables, one to store position information and one to store information about position changes. After getting information from the register, I am XORing it with the positions from previous read and storing it in change variable. Then I am updating position variable. If the bit in the change variable is set, it means switch is not stable and should not be used at this time. When the bit is clear, it means switch did not change it's position since the last time we read it and could be considered stable. One thing about this solution is that you need a wake up switch if you want to preserve power.

Example, let's say we have one 165 with 8 switches, first var is change var, second is position, switches are off.

00000000

00000000

Now we flip one switch 00000001

00000001

00000001

Then on the next interrupt

00000000

00000001

Now we switch it off 00000000

00000001

00000000

And next interrupt

00000000

00000000

 

 

Just my $0.02

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...