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