;Programme function - Operate a relay & release it after 1, 2, 3 or 4 hours.
;The timing is set by a rotary switch. Switch changes are detected by the
; RB change interrupt function & cause the timer to restart from 0.
;Oscillator frequency = 32.768 kHz, Instruction rate = 32768/4 = 8192 Hz.
;TMR0 prescale = 256, so the frequency input to the TMR0 is 8192/256 = 32 Hz.
;If TMR0 is set to the complement of 16 (decimal) then it will overflow after
; approx 16/32 = 0.5 seconds.
;If TMR0 is set to the complement of 128, it will overflow after 128/32 = 4 sec.
LIST P=PIC16F84, F=INHX8M
include "p16f84.inc"
__CONFIG 0x3FF0 ;32.768 kHz Crystal Oscillator, WDT off, Power up reset on
porta equ 05 ;input/output pins RA0 ~ RA4
portb equ 06 ;input/output pins RB0 ~ RB7
cblock 0x10
count1 ;minutes counter (4 sec increments)
count2 ;hours counter (60 sec increments)
temp
endc
#define relay portb, 0 ;relay connected to RB0
#define tmr0_of INTCON, 2 ;TMR0 overflow flag
#define sw_ch INTCON, 0 ;switch change (RB change flag)
ORG 0x00 ;set programme counter to 0
call init
bsf relay ;operate relay
restart ;Starts from here after a switch change is detected
bcf sw_ch ;clear RB change flag
call delay_500m ;call 0.5 second delay to allow switch contacts to settle
movlw d'240' ;4 hour
btfsc portb, 4 ;is rb4 high?
movlw d'60' ;1 hour
btfsc portb, 5 ;is rb5 high?
movlw d'120' ;2 hour
btfsc portb, 6 ;is rb6 high?
movlw d'180' ;3 hour
movwf count2 ;count2 = 60, 120, 180 or 240
;the code below uses count1 & count2 to determine the relay on time.
loopb
movlw d'15'
movwf count1 ;4 sec * 15 = 1 minute
loopa
call delay_4s
btfsc sw_ch ;has a switch changed?
goto restart ;yes - restart to determine the new time setting
decfsz count1 ;decrement count1 by 1, skip if 0
goto loopa ;count1 is not 0, so repeat
decfsz count2 ;count1 is 0 , so decrement count2
goto loopb ;count2 is not 0, so repeat
bcf relay ;count2 is 0, so release relay
sleep ;PIC goes into low power mode & does nothing
NOP
;sub routines
delay_4s
movlw d'127' ;4 second delay @ 32.768 kHz
goto $+2
delay_500m
movlw d'15' ;0.5 second delay @ 32.768 kHz
movwf temp
comf temp, w
movwf TMR0
bcf tmr0_of
btfsc sw_ch ;has a switch changed?
return ;yes - exit loop
btfss tmr0_of ;await TMR0 overflow
goto $-1
return
init
bsf STATUS, 5 ;selects BANK 1
clrf TRISA ;make RA0:4 outputs
movlw b'01110000'
movwf TRISB ;RB0:3,7 outputs RB4:6 inputs
movlw b'10000111' ;sets prescaler to 256, internal clock
movwf OPTION_REG
bcf STATUS,5 ;selects bank 0
clrf INTCON
clrf porta ;clears porta
clrf portb ;clears portb
bsf INTCON, 3 ;RB change enable
bsf INTCON, 5 ;TMR0 overflow enable
return
end