Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Button Debounce Coding help

Status
Not open for further replies.
Wow what a piece of code Mike I will try your coding & tell the progress.It should work for sure.

Thanks Mike.
 
Use Pommie's code, for sure the displays won't turn off or dim or get crazy :D. But make sure you return from the label SHOW. So you don't need to use ISR if you're not familiar with it.
 
Oznog,

I've discovered and developed some relatively simple and reliable methods for debouncing and managing multiple switches over the last few years. Would you mind if I share them with you?

First, I use relatively simple switch state latch logic for managing one to eight switches (in parallel). Using a switch state latch allows you to process and act on a "new" debounced switch press or a "new" debounced switch release while ignoring the remaining portion of a switch cycle (how long the switch is pressed or released).
Code:
;
SWKEYS  equ     0x20            ; debounced switch bits, '1' = pressed
SLATCH  equ     0x21            ; switch state latch
SWITCH  equ     0x22            ; switch flag bits for MAIN
;
;  this routine transfers a new debounced switch press to the SWITCH
;  variable for MAIN
;
ISR_Switch_Press
        movf    SWKEYS,W        ; debounced switch bits
        xorwf   SLATCH,W        ; each '1' is a change (press or release)
        andwf   SWKEYS,W        ; each '1' is a "new" switch press
        xorwf   SWITCH,F        ; toggle switch flag bits for use by MAIN
        movf    SWKEYS,W        ; update switch state latch
        movwf   SLATCH          ;
;
;  this routine transfers a new debounced switch release to the SWITCH
;  variable for MAIN
;
ISR_Switch_Release
        movf    SWKEYS,W        ; debounced switch bits
        xorwf   SLATCH,W        ; each '1' is a change (press or release)
        andwf   SLATCH,W        ; each '1' is a "new" switch release
        xorwf   SWITCH,F        ; toggle switch flag bits for use by MAIN
        movf    SWKEYS,W        ; update switch state latch
        movwf   SLATCH          ;
There are several different ways your MAIN program can process a switch press flag bit in the SWITCH variable (or a switch release flag bit if you're using the "release" algorithm). Let's say we've defined a switch called "sw_UP" as bit 0 in the SWITCH variable. Here's one way you might process that switch in MAIN;
Code:
;
;  test "UP" switch
;
Test_UP btfss   sw_UP           ; is SWITCH,0 a '1' (new switch press)?
        goto    Test_DOWN       ; no, branch, else
        bcf     sw_UP           ; clear bit so we don't process again
; perform "UP" code here
;
The previous example is for momentary type switch functions where we press a switch, perform some function, and we're done. We clear the flag bit after we test it and it won't get set again until the user releases the switch and presses it again.

We can also use our standard momentary push button switches to emulate toggle switches. That is, press a switch to toggle the switch flag bit from on-to-off or from off-to-on. This is extremely handy for lighted push button switches. Push it once to light the LED then push it again to toggle the LED off. In this case the only difference in the way you process the switch in MAIN is that you don't need to clear the switch flag bit after testing it. It gets toggled automatically in the ISR after each "new" press.
Code:
;
;  test SET mode toggle switch flag
;
SET     btfss   sw_SET          ; is SWITCH,1 a '1' (SET mode on)?
        goto    NextProc        ; no, branch, else
;
;  perform SET functions in SET_loop
;
SET_loop
;
;  has SET mode been turned off
;
        btfsc   sw_SET          ; SET switch still on?
        goto    SET_loop        ; yes, continue SET operations, else
;
;  save any changes and exit
;
And if I haven't bored you to death, here's one last extremely simple addition to that ISR code that provides us with a switch press beep. The additional code sends a short 32 msec 500 Hz beep when it detects "new" switch press bits in W.
Code:
;
SWKEYS  equ     0x20            ; debounced switch bits, '1' = pressed
SLATCH  equ     0x21            ; switch state latch
SWITCH  equ     0x22            ; switch flag bits for MAIN

BEEP    equ     0x23            ; beep timer
;
;  process "new" debounced switch "presses"
;
ISR_Switch_Press
        movf    SWKEYS,W        ; debounced switch bits
        xorwf   SLATCH,W        ; each '1' is a change (press or release)
        andwf   SWKEYS,W        ; each '1' is a "new" switch press
;
        skpz                    ; any "new" presses?  no, skip, else
        bsf     BEEP,5          ; send short 32-msec 500-Hz "beep"
;
        xorwf   SWITCH,F        ; toggle switch flag bits for use by MAIN
        movf    SWKEYS,W        ; update switch state latch
        movwf   SLATCH          ;
;
;  BEEP routine (500-Hz when using 1 msec interrupts)
;
        movf    BEEP,W          ; beep timer set?
        bz      ISR_Next        ; no, branch, else
        movf    PORTA,W         ;
        xorlw   1<<SPKR         ; toggle SPKR port bit in W
        movwf   PORTA           ; toggle actual SPKR pin
        decf    BEEP,F          ; decrement beep timer
;
ISR_Next
Not bad for 15 words, yes, no?

The important thing to note about this code and method is that it simply tests the switches during each 1 msec interrupt and doesn't tie up the processor unnecessarily by waiting for a switch to change state.

I've also developed some similarly "tight" code for implementing multiple independant debounce timers (which work on both press and release), repeat timers, etc., but they use vertical counters which seems completely alien to most people so I won't impose those algorithms on you folks at this time (grin).

Regards, Mike
 
Last edited:
Here the request pics of a my tact switch during release. When zoomed out the button press always looks very clean. Yet its a different story when a 1 GS/s digital scope is called into action on the front line :).

**broken link removed**
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top