![]() |
![]() |
![]() |
|
|
|||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
|
|
Thread Tools | Display Modes |
|
|
(permalink) |
|
Experienced 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); 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 by Mike, K8LH; 30th September 2006 at 02:35 AM. |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
The answer should be obvious- you need an independent debounce counter for each pin.
So you either say: Code:
if(pinDebounceFlags!=0x00){
unsigned char i;
for(i=0;i<8;i++){
if(pinDebounceCounter[i]>0){
--pinDebounceCounter[i];
if(pinDebounceCounter[i]==0){
pinDebounceFlags&=~(0b1<<i);
}
}
}
}
__________________
I thought what I'd do was I'd pretend I was one of those deaf-mutes. |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
Just brought the code in the first post up-to-date.
I also have example vertical counter ISR code now with debounce and repeat capability, if anyone's interested. It's relatively small and tight at 48 words and provides a 512-msec repeat rate for designated repeat keys. It's kind of nice to designate a pair of repeat switches on-the-fly and simply push and hold them to increment or decrement displayed values instead of repeatedly pushing them (then I un-designate them as repeat switches when done). Regards, Mike |
|
|
|