Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronics Categories > Micro Controllers


Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc.

Reply
 
Thread Tools Display Modes
Old 31st July 2006, 09:50 PM   (permalink)
Experienced Member
Mike, K8LH is a name known to allMike, K8LH is a name known to allMike, K8LH is a name known to allMike, K8LH is a name known to allMike, K8LH is a name known to allMike, K8LH is a name known to all
Default PIC Switch Management Techniques

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
;
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;

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
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;

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
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

Last edited by Mike, K8LH; 30th September 2006 at 02:35 AM.
Mike, K8LH is online now   Reply With Quote
Old 1st August 2006, 08:18 AM   (permalink)
Experienced Member
 
Oznog is just really niceOznog is just really niceOznog is just really nice
Send a message via AIM to Oznog
Default

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);
            }
        }
    }
}
or you can go with a timer solution, which is preferred since the debounce period remains constant even when the processor has to do other tasks.
__________________
I thought what I'd do was I'd pretend I was one of those deaf-mutes.
Oznog is offline   Reply With Quote
Old 28th September 2006, 12:33 PM   (permalink)
Experienced Member
Mike, K8LH is a name known to allMike, K8LH is a name known to allMike, K8LH is a name known to allMike, K8LH is a name known to allMike, K8LH is a name known to allMike, K8LH is a name known to all
Default

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
Mike, K8LH is online now   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes




All times are GMT. The time now is 05:35 AM.


Electronic Circuits  |  Radio Controlled
Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.