; Lesson13b.asm - Introduction of state variables ; ; Blink one or another LED, toggle when PB1 pressed ; ; WB8RCR - 3-Mar-04 ; ;===================================================================== processor pic16f84a include "p16f84a.inc" __config _XT_OSC & _WDT_OFF & _PWRTE_ON list b=4,n=70 ;===================================================================== ; Manifest Constants ;===================================================================== LED1M equ B'00001000' ; PORTB pin for LED LED2M equ B'00000100' ; PORTB pin for LED PB1 equ H'04' ; PORTA pin for PB1 HZ5TIME equ D'49' ; Clock ticks for 5/sec HZ2TIME equ D'122' ; Clock ticks for 2/sec HZNTIME equ D'12' ; Clock ticks for 20/sec ;===================================================================== ; File register use ;===================================================================== cblock H'20' Hz2Cnt ; Twice per second counter Hz5Cnt ; 5 times per second counter HzNCnt ; 20 times per second counter Outputs ; Output storage Inputs ; Input storage PBstate ; What state is PB? LEDstate ; Which LED flashing? endc goto start ;===================================================================== ; Subroutines ;===================================================================== SendOut movf Outputs,W ; Pick up the output word movwf PORTB ; And send it to the world return ;===================================================================== ; Time domains ;===================================================================== ;--------------------------------------------------------------------- ; Twenty times per second code ;--------------------------------------------------------------------- HzN ; Get inputs movf PORTA,W movwf Inputs ; Check button state btfss PBstate,PB1 ; Was button down? goto wasDown ; Yes wasUp btfsc Inputs,PB1 ; Is button still up? return ; Was up and still up, do nothing bcf PBstate,PB1 ; Was up, remember now down return wasDown btfss Inputs,PB1 ; If it is still down return ; Was down and still down, do nothing bsf PBstate,PB1 ; remember released ; Button was down and now it's up, ; we need to flip LEDstate movlw H'01' ; Toggle LSB of LED xorwf LEDstate,F ; state movlw B'00001110' ; Turn off all LEDs movwf Outputs return ;--------------------------------------------------------------------- ; Five times per second code ;--------------------------------------------------------------------- Hz5 ; Check whether we are doing this btfss LEDstate,0 ; Is LEDstate:0 = 0? return ; Yes, return movlw LED1M ; Toggle LED1 state xorwf Outputs,F ; call SendOut ; Set outputs return ;--------------------------------------------------------------------- ; Two times per second code ;--------------------------------------------------------------------- Hz2 ; Check whether we are doing this btfsc LEDstate,0 ; Is LEDstate:0 = 0? return ; No, return movlw LED2M ; Toggle LED2 state xorwf Outputs,F ; call SendOut ; Set outputs return ;===================================================================== ; Mailine begins here -- Initialization ;===================================================================== start ;--------------------------------------------------------------------- ; Set up timer ;--------------------------------------------------------------------- errorlevel -302 banksel INTCON bcf INTCON,T0IE ; Mask timer interrupt ; Normally, we would have simply loaded a constant, but the ; code below makes it explicit what we are doing banksel OPTION_REG bcf OPTION_REG,T0CS ; Select timer bcf OPTION_REG,PSA ; Prescaler to timer bcf OPTION_REG,PS2 ; \ bsf OPTION_REG,PS1 ; >- 1:16 prescale bsf OPTION_REG,PS0 ; / ;--------------------------------------------------------------------- ; Set up I/O ;--------------------------------------------------------------------- banksel TRISB clrw ; movwf TRISB ; Make all port B output banksel PORTA errorlevel +302 ;--------------------------------------------------------------------- ; Initialize memory ;--------------------------------------------------------------------- movlw B'00001110' ; Initially set all LEDs movwf Outputs ; to off movwf PORTB movlw H'00' ; Initialize LED state movwf LEDstate movlw B'00010000' ; and pushbutton state movwf PBstate movlw HZ5TIME ; Initialize the counters movwf Hz5Cnt ; for the three time domains movlw HZ2TIME movwf Hz2Cnt movlw HZNTIME movwf HzNCnt ;===================================================================== ; Main program loop here ;===================================================================== main btfss INTCON,T0IF ; Did timer overflow? goto main ; No, hang around some more bcf INTCON,T0IF ; reset overflow flag ;--------------------------------------------------------------------- ; Check for twenty times per second ;--------------------------------------------------------------------- decfsz HzNCnt,F ; Count down until HzN goto $+4 ; Not time yet movlw HZNTIME ; Reset the counter so movwf HzNCnt ; it's available next time call HzN ; Go do 20X per second code ;--------------------------------------------------------------------- ; Check for five times per second ;--------------------------------------------------------------------- decfsz Hz5Cnt,F ; Count down until Hz5 goto $+4 ; Not time yet movlw HZ5TIME ; Reset the counter so movwf Hz5Cnt ; it's available next time call Hz5 ; Go do 5X per second code ;--------------------------------------------------------------------- ; Check for two times per second ;--------------------------------------------------------------------- decfsz Hz2Cnt,F ; Count down until Hz2 goto $+4 ; Not time yet movlw HZ2TIME ; Reset the counter so movwf Hz2Cnt ; it's available next time call Hz2 ; Go do twice per second code goto main end