PROGRAM Q ;*************************************** ; written by: John Morton * ; date: 14/03/05 * ; version: 1.0 * ; file saved as: gardenlights.asm * ; for PIC12F675 * ; clock frequency: Int. 4 MHz * ; *************************************** ; Program Description: Intelligent garden lights controller list P=12F675 include "c:\pic\P12F675.inc" __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _BODEN_ON & _CP_OFF & _CPD_OFF Midnight equ 20 Threshold equ 21 Mark125 equ 22 Post125 equ 23 Post75 equ 24 FiveMins equ 25 W_temp equ 26 STATUS_temp equ27 #define summer GPIO, 1 ;============== ; Declarations: org 0 ; first instruction to be executed goto Start ; org 4 ; interrupt service routine goto isr ; ;=========== ; Subroutines: Init bsf STATUS, RP0 ; goes to Bank 1 movlw b'001111' ; GP5: lights, GP4: day/night LED movwf TRISIO ; GP3: button, GP2: summer switch ; GP0: analogue input clrf WPU ; no weak pull-ups movlw b'10000111' ; pull-ups disabled, TMR0 prescaled movwf OPTION_REG ; by maximum amount (256) clrf PIE1 ; turns off peripheral interrupts clrf IOC ; turns off interrupt on change int. clrf VRCON ; turns off comparator V. ref. movlw bÕ00110001Õ ; AN0 is only analogue input movwf ANSEL ; and analogue clock = RC call 3FFh ; calls calibration address movwf OSCCAL ; moves w. reg into OSCCAL bcf STATUS, RP0 ; back to Bank 0 movlw b'00000111' ; turns off comparator movwf CMCON ; clrf T1CON ; turns off TMR1 movlw b'00000001' ; turns on ADC, input: AN0 movwf ADCON0 ; left justified clrf GPIO ; lights off, ÔdayÕ LED on movlw b'00010000' ; enables INT interrupt only movwf INTCON ; retfie ; returns, enabling interrupts ;======================================== isr movwf W_temp ; stores w.reg in temp register movfw STATUS ; stores STATUS in temporary movwf STATUS_temp ; register bcf INTCON, 1 ; resets interrupt flag movfw GPIO ; xorlw b'100000' ; toggles state of lights movwf GPIO ; movfw STATUS_temp ; restores STATUS register to movwf STATUS ; original value swapf W_temp, f ; restores working register to swapf W_temp, w ; original value retfie ; ;=================================== ADconv bsf ADCON0, 1 ; starts AD conversion btfsc ADCON0, 1 ; has it finished? goto ADconv+1 ; no return ; ;================================== Delay5min movfw TMR0 ; resets timing registers addlw d'125' ; movwf Mark125 ; movlw d'125' ; sets up timing registers movwf Post125 ; movlw d'75' ; movwf Post75 ; TimeLoop movfw Mark125 ; creates a five minute delay subwf TMR0, w ; btfss STATUS, Z ; goto TimeLoop ; movlw d'125' ; addwf Mark125,f ; decfsz Post125, f ; goto TimeLoop ; movlw d'125Õ ; movwf Post125 ; decfsz Post75, f ; goto TimeLoop ; return ; 5 minutes have passed ;================================= ; Program Start Start call Init ; initialisation routine bsf STATUS, RP0 ; Bank 1 btfsc PCON, 1 ; Power-Up or MCLR reset? goto SetThreshold ; MCLR reset bsf PCON, 1 ; Power-up; resets POR bit clrf EEADR ; bsf EECON1, 0 ; reads EEPROM address 0 movfw EEDATA ; moves read data into w. reg movwf Midnight ; incf EEADR ; bsf EECON1, 0 ; reads EEPROM address 1 movfw EEDATA ; bcf STATUS, RP0 ; Bank 0 movwf Threshold ; goto Main ; SetThreshold bcf STATUS, RP0 ; Bank 0 call ADconv ; perform A/D conversion movfw ADRESH ; takes 8 most significant bits movwf Threshold ; bsf STATUS, RP0 ; Bank 1 movwf EEDATA ; stores Threshold in EEPROM movlw 1 ; selects EEPROM address 1 movwf EEADR ; bsf EECON1, 2 ; enables a write operation bcf INTCON, 7 ; disables global interrupts movlw 0x55 ; now follows the Ôsafe movwf EECON2 ; combinationÕ movlw 0xAA ; movwf EECON2 ; bsf EECON1, 1 ; starts the write operation EELoop btfsc EECON1, 1 ; has write operation finished? goto EELoop ; no, so keeps looping bcf STATUS, RP0 ; Bank 0 bsf INTCON, 7 ; re-enables global interrupts clrf Midnight ; resets Midnight register goto Dusk ; ;========================================== Main call ADconv ; this is the standard loop movfw Threshold ; is it Dusk? subwf ADRESH, w ; btfsc STATUS, C ; goto Main ; no ;==== Dusk clrf FiveMins ; resets timing register movlw bÕ110000 ; turns on garden lights and movwf GPIO ; ÔnightÕ LED Night call Delay5min ; inserts 5 minute delay incf FiveMins ; counts up no. of 5 minutes movlw d'12' ; has 1 hour passed? subwf FiveMins, w ; btfss STATUS, C ; goto Night ; no movfw Midnight ; is it past midnight? subwf FiveMins,w ; btfss STATUS, C ; goto Night ; no LightsOff movlw bÕ010000 ; turns off garden lights and movwf GPIO ; keeps ÔnightÕ LED on call ADconv ; performs A/D conversion movfw Threshold ; is it Dawn? subwf ADRESH, w ; btfss STATUS, C ; goto Night ; no ;==== Dawn bsf day ; turns on 'day' LED ; determines new midnight bcf STATUS, C ; rrf FiveMins, w ; divides time by 2 btfss summer ; are we in summer time? sublw d'24' ; yes, subtracts 2 hours movwf Midnight ; bsf STATUS, RP0 ; Bank 1 movwf EEDATA ; stores Midnight in EEDATA clrf EEADR ; selects EEPROM address 00 bsf EECON1, 2 ; enables a write operation bcf INTCON, 7 ; disables global interrupts movlw 0x55 ; now follows the Ôsafe movwf EECON2 ; combinationÕ movlw 0xAA ; movwf EECON2 ; bsf EECON1, 1 ; starts the write operation EELoop2 btfsc EECON1, 1 ; has write operation finished? goto EELoop2 ; no, so keeps looping bcf STATUS, RP0 ; Bank 0 bsf INTCON, 7 ; re-enables global interrupts clrf FiveMins ; DawnLoop call Delay5min ; one hour delay before looping back incf FiveMins ; movlw d'12' ; has one hour passed? subwf FiveMins, w ; btfss STATUS, C ; goto DawnLoop ; no goto Main ; END