# 2 push buttons instead of one

#### dayv3

Joined May 22, 2014
38
Hi all,

Awhile ago I wrote/ built an interrupt driven push button de-bouncing circuit with a 12F683. But now, I want to be able to de-bounce 2 push buttons instead of one, each one acting separately. What is the best way to approach this problem? Do I use separate PICs for each button or is it better to have 2 interrupt routines running simultaneously? I am looking for someone to help point me in the correct direction.

Dave

#### shteii01

Joined Feb 19, 2010
4,647
In Intel 8051 interrupts have priority. So even if you trigger both interrupts, one of them will have higher priority then the other and will be executed first.

Is PIC setup the same way?

The debouncing routine should be the same for both buttons.

#### dayv3

Joined May 22, 2014
38
Is PIC setup the same way?
I do not know

For my application, toggling a relay, I do not think it matters that much, but you ask a good question
that I need to know the answer to for future projects. I will look for an answer to your question and on
how to use 2 ISR's
Thanks

#### JohnInTX

Joined Jun 26, 2012
3,976
12Fxxx is single priority interrupts.A good way to debounce is to use a timer interrupt that peridocally samples the inputs and uses the timer period over several interrupts to do the debouncing. Post flags that indicate the status of the switches.
Search the forums for debounce and you will get lots of examples.

#### dayv3

Joined May 22, 2014
38
@JohnInTX I already have a good interrupt routine that you helped me with some time ago.
What do you mean by single priority?

But I have never ran two ISR's at the same time so I will need to teach myself how to do that.
Does a anyone know where there is a good example of a PIC being run with multiple ISR's
that I can study? ( In C)

Dave

#### spinnaker

Joined Oct 29, 2009
7,837
Your current interrupt routine should read the value of the pin. Do it the same way as one except expand your code to read the second pin.

It would have really helped if you included your code.

#### ErnieM

Joined Apr 24, 2011
8,018
There is no need to see the existing code because it is based on a poor method of reading buttons. Why poor? Because it struggles to handle multiple pins.

Instead of an interrupt for each pin thing of one interrupt to start a button check. If even multiple buttons are stable (pressed or not pressed) over several readings then they can be marked as changed and denounced.

When I do this I have found readings every 25 ms to be good; two readings that agree will mark stable buttons. Note the time may need be longer for buttons that bounce more. I findvthis interval intercept able for the human pressing the button.

This method also gives you a way to get a system heartbeat which is quite useful when you need to time something.

#### spinnaker

Joined Oct 29, 2009
7,837
There is no need to see the existing code because it is based on a poor method of reading buttons. Why poor? Because it struggles to handle multiple pins.

Instead of an interrupt for each pin thing of one interrupt to start a button check. If even multiple buttons are stable (pressed or not pressed) over several readings then they can be marked as changed and denounced.

When I do this I have found readings every 25 ms to be good; two readings that agree will mark stable buttons. Note the time may need be longer for buttons that bounce more. I findvthis interval intercept able for the human pressing the button.

This method also gives you a way to get a system heartbeat which is quite useful when you need to time something.

You are recommending polling rather than instead of using interrupts for the switches? Yeah I was going to mention that.

What I would like to see is some good debounce code written in C. I think others would find it useful so please share. I have some I use that I wrote years ago and I sort of use the method you mentioned, seems to work put I am not positive the code is flawless.

#### dayv3

Joined May 22, 2014
38
For the C code that I wrote/ use look up "12F683 ISR switch debounce", I always document my code well.
I looked on the web and found a few references to using multiple interrupts but I have not yet
found a really clean picture. If anyone has or knows of a good example of using multiple interrupts I
would appreciate it if you would point me to it.

#### JohnInTX

Joined Jun 26, 2012
3,976
What do you mean by single priority?
I could have been more clear on that - sorry, typing on a tablet.
Single priority (and single interrupt vector) means that there is only one interrupt / service routine. You can process more than one interrupt in the system but they all share resources and if you in the process of servicing one interrupt, any others that may occur during that time have to wait, regardless of how much more important they may be. That is why experienced PIC programmers will tell you to always keep your interrupt routines as short as possible and never do delays inside the ISR.

I do my debouncing logic a little different than ErnieM but we both use a single timer interrupt to schedule sampling of the switch(es).

#### spinnaker

Joined Oct 29, 2009
7,837
Why do you think you need to use interrupts? Just use polling instead.

But if you insist on interrupts.

I stand corrected on my post above above for those chips that support multiple external interrupts. That is the problem with not checking datasheets. It is more complicated than just reading the values. You need to enable the interrupts for those other pins and implement the additional interrupt code.

But I think that is not going to apply for you anyway.

I am not familiar with the 12 family of Pics but I have checked the datasheet. Have you done the same? From what I am reading, only GP2 has an external interrupt. So you will either need to poll or move to another Pic. Or hopefully someone will correct me on one external interrupt.

#### spinnaker

Joined Oct 29, 2009
7,837
I could have been more clear on that - sorry, typing on a tablet.
Single priority (and single interrupt vector) means that there is only one interrupt / service routine. You can process more than one interrupt in the system but they all share resources and if you in the process of servicing one interrupt, any others that may occur during that time have to wait, regardless of how much more important they may be. That is why experienced PIC programmers will tell you to always keep your interrupt routines as short as possible and never do delays inside the ISR.

I do my debouncing logic a little different than ErnieM but we both use a single timer interrupt to schedule sampling of the switch(es).
I think the 12F683 only has one external interrupt on GP2 anyway. Can you confirm?

#### spinnaker

Joined Oct 29, 2009
7,837
Looks like all of the pins are interrupt on change. But only GP0 has external interrupt.

#### JohnInTX

Joined Jun 26, 2012
3,976
As @spinnaker says. But I would not use interrupt on change for debouncing. It gets ugly fast IMO.

#### dayv3

Joined May 22, 2014
38
I could have been more clear on that - sorry, typing on a tablet. Single priority (and single interrupt vector) means that there is only one interrupt / service routine.
That is what I thought you meant. but if I remember correctly once the interrupt routine is entered the processor saves the stack so no events will be lost, just delayed. Which is fine for my application.

I need to do a little more research on how to do multiple interrupts, but if anyone has a clean example in C I would greatly appreciate it.

#### MMcLaren

Joined Feb 14, 2010
842
Hello again, Dave. Hope you and family are well and enjoying the beginning of this Holiday season.

There are a couple example code snippets at Debouncing a switch in software using a PIC16F72 that use parallel switch state logic to filter out all but the "new press" state for multiple switches. One of the examples simply samples the switches at some prescribed 'debounce' interval while one of the other examples includes a low pass filter, like you're using now, using a 2-bit vertical counter. Basically, it's a way to run up to eight independent 24-msec counters in parallel. Not the easiest code to understand, however, recently Forum member Joey999 reminded me of a method I came across on the Microchip Forum which may be a little easier to understand. Both low pass filter methods rely on sampling a switch at the same state four times in a 24-millisecond span before toggling the debounced switch state latch for any particular switch. All of the routines debounce both the "press" and "release" states and pass along "new press" flags for your main program.

Don't be afraid to ask questions...

Cheerful regards, Mike

Code:
;
;  sample switches at 8-msec intervals.  debounce both 'press' and 'release'
;  states by sampling them four times at the same state spanning 24-msecs.
;
void interrupt()             //
{ TMR2IF = 0;                // clear TMR2 interrupt flag
delta[3] = delta[2];       // shift delta accumulator
delta[2] = delta[1];       //  "
delta[1] = delta[0];       //  "
swnew = ~GPIO;             // sample active lo switches
swnew &= 0b00001001;       // on GP3 & GP0 pins only
swnew ^= swold;            // changes, press or release
delta[0] = swnew;          // add sample to accumulator
swnew &= delta[1];         // check debounce 'time-out'
swnew &= delta[2];         //  "
swnew &= delta[3];         //  "
swold ^= swnew;            // update switch state latch
swnew &= swold;            // filter out 'release' bits
flags |= swnew;            // save 'new press' flags
}                            //
Code:
;
;  vertical counter example
;
;  sample switches at 8-msec intervals.  debounce both 'press' and 'release'
;  states by sampling them four times at the same state spanning 24-msecs.
;
void interrupt()             //
{ TMR2IF = 0;                // clear TMR2 interrupt flag
delta = ~GPIO;             // sample active lo switches
delta &= 0b00001001;       // on GP3 & GP0 pins only
delta ^= latch;            // changes, press or release
vcnt0 &= delta;            // clear stable or bouncing counters
vcnt1 &= delta;            //  "
vcnt0 = ~vcnt0;            // increment counters
vcnt1 ^= vcnt0;            //  "
delta &= vcnt0;            // collect counter overflows
delta &= vcnt1;            //  "
latch ^= delta;            // update switch state latch
delta &= latch;            // filter out 'release' bits
flags |= delta;            // save 'new press' flags
}                            //

Last edited:

#### spinnaker

Joined Oct 29, 2009
7,837
That is what I thought you meant. but if I remember correctly once the interrupt routine is entered the processor saves the stack so no events will be lost, just delayed. Which is fine for my application.

I need to do a little more research on how to do multiple interrupts, but if anyone has a clean example in C I would greatly appreciate it.

You cannot do external interrupts with more than one switch on that Pic. Why don't you post you existing code so this all becomes more clear? Help others to help you.

#### MMcLaren

Joined Feb 14, 2010
842
You cannot do external interrupts with more than one switch on that Pic. Why don't you post you existing code so this all becomes more clear? Help others to help you.
Nonsense! You can use IOC (Interrupt On Change) for all six I/O pins on the 12F683.

#### spinnaker

Joined Oct 29, 2009
7,837
I said external interrupt not IOC. IOC capability mentioned in post #13. Since the OP has not posted his code no way to know what he is doing.

Last edited:

#### spinnaker

Joined Oct 29, 2009
7,837
And I am trusting John's knowledge of IOC that this is not the best way to go in this application. Post 14.