title "Bounce4 - Debounce the Button input with Interrupt." ; ; This Code Simply Lights an LED and polls a button and toggles ; the state of another LED when it is pressed (and debounced). ; ; This is an update to the original interrupt driven debounce in ; that the button interrupt is working continuously and updates ; two bits of a "flag" register. ; ; ; Hardware Notes: ; Reset is tied directly to Vcc and PWRT is Enabled. ; The PIC is a 16F84 Running at any speed. ; PortB.0 is Connected to a Button that pulls down to Ground when Pressed ; PortB.1 is Connected to an LED which is Pulled to Ground ("On" LED) ; PortB.2 is Connected to an LED which is Pulled to Ground ("Button" LED) ; ; Myke Predko ; 99.06.15 ; LIST P=16F84, R=DEC errorlevel 0,-305 INCLUDE "p16f84.inc" ; Register Usage CBLOCK 0x00C ; Start Registers at End of the Values _w, _status ; State Save Variables flags ; State Register for Button State ENDC #define Button PORTB,0 ; Define the "Button" Pin #define Debugt ; Use "Debug" To Reduce Polling Loops #define Lo flags,0 ; Bit 0 Set when #define Hi flags,1 ; Macros PAGE __CONFIG _CP_OFF & _XT_OSC & _PWRTE_ON & _WDT_OFF ; Note that the WatchDog Timer is OFF ; Bounce - Turn on LED and poll the Button to toggle another LED. org 0 goto MainLine ; Skip Over the Interrupt Handler ; Interrupt Handler org 4 Int ; Depending on Interrupt movwf _w ; Save the Context Registers movf STATUS, w movwf _status movlw 256 - 0x09C ; Reset the Timer to Overflow in 20 msec movwf TMR0 btfss INTCON, INTF ; Button Low Received goto IntTimerOF ; Else, Overflow - Button Pressed IntTMR0Reset ; Reset the Interrupt OverFlow Timer bcf INTCON, INTF ; Reset the Interrupts bsf STATUS, RP0 ; Toggle the Interrupt Edge Bit movlw 0x040 xorwf OPTION_REG ^ 0x080 bcf STATUS, RP0 bcf Lo ; Neither Flag is Valid Yet bcf Hi goto IntEnd IntTimerOF ; Overflow - Debounce Completed bcf INTCON, T0IF ; Reset the Timer Interrupt bsf Lo ; Assume "Lo" is True bcf Hi movlw 1 ; If "Hi" is True, Add to the flags btfsc Button addwf flags ; Button is Hi IntEnd movf _status, w ; Restore Interrupt Registers before Return movwf STATUS swapf _w swapf _w, w retfie ; Return from Interrupt ; Bounce3 Mainline MainLine bcf Lo ; Reset the Button Flags bcf Hi movlw 0x0FD ; Turn on LED on RB1 When Output Enabled movwf PORTB movlw 0x016 ; Set up a 20 msec delay with Internal Pull-Ups Active ; Edge of RB0 and the Internal Clock ; TMR0 Source ; Prescaler Assigned to Interrupt ; Handler with an 8x Delay btfss PORTB, 0 ; If Button Line is Low, Set Low to High Transition iorlw 0x040 bsf STATUS, RP0 bcf TRISB ^ 0x080, 1 ; Enable RB1 for Output bcf TRISB ^ 0x080, 2 ; Enable RB2 for Output ifdef Debug andlw 0x0F8 ; Debug Delay (2x Only) endif movwf OPTION_REG ^ 0x080 ; Along with Interrupts on the Falling bcf STATUS, RP0 movlw 256 - 0x09C ; Reset the Timer to Overflow in 20 msec movwf TMR0 movlw 0x0B0 ; Enable Interrupts movwf INTCON Loop btfss Hi ; Wait for the Button to go high goto $ - 1 btfss Lo ; Wait for the Button to go low goto $ - 1 btfsc PORTB, 2 ; Is the Button Pressed? goto ButtonUp ; No, Light Off bsf PORTB, 2 ; Turn Light On goto Loop ButtonUp ; Button Up, Turn Light Off bcf PORTB, 2 goto Loop end