Myke's Home Page

Book CD-ROM Home

File Copying/Harddrive Setup

Development Tools

Experiments

Projects

Useful Code Snippets and Macros

Introduction to Electronics

Introduction to Programming

Datasheets

PCBs

Links

McGraw-Hill Professional Publishing

"Debounce" Experiment

Any time a switch is closed, the contacts will "bounce", which may be interpreted by the PICmicro® MCU as multiple button presses or key closures. There are many different ways to "debounce" an input, in this experiment, I demonstrate how to implement it using a polling loop. The circuit is identical to the one used by "LEDOn":

The parts needed for this experiment are listed in the table:

Part Description Required for the YAP-II/EMU-II?
PICmicro® MCU PIC16F84-04/P
PIC16F877-04/P
In Socket
Vdd/Vss Decoupling Capacitor 0.1 uF (Any Type) No
_MCLR Pull Up Resistor 10K, 1/4 Watt No
4 MHz Ceramic Resonator Three Leaded Ceramic Resonator with Built in 27-33pF Capacitors No
RA0 Pull Up 10K, 1/4 Watt No - "BUT1" Used
RA0 Push Button Momentary On/Modified for Breadboard No - "BUT1" Used
RB0 LED Current Limiting Resistor 220W, 1/4 Watt No - "LED1" Used
RB0 LED Any Type No - "LED1" Used
Breadboard Any Type No
+5 Volt "Vcc" Power Supply Any Type No

Using a breadboard, the experiment is wired using the guide:

If the EMU-II or YAP-II is used, the experiment is wired as:

The debounce operation can be modeled as the "C" pseudo-code:

Debounce_Down:                //  Wait for the Switch to be held down 
                              //   for 20 msec
  while (Switch == Up);       //  Wait for the Switch to go down

  for (Dlay = 0; (Switch == Down) && (Dlay < 20msec); Dlay++);
                              //  Poll the Switch while Incrementing 
                              //   the Delay Timer
  if (Dlay < 20msec)
    goto Debounce_Down;       //  If 20 msecs has NOT passed, wait for 
                              //   Switch Down and Repeat Process

//  When Execution reaches here, the switch is "Down" and Debounced
              

and was converted into the macro:

Debounce MACRO Port, Pin, Direction

 if (Direction < 0)           ;  Going Down
  btfsc  Port, Pin
 else
  btfss  Port, Pin            ;  Wait for Button Released
 endif
   goto  $ - 1

  movlw  0x0100 - 0x0C4       ;  Initialize Dlay for a 20 msec
  movwf  Dlay                 ;   Delay
  movlw  0x0100 - 0x00A
  movwf  Dlay + 1

  bcf    STATUS, Z            ;  Make Sure that Zero is Reset

  incfsz Dlay, f
   goto  $ + 2
  incf   Dlay + 1, f
 if (Direction < 0)
  btfsc  Port, Pin
 else
  btfss  Port, Pin            ;  Button Still Released?
 endif
   goto  $ - 11               ;  No - Loop Around Again
  btfss  STATUS, Z            ;  Zero Flag Set (20 mSecs Past?)
   goto  $ - 6

 ENDM                         ;  End the Macro
              

The source code listed below can be accessed from the CD-ROM by clicking Here.

 title  "debounce - Debounce Button input and Toggle LED"
;
;  This Application waits for the button on RA0 to be released 
;   (for more than 20 msecs) and then when it has been pressed and
;   stays constant for 20 msecs, the LED on RB0 is toggled.  The 
;   Process then repeats.
;
;  Hardware Notes:
;   _MCLR is tied through a 4.7K Resistor to Vcc and PWRT is Enabled
;   A 220 Ohm Resistor and LED is attached to PORTB.0 and Vcc
;   A 10K pull up is connected to RA0 and it's state is passed to 
;    RB0
;
;  Myke Predko
;  99.12.04
;
  LIST R=DEC
 ifdef __16F84
  INCLUDE "p16f84.inc"
 else
 ifdef __16F877
  INCLUDE "p16f877.inc"
 endif

;  Registers
 CBLOCK 0x020
Dlay:2                        ;  Delay Value
 ENDC

Up   EQU 1                    ;  Flag Value for Debounce "Up"
Down EQU -1                   ;  Flag Value for Debounce "Down"

;  Macros
Debounce MACRO Direction

 if (Direction < 0)           ;  Going Down
  btfsc  PORTA, 0
 else
  btfss  PORTA, 0             ;  Wait for Button Released
 endif
   goto  $ - 1

  movlw  0x0100 - 0x0C4       ;  Initialize Dlay for a 20 msec
  movwf  Dlay                 ;   Delay
  movlw  0x0100 - 0x00A
  movwf  Dlay + 1

  bcf    STATUS, Z            ;  Make Sure that Zero is Reset

  incfsz Dlay, f
   goto  $ + 2
  incf   Dlay + 1, f
 if (Direction < 0)
  btfsc  PORTA, 0
 else
  btfss  PORTA, 0             ;  Button Still Released?
 endif
   goto  $ - 11               ;  No - Loop Around Again
  btfss  STATUS, Z            ;  Zero Flag Set (20 mSecs Past?)
   goto  $ - 6

 ENDM                         ;  End the Macro


 ifdef __16F84
 __CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
 else
 __CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON & _DEBUG_OFF & _LVP_OFF & _BODEN_OFF
 endif

  PAGE
;  Mainline of ledon

 org     0

  nop

  bsf    PORTB, 0             ;  Make LED on RB0 "off" Initially

  bsf    STATUS, RP0          ;  Goto Bank 1 to set Port Direction
  bcf    TRISB & 0x07F, 0     ;  Set RB0 to Output
  bcf    STATUS, RP0          ;  Go back to Bank 0

Loop                          ;  Loop Here
 
 Debounce Up                  ;  Wait for Key to Go Up

  nop                         ;  Location for Stopping after
                              ;   "Up" Debounce
 Debounce Down                ;  Wait for Key to Go Down

  comf   PORTB, f             ;  Toggle the PORTB Value

  goto   Loop


 end
              

Click Here to look at the twenty first experiment - PinChg