Mike - K8LH
Well-Known Member
Dear fellow Designers/Hobbyists,
Has anyone else struggled to write code to debounce and manage multiple push button switches in the PIC environment? If so, and you've come up with a clever or innovative technique, would you consider sharing it with us here on the Forum, please? We'd love to study it. Thanks.
In that spirit I'd like to share a technique I've developed to process up to 8 switches in parallel in my applications. In a nutshell, it's 27 lines of ISR code that provides the following features/capabilities;
<> process up to 8 switches in parallel
<> eight independent 24.0-msec "debounce" vertical counters
<> debounced switch press audible feedback (beep or click)
<> momentary switch operation (test then clear a SWITCH bit)
<> toggle switch emulation (push to toggle a SWITCH bit from off-to-on or from on-to-off) perfect for lighted switches
I discovered early on that if I set a switch pressed "memory" or "latch" bit to the last state of the switch that I could determine a couple different conditions. Specifically, if the live switch bit is on and the switch memory bit is off I'm detecting a new switch "press", and if the live switch bit is off and the switch memory bit is on I'm detecting a new switch "release". Translating this into ISR code to detect new switch presses for up to 8 switches in parallel, I came up with this (the SWITCH variable contains pressed switch flag bits for MAIN);
I thought the code was pretty cool considering the size (grin). The MAIN program simply tests a SWITCH flag bit and clears it for "momentary" switches and simply tests a SWITCH flag bit for push button switches emulating "toggle" switches (push the switch to toggle the SWITCH flag bit from on-to-off or from off-to-on). I use "toggle" switch emulation for lighted push button switches.
Next I added code to send audible feedback for "new" switch presses;
Not bad for a handful of instructions but there's something missing. These 8 switches aren't debounced. How the heck can you provide independent debounce timers for 8 switches? I was sure it could be done but I suspected that it wouldn't be very pretty (grin). That's when I discovered vertical counters. They were difficult for me to grasp at first and I won't go into details here but refer you instead to Scott Dattalo's examples. Here's the final fully debounced example ISR code;
This small "debounce" vertical counter ISR code has turned out to be so handy that I use it for switch management even on the simplest projects that might only have one or two switches. And managing lighted push button switches emulating "toggle" switches is a breeze (push on, push off).
Those of you interested in vertical counters should check out Scott Dattalo's examples and a "vertical counter" thread on the MC Forum.
Have fun. Kind regards, Mike
Has anyone else struggled to write code to debounce and manage multiple push button switches in the PIC environment? If so, and you've come up with a clever or innovative technique, would you consider sharing it with us here on the Forum, please? We'd love to study it. Thanks.
In that spirit I'd like to share a technique I've developed to process up to 8 switches in parallel in my applications. In a nutshell, it's 27 lines of ISR code that provides the following features/capabilities;
<> process up to 8 switches in parallel
<> eight independent 24.0-msec "debounce" vertical counters
<> debounced switch press audible feedback (beep or click)
<> momentary switch operation (test then clear a SWITCH bit)
<> toggle switch emulation (push to toggle a SWITCH bit from off-to-on or from on-to-off) perfect for lighted switches
I discovered early on that if I set a switch pressed "memory" or "latch" bit to the last state of the switch that I could determine a couple different conditions. Specifically, if the live switch bit is on and the switch memory bit is off I'm detecting a new switch "press", and if the live switch bit is off and the switch memory bit is on I'm detecting a new switch "release". Translating this into ISR code to detect new switch presses for up to 8 switches in parallel, I came up with this (the SWITCH variable contains pressed switch flag bits for MAIN);
Code:
;
; toggle SWITCH variable switch pressed flags for MAIN
;
movf SWLIVE,W ; live switch bits for 8 switches
xorwf SWPEND,W ; xor switch pressed latch
xorwf SWPEND,f ; update switch pressed latch
andwf SWLIVE,W ; get new switch pressed bits
xorwf SWITCH,f ; toggle SWITCH flag bits for MAIN
;
Next I added code to send audible feedback for "new" switch presses;
Code:
;
; send short beep for "new" switch presses
;
movf SWLIVE,W ; live switch bits for 8 switches
xorwf SWPEND,W ; xor switch pressed latch
xorwf SWPEND,f ; update switch pressed latch
andwf SWLIVE,W ; any new switch pressed bits?
btfss STATUS,Z ; no, skip, else
bsf BEEPER,5 ; send 32-msec short beep
xorwf SWITCH,f ; toggle SWITCH flag bits for MAIN
;
; beep (500-Hz tone with 1.0-msec interrupts)
;
movf BEEPER,W ; is beep on?
bz ISR_Next ; no, branch, else
btg Speaker ; toggle speaker on PORTA,3
decf BEEPER,f ; decrement beep msec counter
;
ISR_Next
Code:
;******************************************************************
;
; Mike McLaren's "debounce" vertical counter ISR code based
; on concepts and examples from Jonny Doin and Scott Dattalo
;
; <> process up to eight switches in parallel
; <> eight independent 24.0-msec "debounce" vertical counters
; <> debounced switch press audible feedback (beep or click)
; <> momentary switch operation (test then clear a SWITCH bit)
; <> toggle switch emulation (push to toggle a SWITCH bit from
; off-to-on or from on-to-off) perfect for lighted switches
;
; 27 words/27 cycles (14-bit core)
;
;
; setup the SWKEYS variable with "live" switch press data from
; your switch input pins or your scanned switch matrix before
; falling into this routine. A '1' bit represents a 'pressed'
; switch and a '0' bit represents a 'released' switch.
;
; execute this code each 1.0-msec interrupt cycle
;
;
; clear vertical counters for bouncing and steady-state switches
;
ISR_Sw
movf SWKEYS,W ; live switch press data |B0
xorwf SLATCH,W ; debounced pressed switch latch |B0
andwf VCBIT0,f ; |B0
andwf VCBIT1,f ; |B0
;
; cyclic vertical counter algorithm. vcmask is seeded with an
; active switch mask and bn' is the previous state of bn before
; the bit increment operation.
;
; a switch is debounced or filtered after sampling it at the
; same level through four vertical counts spanning 24.0-msecs
;
; b0 ^= (vcmask)
; b1 ^= (vcmask & b0')
; b2 ^= (vcmask & b0' & b1')
;
; Mike McLaren's "cumulative AND" vertical counter method
;
; b0 ^= vcmask : vcmask &= bo'
; b1 ^= vcmask : vcmask &= b1'
; b2 ^= vcmask
;
andwf COLPOS,W ; 8-msec 'column' prescaler |B0
movwf VCMASK ; seed "cumulative AND" mask |B0
xorwf VCBIT0,f ; b0 ^= vcmask |B0
xorwf VCBIT0,W ; restore b0' in W |B0
andwf VCMASK,W ; vcmask &= b0' |B0
movwf VCMASK ; |B0
xorwf VCBIT1,f ; b1 ^= vcmask |B0
xorwf VCBIT1,W ; restore b1' in W |B0
andwf VCMASK,W ; vcmask &= b1' |B0
;
; each '1' bit in the SLATCH variable represents a "debounced"
; 24.0-msec switch press (bit cleared when switch is released)
;
xorwf SLATCH,f ; update debounced state latch |B0
;
; send a 32-msec short beep for new debounced switch presses
;
andwf SWKEYS,W ; new debounced switch press? |B0
btfss STATUS,Z ; no, skip, else |B0
bsf BEEPER,5 ; send 32-msec short beep |B0
;
; toggle SWITCH flag bits for processing by the MAIN program
;
; test SWITCH bits for emulated "toggle" switches. test then
; clear SWITCH bits for "momentary" switches.
;
xorwf SWITCH,f ; toggle SWITCH bits for MAIN |B0
;
; advance ring counter prescaler (initialized value = 00000001)
; for the next interrupt cycle
;
rlf COLPOS,W ; advance column ring counter |B0
rlf COLPOS,f ; |B0
;
; beep (500-Hz tone with 1.0-msec interrupts)
;
movf BEEPER,W ; beep timer set? |B0
bz ISR_Next ; no, branch, else |B0
movf GPIO,W ; read port |B0
xorlw 1<<Speaker ; |B0
movwf GPIO ; toggle piezo speaker pin |B0
decf BEEPER,f ; decrement timer |B0
;
ISR_Next
Those of you interested in vertical counters should check out Scott Dattalo's examples and a "vertical counter" thread on the MC Forum.
Have fun. Kind regards, Mike
Last edited: