PIC – Single Port Debounce Routine

PIC – Single Port Debounce Routine

Mechanical switches all ‘bounce’ to some degree, and this can cause havoc with microprocessor systems, especially when things need to be counted.  Luckily, it’s easy to debounce an entire ports-worth of switches with a fairly compact routine.  Look here for A Guide to Debouncing by Jack G. Ganssle.

Flow ChartDebounce Input Port

Download the Debounce Input Port flowchart.

 

Code

;*******************************************************************************
;*    Filename: SwitchDebouncePort.asm
;*    Date: 27-Mar-2015
;*    File Version:  0.0
;*    Author:    Brian Volken
;*    Company:     Brady Volken Enterprises
;*    Description: Debounce selected pins on desired port
;*******************************************************************************
;*    Revision History:
;*    0.0 Initial Version
;*******************************************************************************

;*******************************************************************************
;* Calling Instructions for this module
;*******************************************************************************
;*
;* This is for any details related to calling this module
;*
;* Exposed properties & Methods:
;*   Port_Changed, Byte, bit set to indicate what pin(s) changed
;*      Calling routine must clear unused flags/processed flags
;*   Port_Old, Byte, contains debounced port status
;*
;*   InitDebouncePort, call at initizilation
;*   DebouncePins, call at regualr intervals (1ms?).
;*      Will set Port_Changed & Port_Old
;*
;* Does not generate an interrupt, but could easily be adapted to do so.
;*
;* Routine reads the specified port, masks out non-input pins, compares to the
;* last-saved-debounced status.  If a change is detected, a counter
;* (Debounce_Count) is decremented.  When it hits zero, the port is considered
;* debounced.  More debounce?  Increase InitDebounceCount
;*
;*
;*
;******************************************************************************
;

;*******************************************************************************
; Processor Inclusion
;*******************************************************************************

   #include p18f4580.inc

;*******************************************************************************
; Define Variable Definitions
;
; Refer to datasheet for available data memory (RAM) organization assuming
; relocatible code organization (which is an option in project
; properties > mpasm (Global Options)).  Absolute mode generally should
; be used sparingly.
;
; Example of using GPR Uninitialized Data
;
;   GPR_VAR        UDATA
;   MYVAR1         RES        1      ; User variable linker places
;   MYVAR2         RES        1      ; User variable linker places
;   MYVAR3         RES        1      ; User variable linker places
;
;   ; Example of using Access Uninitialized Data Section (when available)
;   ; The variables for the context saving in the device datasheet may need
;   ; memory reserved here.
;   INT_VAR        UDATA_ACS
;   W_TEMP         RES        1      ; w register for context saving (ACCESS)
;   STATUS_TEMP    RES        1      ; status used for context saving
;   BSR_TEMP       RES        1      ; bank select used for ISR context saving
;
;*******************************************************************************

    UDATA_ACS
Port_Old		RES	1
Port_New		RES	1
Port_Changed	RES	1
Debounce_Count	RES	1

;*******************************************************************************
;* Defines
;*******************************************************************************
;#define	FOSC	8000000
#define  PortInput 	PORTB
#define  TRISInput  TRISB
#define  PinsInput	0x0F    ; Lower Nibble
#define	 InitDebounceCount	4  ;# of iterations switch needs to be stable

; TODO PLACE ASSEMBLER VARIABLE DEFINITIONS HERE
; cCLOCK  set  8000000        ;Clock Speed

;*******************************************************************************
; "Exposed" sub routine elements (variables & code)
; GLOBAL is used to make a lable visible to other files.
; EXTERN must be used in the file that uses (calls) the lable to make it visible
;*******************************************************************************

; These routines are exposed by SwitchDebouncePort.asm
    global Port_Changed, Port_Old        ;, VARIABLE2
    global InitDebouncePort, DebouncePins;, routine1, routine2, routine3, routine4

; To be copied into Calling Routine
;    ; These routines are in SwitchDebouncePort.asm
;    extern Port_Changed, Port_Old
;    extern InitDebouncePort, DebouncePins

;*******************************************************************************
;* Macros
;*******************************************************************************
;*
;* Enable & Disable Macros
mEnableGI   macro
    BANKSEL INTCON
    BSF     INTCON, GIE
    endm
mDisableGI  macro
    BANKSEL INTCON
    BCF      INTCON, GIE
    endm


;*******************************************************************************
;* Initilization Code Section
;*******************************************************************************
DebounceCode CODE

InitDebouncePort	                         ;Called at boot time

; Set PortInput for input

	MOVLW	PinsInput                              	; pins for input
	MOVWF	TRISInput

; Init "holder" bytes
        	MOVFF	PortInput, Port_Old
	MOVLW	PinsInput	                            ; mask 'zeros'
	ANDWF	Port_Old, f
	CLRF	Port_New
	CLRF	Port_Changed
        MOVLW   InitDebounceCount
        MOVWF   Debounce_Count

	Return

;*******************************************************************************
;* Main Code Section
;*******************************************************************************
DebouncePins
; Read input port, mask unused bits, save into "Port_New"
    	MOVFF	    PortInput, Port_New
    	MOVLW	    PinsInput	                        ; mask 'zeros'
    	ANDWF	    Port_New, f

; XOR Port_New with Port_Old
    	MOVF	     Port_New, w
	    XORWF    	Port_Old, w
    	BTFSC    	STATUS, Z
    	GOTO	     ResetDebounce

; Decrement Debounce_Count
    DECFSZ   Debounce_Count, 1
    RETURN                 ; Not debounced yet, get outta here

; Move Port_New into Port_Old
    	MOVFF   Port_New, Port_Old
; Move W to Port_Changed
    	MOVWF   Port_Changed

ResetDebounce
    	MOVLW    	InitDebounceCount
    	MOVWF    	Debounce_Count
    Return

	END