//PIC16F1823 Button debounce using Interrupt On Change and timer overflow interrupts
/*@ignore@*/
#include <xc.h>
/*@end@*/
#include "header.h"
//Configuration bits
#pragma config WDTE=OFF, PWRTE = OFF, MCLRE=ON, BOREN=OFF, FCMEN=OFF, CLKOUTEN = OFF, IESO=OFF, FOSC=INTOSC, CPD=OFF, LVP = OFF, BORV = 0, PLLEN = OFF
#pragma switch speed
#define _XTAL_FREQ 32000000
void main() {
//TRISA
//TRISC
//RX(RC5), SCL(RC0) and SDA(RC1) as inputs
TRISA = 0b00010000;
TRISC = 0b00100011;
//Weak pull ups enabled on RA4
WPUA = 0b00010000;
//Set all I/O's to digital
ANSELA = 0x00;
ANSELC = 0x00;
PORTA = 0b00110000;
PORTC = 0x00; //Clear RC2 to unlight LED
//Enable Interrupt On Change on neagative slope on RA4
IOCAN = 0b00010000;
//No interrupt on positive slope
IOCAP = 0x00;
//Reset interrupt flag
IOCAF = 0x00;
//0 Internal oscillator, 3 <fosc> on, 6-4 31kHz
// OSCCON = 0b00000000;
OSCCON = 0b11110000;
//Interrupt controller
//5 Timer0 overflow interrupt enabled
//6 Peripheral interrupt enabled
//7 Global interrupt enabled
//3 Interrupt on change enabled
INTCON = 0b11101000;
//Timer0
TMR0 = 0x00;
//Option Register
//2-0 Prescaler 1:4
//3 prescaler assigned to Timer0
//4 timer edge, high to low
OPTION_REG = 0b01000101;
//Loop forever, interrupts when Timer0 overflows
while (1) {
}
}
//Interrupt routine
interrupt void isr(void) {
static char overFlow = 0;
if (TMR0IF == 1)
{
TMR0IF = 0;
overFlow++;
if (overFlow == 0)
{
//Reenable Interrupt On Change
IOCAN = 0b00010000;
INTCON = 0b11101000;
}
}
else if (IOCAF4 == 1)
{
//Disable Interrupt On Change
INTCON = 0b11100000;
//Toggle LED
LATC ^= 1 << 2;
//Reset Interrupt On Change flag
IOCAF4 = 0;
}
return;
}
This is a very well controlled way to specify at which rate the button can be pressed without missing push-events, but as you can see, it adds quite a lot of code to the interrupt service routine. Since I have optimized my ISR quite a bit, I want to avoid adding code to it. I am also running out of data space in general, so that is also a reason not to add more code.
So, I tried out debouncing the analog way, by adding a low pass filter between the button and the IO pin.
Analogue Switch Debouncer |
The analogue solution worked fine, but I need to do some strapping for it to work. I'll make a new version of the board that incorporates this.
Analogue Debounce strap |