title "Bounce5 - Debounce the Port Change Buttons." ; ; This Code Monitors the Pins on RB4 and RB5 and uses the switches ; on them to turn on and off the LED. ; ; This is an update to the original interrupt driven debounce in ; that the button interrupt is working continuously and updates ; two bits of a "flagHi" and "flagLo" register. ; ; ; Hardware Notes: ; Reset is tied directly to Vcc and PWRT is Enabled. ; The PIC is a 16F84 Running at any speed. ; PortB.4 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.17 ; 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 flagHi, flagLo ; Button State Registers for High/Low Pins PORTBState ; Current State of PORTB Register ENDC #define Lo flagLo, 4 ; Define the "Down" Button #define Hi flagHi, 4 ; Define the "Up" Button #define Debugt ; Use "Debug" To Reduce Polling Loops ; 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, RBIF ; Button Low Received goto IntTimerOF ; Else, Overflow - Button Pressed IntTMR0Reset ; Reset the Interrupt OverFlow Timer movf PORTB, w ; PORTB Read To Reset Interrupt Requests bcf INTCON, RBIF ; Reset the Interrupts clrf flagLo ; Reset the Flags Registers clrf flagHi goto IntEnd IntTimerOF ; Overflow - Debounce Completed bcf INTCON, T0IF ; Reset the Timer Interrupt movf PORTB, w ; Get the current Button State xorlw 0x0F0 andlw 0x0F0 movwf flagLo ; Save the Current Low Values movf PORTB, w ; Save the Current High Values andlw 0x0F0 movwf flagHi IntEnd movf _status, w ; Restore Interrupt Registers before Return movwf STATUS swapf _w swapf _w, w retfie ; Return from Interrupt ; Bounce3 Mainline MainLine movlw 0x0FD ; Turn on LED on RB1 When Output Enabled movwf PORTB movwf PORTBState clrf flagHi ; Clear the Flags Registers clrf flagLo 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 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 0x0A8 ; Enable TMR0 Interrupt and RBIE Interrupt 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 PORTBState, 2 ; Is the Button Pressed? goto ButtonUp ; No, Light Off bsf PORTBState, 2 bsf PORTB, 2 ; Turn Light On goto Loop ButtonUp ; Button Up, Turn Light Off bcf PORTBState, 2 bcf PORTB, 2 goto Loop end