;********************************************************************** ; * ; Filename: PSS2.asm * ; Date: 14-04-2007 * ; File Version: Pump/motor safety switch2 * ; PCB: * ; processor: PIC16F913 * ; SET VELLEMAN PROGRAMMER TO: PIC16F876 * ; * ;********************************************************************** ; NOTES ; ; - When motor current reduces under a threshold, power will be turned off ; - PIC16F913, clock frequency: 4 MHz ,internal clock oscillator ; - Power is turned back on automatically after settable time 1 to 87 hours (if hrs=88 not at all) ; - Trip-current can be set from 1,0 to 9,0 Amps ; - Display shows current/and can also show setpoint of current /auto resettime in hours ; - udelay calibrated to 100 usec (4 MHz) ; - WDT enabled ; ;LOOKUP index (in w), table ; Finds the table entry corresponding to index (in w) and ; returns it in w. to patterns on a seven-segment LED ; display. It assumes that the display is connected with segment ; a to rb.0, b to rb.1... and g to rb.6 through current-limiting ; resistors of 1K ohms. ; PIC ports used: ; ; RC0-7 outputs: drives Display 7 segments and point ; RC3 = point ; RC5 = a ; RC4 = b ; RC2 = c ; RC1 = d ; RC0 = e ; RC6 = f ; RC7 = g ; RA1 = relais ; RA6 output: common cathode of MSB display ; RA7 output: common cathode of LSB display ; RB1 LED1 green "power to motor" ; RB3 LED2 red "set tripcurrent" ; RA0 LED3 red "set autoresettime" ; inputs: ; RA5/AN4 = analog input ; RB5 = key "up" ; RB7 = key "set" ; RB6 = key "down" ; RB4 = key "reset" ;********************************************************************** list p=16f913 #include "p16f913.inc" ;#include ;; #include ;#include ; #include "picmac1.inc" __CONFIG _DEBUG_OFF & _FCMEN_OFF & _IESO_OFF & _BOD_ON & _CPD_OFF & _CP_OFF & _PWRTE_ON & _WDT_ON & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT ;; __CONFIG 3BCC cblock 0x20 ; start of general purpose registers FLAG_SETKEY FLAG_RESETKEY halfsecs secs mins hours STATUS_TEMP W_TEMP VALUE ; to get value from table CURRENT ; measured ADC value for current CURRENTdec ; value transformed to decimal CURRENTdecH ; temporary value to calculate MSNvalue CURRENTtemp ; temporary value to calculate SETPOINTCURRENT ; value tripcurrent setpoint count1 ; used in delay routine counta ; used in delay routine countb count Delay_Count keyrepeat ; keynumber tablenumber ; 2 x (number of pushed key) dcnt0 ; delay counter 0 dcnt1 ; delay counter 1 dcnt2 ; delay counter 2 keycode ; matrix-number of pushed key temp ; Variables for delays temp2 ; used in demo subroutines. FLAG_MSNDISPLAY ; If MSBdisplay is multiplexed, this flag is high TIMEFLAG MSNvalue ; value for MSN nuber LSNvalue ; value for LSN number DISPL_VALUE ; temporary value for MSN/LSNVALUE TRIPCURRENT ; value for tripcurrent AUTOTIME ; value for autoresettime in hours SPdec SPdecH speed MSD_POINT_FLAG LSD_POINT_FLAG FLAG_UPKEY FLAG_DOWNKEY TEMPEEDATA TEMPEEADDR endc mhz EQU D'4' ; processor frequency in MHz up EQU 5 ; pushbutton "up" down EQU 6 ; pushbutton "down" setkey EQU 7 ; pushbutton "set" reset EQU 4 ; pushbutton "reset" relais EQU 1 ; output to relais MSD EQU 6 ; output Common cathode MSD LSD EQU 7 ; LSD led1 EQU 1 ; led green "power to motor" led2 EQU 3 ; led red "set tripcurrent" led3 EQU 0 ; led red "set autoresettime" vectors ORG 0x000 goto INIT nop nop nop goto INT_POLL ; at interrupt goto INT_Poll; check where interrupt came from ORG 0x005 ; *************************************************************************** ; ; ; LOOKUP index (in w), table ; Finds the table entry corresponding to index (in w) and ; returns it in w. This demonstration uses a table to map the ; numbers 0 through F hex to patterns on a seven-segment LED ; display. It assumes that the display is connected with segment ; a to rc5, b to rc4, c to rc2, d to rc1, e to rc0, f to rc6, g to rc7 through ; current-limiting resistors of 1k5. Lookup BANKSEL PCLATH movlw HIGH segm_codetable ; get high byte of table data address movwf PCLATH ; and save in PCLATH register movfw DISPL_VALUE segm_codetable addwf PCL,F ; compute goto RETLW d'119' ; 0 a+b+c+d+e+f 32+16+4+2+1+64 = 119 RETLW d'20' ; 1 b+c 16+4 = 20 RETLW d'179' ; 2 a+b+g+e+d 32+16+128+1+2 = 179 RETLW d'182' ; 3 a+b+g+c+d 32+16+128+4+2 = 182 RETLW d'212' ; 4 f+g+b+c 64+128+16+4 = 212 RETLW d'230' ; 5 a+f+g+c+d 32+64+128+4+2 = 230 RETLW d'231' ; 6 a+f+e+d+c+g 32+64+1+2+4+128 = 231 RETLW d'52' ; 7 a+b+c 32+16+4 = 52 RETLW d'247' ; 8 a+b+c+d+e+f+g 32+16+4+2+1+64+128 = 247 RETLW d'246' ; 9 a+b+c+d+f+g 32+16+4+2+64+128 = 246 RETLW d'119' ; A, B, C RETLW d'124' RETLW d'57' RETLW d'94' ; D, E, F RETLW d'121' RETLW d'113' ;*************************************************** ; Lookup table ; Eerst LSB-byte en daarna MSB byte uitlezen ; dus high-byte en low-byte zijn verwisseld ;*************************************************** get BANKSEL PCLATH movlw HIGH table ; get high byte of table data address movwf PCLATH ; and save in PCLATH register movfw VALUE ; get current addwf PCL,F ; compute goto ; Amps/time on display table dt H'00' ; 0.0 dt H'01' ; 0.1 dt H'02' ; 0.2 dt H'03' ; 0.3 dt H'04' ; 0.4 dt H'05' ; 0.5 dt H'06' ; 0.6 dt H'07' ; 0.7 dt H'08' ; 0.8 dt H'09' ; 0.9 dt H'10' ; 1.0 dt H'11' ; 1.1 dt H'12' ; 1.2 dt H'13' ; 1.3 dt H'14' ; 1.4 dt H'15' ; 1.5 dt H'16' ; 1.6 dt H'17' ; 1.7 dt H'18' ; 1.8 dt H'19' ; 1.9 dt H'20' ; 2.0 dt H'21' ; 2.1 dt H'22' ; 2.2 dt H'23' ; 2.3 dt H'24' ; 2.4 dt H'25' ; 2.5 dt H'26' ; 2.6 dt H'27' ; 2.7 dt H'28' ; 2.8 dt H'29' ; 2.9 dt H'30' ; 3.0 dt H'31' ; 3.1 dt H'32' ; 3.2 dt H'33' ; 3.3 dt H'34' ; 3.4 dt H'35' ; 3.5 dt H'36' ; 3.6 dt H'37' ; 3.7 dt H'38' ; 3.8 dt H'39' ; 3.9 dt H'40' ; 4.0 dt H'41' ; 4.1 dt H'42' ; 4.2 dt H'43' ; 4.3 dt H'44' ; 4.4 dt H'45' ; 4.5 dt H'46' ; 4.6 dt H'47' ; 4.7 dt H'48' ; 4.8 dt H'49' ; 4.9 dt H'50' ; 5.0 dt H'51' ; 5.1 dt H'52' ; 5.2 dt H'53' ; 5.3 dt H'54' ; 5.4 dt H'55' ; 5.5 dt H'56' ; 5.6 dt H'57' ; 5.7 dt H'58' ; 5.8 dt H'59' ; 5.9 dt H'60' ; 6.0 dt H'61' ; 6.1 dt H'62' ; 6.2 dt H'63' ; 6.3 dt H'64' ; 6.4 dt H'65' ; 6.5 dt H'66' ; 6.6 dt H'67' ; 6.7 dt H'68' ; 6.8 dt H'69' ; 6.9 dt H'70' ; 7.0 dt H'71' ; 7.1 dt H'72' ; 7.2 dt H'73' ; 7.3 dt H'74' ; 7.4 dt H'75' ; 7.5 dt H'76' ; 7.6 dt H'77' ; 7.7 dt H'78' ; 7.8 dt H'79' ; 7.9 dt H'80' ; 8.0 dt H'81' ; 8.1 dt H'82' ; 8.2 dt H'83' ; 8.3 dt H'84' ; 8.4 dt H'85' ; 8.5 dt H'86' ; 8.6 dt H'87' ; 8.7 dt H'88' ; 8.8 dt H'89' ; 8.9 dt H'90' ; 9.0 dt H'91' ; 9.1 dt H'92' ; 9.2 dt H'93' ; 9.3 dt H'94' ; 9.4 dt H'95' ; 9.5 dt H'96' ; 9.6 dt H'97' ; 9.7 dt H'98' ; 9.8 dt H'99' ; 9.9 ;;; ORG 0x100 ;**************************************************************** INIT ; initialisation starts here movlw OSCCON movwf FSR movlw b'11100111' ; internal oscillator, 4 MHz movwf INDF movlw T1CON ; movwf FSR ; movlw b'00110000' ; timer 1 OFF, prescaler 1:8 movwf INDF ; movlw PORTB movwf FSR movlw b'00000000' ; movwf INDF movlw T2CON ; Timer 2 off movwf FSR ; clrw movwf INDF ; movlw TRISA ; port A movwf FSR ; all movlw b'00100000' ; out- movwf INDF ; puts exept RA5 movlw TRISB movwf FSR movlw 0xF0 ; pb4-7 inputs movwf INDF movlw TRISC movwf FSR movlw 0x00 ; pc0-7 output 7 segments and point movwf INDF clrwdt BCF STATUS,RP0 ;Bank 0 BCF STATUS,RP1 ; CLRF PORTA ;Init PORTA BSF STATUS,RP0 ;Bank 1 BCF STATUS,RP1 ; MOVLW 07h ;Set RA<2:0> to MOVWF CMCON0 ;digital I/O CLRF ANSEL ;Make all PORTA I/O MOVLW b'00100000' ;Set RA<7:4> as inputs MOVWF TRISA ;and set RA<3:0> ; as outputs BCF STATUS,RP0 ;Bank 0 BCF STATUS,RP1 ; MOVLW 0x20 ;initialize pointer MOVWF FSR ;to RAM NEXT CLRF INDF ;clear INDF register INCF FSR,f ;inc pointer BTFSS FSR,5 ;all done? GOTO NEXT ;no clear next CONTINUE ;yes continue movlw OPTION_REG ; internal pullups on port A/B enabled ; must be done before changing PSA movwf FSR ; prescaler assigned to timer0 ; prescaler to timer0 movlw b'00000100' ; ; 1:32 movwf INDF ; timer 0 = timer BANKSEL LCDCON clrw movwf LCDCON movlw ADCON1 movwf FSR movlw b'00010000' ; set ADC clock to movwf INDF ; Fosc/8 (clockfreq = 4 MHz) BANKSEL WDTCON movlw b'00010111' ; enable WDT; 1:65536 ( 2 sec?) movwf WDTCON movlw PIE1 movwf FSR movlw b'00000001' ; enable timer1 interrupts movwf INDF movlw PIE2 movwf FSR movlw b'00000000' ; movwf INDF movlw PIR1 movwf FSR movlw b'00000000' ; all flags 0 movwf INDF movlw PIR2 movwf FSR movlw b'00000000' ; all flags 0 movwf INDF BANKSEL ANSEL movlw b'00010000' ; set AN4 to analog input movwf ANSEL movlw WPUB movwf FSR movlw b'11110000' ; PORTB4-7 movwf INDF ; pull-ups on movlw IOCB movwf FSR movlw b'00000000' ; DIS enable PORTB4-7 interrupt movwf INDF ; on change bcf INTCON,RBIF BANKSEL T1CON bsf T1CON, TMR1ON ; start timer1 ;;;;;; bsf INTCON,RBIE ; enable RB port change interrupt bsf INTCON,T0IE ; enable timer0 interrupt bsf INTCON,PEIE ; enable perifere interrupts bsf INTCON,GIE ; enable global interrupts clrf FLAG_SETKEY clrf FLAG_RESETKEY clrf FLAG_UPKEY clrf FLAG_DOWNKEY clrf halfsecs clrf secs clrf mins clrf hours CALL setpoint_validate ; movlw .40 ; movwf AUTOTIME ; movwf TRIPCURRENT ;********************************************************************************** ;********************************************************************************* ;MAIN PROGRAM ;********************************************************************************* MAIN BANKSEL PIR1 ; bank0 Call ADC ; Get value (Amps) movfw CURRENT movwf VALUE ; and save in Value bsf MSD_POINT_FLAG,0 ; MSD display-point on bcf LSD_POINT_FLAG,0 ; LSD display-point off call CALC ; calculate value call DELAY ; wait 0,1 sec call DELAY ; wait 0,1 sec call DELAY clrwdt call DELAY BANKSEL PORTB bcf PORTB,led2 ; leds bsf PORTA,led3 ; off bsf PORTB,led1 ; led1 on bcf PORTB,relais ; power on; =relais off NOP ; wait for portB to settle NOP btfsc PORTB,1 ; test if led1 is on goto continue ; point at display on movfw PORTB addlw .2 nop movwf PORTB continue BTFSS PORTB,reset ; RESET goto RESET BTFSS PORTB,setkey ; SETKEY GOTO SETCURR nop clrwdt movfw CURRENT ; is CURRENT lower then 0.5 Amp? sublw .5 ; btfsc STATUS,C GOTO MAIN ; yes, goto MAIN movfw TRIPCURRENT ; get CURRENT subwf CURRENT,0 ; is CURRENT bigger then TRIPCURRENT? btfsc STATUS,C goto testSETkey ; yes ; no BTFSS PORTB,reset ; RESET goto RESET BTFSS PORTB,setkey ; SETKEY goto SETCURR nop movfw CURRENT ; is CURRENT lower then 0.5 Amp? sublw .5 ; btfsc STATUS,C GOTO MAIN ; yes, goto MAIN call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec ;;;;clrwdt call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call ADC movfw CURRENT movwf VALUE call CALC movfw CURRENT ; get CURRENT subwf TRIPCURRENT,0 ; is CURRENT bigger then TRIPCURRENT? btfss STATUS,C goto testSETkey ; yes ; no BTFSS PORTB,reset ; test RESETkey goto RESET BTFSS PORTB,setkey ; test SETKEY goto SETCURR nop ;;;;clrwdt movfw CURRENT ; is CURRENT lower then 0.5 Amp? sublw .5 ; btfsc STATUS,C GOTO MAIN ; yes, goto MAIN call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec ;;;;clrwdt call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call ADC movfw CURRENT movwf VALUE call CALC movfw CURRENT ; get CURRENT subwf TRIPCURRENT,0 ; is CURRENT bigger then TRIPCURRENT? btfss STATUS,C goto testSETkey ; yes ; no BTFSS PORTB,reset ; test RESETkey goto RESET BTFSS PORTB,setkey ; test SETKEY goto SETCURR nop ;;;;clrwdt movfw CURRENT ; is CURRENT lower then 0.5 Amp? sublw .5 ; btfsc STATUS,C GOTO MAIN ; yes, goto MAIN call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec ;;;;clrwdt call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call ADC movfw CURRENT movwf VALUE call CALC movfw CURRENT ; is CURRENT lower then 0.5 Amp? sublw .5 ; btfsc STATUS,C GOTO MAIN movfw CURRENT ; get CURRENT subwf TRIPCURRENT,0 ; is CURRENT bigger then TRIPCURRENT? btfsc STATUS,C goto OFF ; no ; yes ;;;;clrwdt movfw CURRENT ; is CURRENT lower then 0.5 Amp? sublw .5 ; btfsc STATUS,C GOTO MAIN ; yes, goto MAIN call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec ;;;;clrwdt call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call DELAY ; wait 0.1 sec call ADC movfw CURRENT movwf VALUE call CALC movfw CURRENT ; is CURRENT lower then 0.5 Amp? sublw .5 ; btfsc STATUS,C GOTO MAIN movfw CURRENT ; get CURRENT subwf TRIPCURRENT,0 ; is CURRENT bigger then TRIPCURRENT? btfsc STATUS,C goto OFF ; no testSETkey BTFSS PORTB,setkey ; set-key is pushed? goto SETCURR ; Do set-tripcurrent-thing GOTO MAIN OFF bcf STATUS,RP1 bcf STATUS,RP0 clrf secs ; Re clrf mins ; set clrf hours ; RTC ; exept halfsecs AUTO_TIME bsf PORTA,relais ; Power off; relais on bcf PORTB,led1 ; led off ;;;CLRWDT BANKSEL PIR1 ; bank0 Call ADC ; Get value (Amps) movfw CURRENT movwf VALUE call CALC call DISPL_FLASH BTFSS PORTB,reset ; RESET goto RESET movfw AUTOTIME sublw .88 btfsc STATUS,Z ; is autotime .88 ? goto OFF ; yes, goto OFF movfw AUTOTIME ; get autotime subwf hours,0 ; is btfss STATUS,Z ; time finished? goto AUTO_TIME ; no timefinished bsf PORTB,led1 bcf PORTA,relais ; relais off; power ON banksel TRISA bcf TRISA,LSD ; put display on bcf TRISA,MSD banksel PIR1 goto MAIN ;************************************************************************ ; SETCURR ; Part of Menu, to set tripcurrent ;************************************************************************ SETCURR clrf halfsecs clrf secs testkey btfsc PORTB,setkey ; key has goto MAIN ; to ;;;clrwdt ; be movf secs,w ; pushed sublw .1 ; for 2 seconds btfsc STATUS,C ; before setcurrent menu starts goto testkey ; else goto MAIN BANKSEL PIR1 ; bank0 ;;;clrwdt bcf PIR1,TMR1IF clrf TMR1L clrf TMR1H clrf halfsecs ; reset clrf secs ; real clrf mins ; time clrf hours ; clock to zero bsf PORTB,led2 ; led2 "setcurrent" on call DELAY bsf MSD_POINT_FLAG,0 ; light point on MSD-display bcf LSD_POINT_FLAG,0 ; point on LSD-display off _show movfw TRIPCURRENT ; DIsplay tripcurrent movwf VALUE call CALC ;;;;clrwdt btfss PORTB,setkey ; test if key still pushed goto _show ; key is still pushed... call DELAY bcf STATUS,RP1 bcf STATUS,RP0 TESTKEYS BTFSS PORTB,up ; call _keyPressup BTFSS PORTB,down ; call _keyPressdown btfss PORTB,setkey ; test if key pushed goto AUTOTIME2 ; btfss PORTB,reset goto RESET TIMERFINISHED? movfw mins sublw .5 btfss STATUS,C goto MAIN goto _show ;********* ; Key Switch state ; _keyPressup BANKSEL TMR1H clrf mins movlw .5 call udelay _stable btfss PORTB, up ; is key down? goto _keydown goto _keyup ; if not do _keyup _keydown movf keyrepeat,F ; Test value in keyrepeat to see if we have been here already bnz _krdelay ; if we have goto repeat delay _keything movfw TRIPCURRENT ; pcurrent sublw .89 btfss STATUS,C ; is tripcurrent .90 ? return incf TRIPCURRENT,f ; 1 higher movfw TRIPCURRENT movwf VALUE movwf TEMPEEDATA call DELAY call DELAY ok BANKSEL PIR1 ;;;;clrwdt movlw 0x02 ; load W with EE address movwf TEMPEEADDR ; set EE write address movf TRIPCURRENT,W ; put in W movwf TEMPEEDATA call eeWrite ; and write back to EE call DELAY call DELAY btfsc PORTB, up goto _keyup return _krdelay movlw 0xff ; Load W with 0xFF (we test for not 0 in keydown code) movwf keyrepeat ; save it back to keyrepeat movfw TRIPCURRENT ; put value in tripcurrent sublw .89 ; btfss STATUS,C ; is tripcurrent .90 ? return ; incf TRIPCURRENT,f ; 1 higher movfw TRIPCURRENT movwf VALUE movwf TEMPEEDATA movlw 0x02 ; load W with EE address movwf TEMPEEADDR ; set EE write address BANKSEL PIR1 movf TRIPCURRENT,W ; put in W call eeWrite ; and write back to EE movlw .100 call udelay return _keyup clrf keyrepeat ; reset keyrepeat to 0 RETURN ;******* _keyPressdown BANKSEL TMR1H clrf mins movlw .5 call udelay _stable1 btfss PORTB, down ; is key down? goto _keydown1 goto _keyup1 ; if not do _keyup _keydown1 movf keyrepeat,F ; Test value in keyrepeat to see if we have been here already bnz _krdelay1 ; if we have goto repeat delay _keything1 movfw TRIPCURRENT sublw .10 btfsc STATUS,C return decf TRIPCURRENT,F ; increment speed by 1 movfw TRIPCURRENT movwf VALUE movwf TEMPEEDATA call DELAY call DELAY bcf FLAG_DOWNKEY,0 ok1 movlw 0x02 ; load W with EE address movwf TEMPEEADDR ; set EE write address BANKSEL PIR1 movf TRIPCURRENT,W ; put in W movwf TEMPEEDATA call eeWrite ; and write back to EE return _krdelay1 movlw 0xff ; Load W with 0xFF (we test for not 0 in keydown code) movwf keyrepeat ; save it back to keyrepeat movfw TRIPCURRENT sublw .10 btfsc STATUS,C return decf TRIPCURRENT,F ; increment speed by 1 movfw TRIPCURRENT movwf VALUE movwf TEMPEEDATA movlw 0x02 ; load W with EE address movwf TEMPEEADDR ; set EE write address BANKSEL PIR1 movf TRIPCURRENT,W ; put in W call eeWrite ; and write back to EE movlw .100 call udelay bcf FLAG_DOWNKEY,0 return _keyup1 clrf keyrepeat ; reset keyrepeat to 0 bcf FLAG_DOWNKEY,0 RETURN ;******* ;************************************************************************************ ; AUTOTIME2 ; Part of Menu, to set auto-reset-time ;************************************************************************************ AUTOTIME2 BANKSEL PIR1 ; bank0 ;;;clrwdt movfw AUTOTIME ; DIsplay autotime movwf VALUE call CALC btfss PORTB,setkey ; test if key still pushed goto AUTOTIME2 ; key is still pushed... bcf INTCON,GIE bcf PIR1,TMR1IF clrf TMR1L clrf TMR1H clrf halfsecs ; reset clrf secs ; real clrf mins ; time clock bsf INTCON,GIE bcf PORTA,led3 ; led3 "set autotime" on bcf PORTB,led2 ; led2 off bcf MSD_POINT_FLAG,0 ; set display point on LSD-display bsf LSD_POINT_FLAG,0 show2 movfw AUTOTIME ; DIsplay autotime movwf VALUE call CALC ;;;;clrwdt call DELAY bcf STATUS,RP1 bcf STATUS,RP0 TESTKEYS2 BTFSS PORTB,up ; call _keyPressup2 BTFSS PORTB,down ; call _keyPressdown2 btfss PORTB,setkey ; test if key pushed goto RESET ; btfss PORTB,reset goto RESET TIME_OUT movfw mins ; after 5 minutes, this sublw .5 ; menu is aborted and btfss STATUS,C ; normal operation is goto MAIN ; resumed goto show2 ;********* ; Key Switch state ; _keyPressup2 BANKSEL TMR1H movlw .5 call udelay clrf mins _stable3 btfss PORTB, up ; is key down? goto _keydown3 goto _keyup3 ; if not do _keyup _keydown3 movf keyrepeat,F ; Test value in keyrepeat to see if we have been here already bnz _krdelay3 ; if we have goto repeat delay _keything3 movfw AUTOTIME ; pcurrent sublw .87 btfss STATUS,C ; is autotime .88 ? return incf AUTOTIME,f ; 1 higher movfw AUTOTIME movwf VALUE movwf TEMPEEDATA call DELAY call DELAY bcf FLAG_UPKEY,0 ok3 movlw 0x03 ; load W with EE address movwf TEMPEEADDR ; set EE write address BANKSEL PIR1 movf AUTOTIME,W ; put in W call eeWrite ; and write back to EE btfsc PORTB, up goto _keyup3 return _krdelay3 movlw 0xff ; Load W with 0xFF (we test for not 0 in keydown code) movwf keyrepeat ; save it back to keyrepeat movfw AUTOTIME ; put value in autotime sublw .87 ; btfss STATUS,C ; is tripcurrent .88 ? return ; incf AUTOTIME,f ; 1 higher movfw AUTOTIME movwf VALUE movwf TEMPEEDATA movlw 0x03 ; load W with EE address movwf TEMPEEADDR ; set EE write address BANKSEL PIR1 movf AUTOTIME,W ; put in W call eeWrite ; and write back to EE movlw .100 call udelay return _keyup3 clrf keyrepeat ; reset keyrepeat to 0 RETURN ;******* _keyPressdown2 BANKSEL TMR1H movlw .5 call udelay clrf mins _stable4 btfss PORTB, down ; is key down? goto _keydown4 goto _keyup4 ; if not do _keyup _keydown4 movf keyrepeat,F ; Test value in keyrepeat to see if we have been here already bnz _krdelay4 ; if we have goto repeat delay _keything4 movfw AUTOTIME ; Autotime can not sublw .1 ; be lower then btfsc STATUS,C ; 1 return decf AUTOTIME,F ; increment speed by 1 movfw AUTOTIME movwf VALUE movwf TEMPEEDATA call DELAY call DELAY bcf FLAG_DOWNKEY,0 ok4 movlw 0x03 ; load W with EE address movwf TEMPEEADDR ; set EE write address BANKSEL PIR1 movf AUTOTIME,W ; put in W call eeWrite ; and write back to EE return _krdelay4 movlw 0xff ; Load W with 0xFF (we test for not 0 in keydown code) movwf keyrepeat ; save it back to keyrepeat movfw AUTOTIME ; Autotime can not be lower sublw .1 ; then btfsc STATUS,C ; 1 return decf AUTOTIME,F ; increment speed by 1 movfw AUTOTIME movwf VALUE movwf TEMPEEDATA movlw 0x03 ; load W with EE address movwf TEMPEEADDR ; set EE write address BANKSEL PIR1 movf AUTOTIME,W ; put in W call eeWrite ; and write back to EE movlw .100 call udelay return _keyup4 clrf keyrepeat ; reset keyrepeat to 0 RETURN ;******* ;****************************************************************** ; DISPL_FLASH ; Subroutine that flashes display every half second ;****************************************************************** DISPL_FLASH btfss halfsecs,0 ; if halfsecs is 0 goto Display_OFF ; DISPLAY OFF displON BANKSEL TRISA BCF TRISA,MSD nop BCF TRISA,LSD BANKSEL PIR1 ; bank0 RETURN Display_OFF BANKSEL TRISA bsf TRISA,MSD nop BSF TRISA,LSD BANKSEL PIR1 ; bank0 RETURN ;************************************************************************ ; Subroutine CALC, calculates values for display ;************************************************************************ CALC movfw VALUE call get ; get corresponding decimal value movwf CURRENTdec ; write to CURRENTdec movwf CURRENTdecH RRF CURRENTdecH,1 ; shift RRF CURRENTdecH,1 ; byte RRF CURRENTdecH,1 ; 4 RRF CURRENTdecH,1 ; places to the right MOVF CURRENTdecH,w ; put into w ANDLW b'00001111' ; mask off 4 lowbits movwf MSNvalue ; write value to MSNvalue movfw CURRENTdec ; get current ANDLW b'00001111' ; mask off 4 highbits movwf LSNvalue ; write value to LSNvalue RETURN ;**************************************************************************** ; Subroutine udelay ; gives a delay depending on value in W ; *************************************************************************** udelay ; delay W * 100 usec movwf dcnt0 udelay0 movlw 10 * mhz movwf dcnt1 udelay1 decfsz dcnt1, F goto udelay1 decfsz dcnt0, F goto udelay0 return ; ********************************************************************************** ; *************************** ; SUBROUTINE AD-CONVERSION; MEASURE CURRENT ; *************************** ADC BANKSEL ADCON0 movlw b'10010001' ; right justified, ch AN4, VDD=Vref movwf ADCON0 ; bcf PIR1,ADIF movlw .4 ; acquisitiom time call udelay bsf ADCON0, GO ; start ADC NOP btfsc ADCON0, GO goto $-1 movlw ADRESH ;indirect movwf FSR ;adressing movf INDF,w ;anders btfss STATUS,Z ;gaat het fout goto ninetynine movlw ADRESL ;indirect movwf FSR ;adressing movf INDF,w ;anders movwf CURRENTtemp sublw .99 ; check if lower then 100 btfsc STATUS,C ; if lower then 100 goto ok2 ; then ok ninetynine movlw .99 ; not lower then 100 so make 99 movwf CURRENT RETURN ok2 movf CURRENTtemp,w movwf CURRENT bcf CURRENT,7 ; clear signbit BANKSEL PIR1 ; bank0 bcf PIR1,ADIF RETURN ;************************************************************************* ; RESET ; Subroutine that resets system ;************************************************************************* RESET BANKSEL PIR1 ; bank0 call DELAY banksel TRISA bcf TRISA,LSD ; put display on bcf TRISA,MSD BANKSEL PIR1 bcf FLAG_RESETKEY,0 ; clear flag bcf FLAG_SETKEY,0 ; clear flag keyuptest btfss PORTB,reset ; is key up? goto keyuptest ; no, wait call DELAY ; yes, little pause bcf PORTA,relais ; relais off: power to motor on bsf PORTA,0 ; led3 off bcf PORTB,led2 ; led2 off bsf PORTB,led1 ; led1 ON goto MAIN ;************************************************************************ ; DELAY ; Subroutine that gives a delay of approx 0.2 secs ;************************************************************************ DELAY movlw .255 movwf dcnt0 delay0 movlw .255 movwf dcnt1 delay1 decfsz dcnt1, F goto delay1 decfsz dcnt0, F goto delay0 return ;**** ;****************************************************************************** ; Interrupt routine key_pressed ; ***************************************************************************** ;key_pressed movwf W_TEMP ; swapf STATUS,W ; clrf STATUS ; movwf STATUS_TEMP ; BANKSEL PORTA ; btfss PORTB,setkey ; bsf FLAG_SETKEY,0 ; btfss PORTB, reset ; bsf FLAG_RESETKEY,0 ; btfss PORTB,up ; bsf FLAG_UPKEY,0 ; btfss PORTB,down ; bsf FLAG_DOWNKEY,0 ; clrf PORTB ; bcf INTCON,RBIF ; SWAPF STATUS_TEMP,W ; MOVWF STATUS ; SWAPF W_TEMP,F ; SWAPF W_TEMP,W ; RETFIE ; Done ;*************************************************************************************** ; INT_POLL INTERRUPT POLL ROUTINE ;*************************************************************************************** ; TEST WHERE INTERRUPT IS COMING FROM EN REDIRECT TO THE CORRESPONDING INT-ROUTINE INT_POLL btfsc INTCON,T0IF ; test if timer0 interrupt goto Refresh_display ; yes btfsc PIR1,TMR1IF ; test if timer1 interrupt goto RTCISR ; yes ;; btfsc INTCON,RBIF ; test if portA IOC-interrupt; button pushed ;; goto key_pressed ; yes GOTO INIT ; faulty situation ;*************************************************************************************** ;*************************************************************************************** ;REALTIME CLOCK INTERRUPT ROUTINE ;*************************************************************************************** RTCISR movwf W_TEMP swapf STATUS,W clrf STATUS movwf STATUS_TEMP BANKSEL TMR1H ; bank0 MOVLW b'00001011' ; Preload TMR1 register pair MOVWF TMR1H ; for MOVLW b'11011100' ; one half second MOVWF TMR1L ; overflow bcf STATUS,RP0 bcf STATUS,RP1 BCF PIR1, TMR1IF ; Clear interrupt flag INCF halfsecs, F ; Increment half seconds MOVF halfsecs, w SUBLW .2 BTFSS STATUS, Z ; 2 half-seconds elapsed? GOTO STOP ; No, done CLRF halfsecs ; Clear half-seconds INCF secs, F ; Increment seconds MOVF secs, w SUBLW .60 BTFSS STATUS, Z ; 60 seconds elapsed? GOTO STOP ; No, done CLRF secs ; Clear seconds INCF mins, f ; Increment minutes MOVF mins, w SUBLW .60 BTFSS STATUS, Z ; 60 minutes elapsed? GOTO STOP ; No, done CLRF mins ; Clear minutes INCF hours, f ; Increment hours MOVF hours, w SUBLW .90 BTFSS STATUS, Z ; 90 hours elapsed? GOTO STOP ; No, done CLRF hours ; Clear hours STOP SWAPF STATUS_TEMP,W MOVWF STATUS SWAPF W_TEMP,F SWAPF W_TEMP,W RETFIE ; Done ;******************************************************************************************* ;***************************************************************************** ; Refresh display Interrupt routine ;***************************************************************************** Refresh_display movwf W_TEMP swapf STATUS,W clrf STATUS movwf STATUS_TEMP clrwdt BANKSEL PIR1 ; bank0 bcf INTCON,T0IF ; clear timer0 overflow-flag MSN btfsc FLAG_MSNDISPLAY,0 ; is MostSignificantNumber multiplexed? goto LSN ; yes, switch to LSN bsf PORTA,LSD ; no, switch LSN off movf MSNvalue,w ; get (new) value for display movwf DISPL_VALUE call Lookup ; find 7-segment code in table btfsc MSD_POINT_FLAG,0 ; test if point has to be displayed addlw .8 ; on MSD-display. RC3 = 8 movwf PORTC ; light MSN bcf PORTA,MSD ; switch MSN on bsf FLAG_MSNDISPLAY,0 ; set flag goto STOP2 LSN bsf PORTA,MSD ; switch off MSN movf LSNvalue,w ; get (new) value for display movwf DISPL_VALUE call Lookup ; find 7 segmet code in table btfsc LSD_POINT_FLAG,0 ; test if point has to be displayed addlw .8 ; on LSD-display. RC3 = 8 movwf PORTC ; light LSN bcf PORTA,LSD ; switch on LSN bcf FLAG_MSNDISPLAY,0 ; reset flag STOP2 SWAPF STATUS_TEMP,W MOVWF STATUS SWAPF W_TEMP,F SWAPF W_TEMP,W RETFIE ; Done ; ************************************************************************* ; Test EEPROM to see if it contains valid data from previous ; operation. Initialise EEPROM if it doesn't ; Two bytes are used to validate the EEPROM mode setting data. If these ; two bytes are contain the correct values then the mode is assumed to be correct, ; if not the validation bytes are set and speed is set to 20. ;_setpoint_validate setpoint_validate movlw 0x00 ; set EE address 0 movwf TEMPEEADDR call eeRead ; read data xorlw 0x81 ; compare to 0x81 skpz ; skip next if match call eeInit ; else initialize EE data movlw 0x01 ; set EE address 1 movwf TEMPEEADDR call eeRead ; read data xorlw 0x69 ; compare to 0x69 skpz ; skip next if match call eeInit ; else initialize EE data movlw 0x02 ; set EE address 2 movwf TEMPEEADDR call eeRead ; read data. Setpoint tripcurrent select movwf TRIPCURRENT movlw 0x03 ; set EE address 3 movwf TEMPEEADDR call eeRead ; read data. Setpoint autotime select movwf AUTOTIME return ; ********************************* ; EEPROM read ; call with W reg containg address to read ; returns with eeprom read data in W reg eeRead MOVF TEMPEEADDR,w ; get BSF STATUS,RP1 ; BCF STATUS,RP0 ; Bank 2 MOVWF EEADRL ; Address to read BSF STATUS,RP0 ; Bank 3 BSF STATUS,IRP BCF EECON1,EEPGD ; Point to Datamemory BSF EECON1,RD ; EE Read BCF STATUS,RP0 ; Bank 2 MOVF EEDATL,W ; W = EEDATA bcf STATUS,RP1 ; Bank 0 bcf STATUS,IRP return ; ********************************* ; EEPROM write ; calling code must set EEADR register ; and call with W reg containg data to write eeWrite bcf PIR1,EEIF MOVf TEMPEEADDR,w ;Data Memory BSF STATUS,RP1 ; BCF STATUS,RP0 ;Bank 2 MOVWF EEADRL ;Address to write bcf STATUS,RP1 MOVF TEMPEEDATA,w ;Data Memory Value BSF STATUS,RP1 MOVWF EEDATL ;to write BSF STATUS,RP0 ;Bank 3 BCF EECON1,EEPGD ;Point to DATA memory bcf INTCON,GIE BSF EECON1,WREN ;Enable writes MOVLW 0x55 ; MOVWF EECON2 ;Write 55h MOVLW 0xAA ; MOVWF EECON2 ;Write AAh BSF EECON1,WR ;Set WR bit to begin write BSF INTCON,GIE ;Enable INTs. bcf STATUS,RP0 ;bank0 bcf STATUS,RP1 btfss PIR1,EEIF ;write finished? goto $-1 ;no nop ; bcf PIR1,EEIF ;yes bsf STATUS,RP1 ;bank3 bsf STATUS,RP0 BCF EECON1,WREN ;Disable writes bcf STATUS,RP1 ;bank0 bcf STATUS,RP0 return ; ********************************* ; Initializes EEPROM eeInit clrw movwf TEMPEEADDR bcf STATUS,RP0 bcf STATUS,RP1 movlw 0x81 ; init test byte #0 movwf TEMPEEDATA call eeWrite bcf STATUS,RP0 bcf STATUS,RP1 movlw .1 movwf TEMPEEADDR movlw 0x69 ; init test byte #1 movwf TEMPEEDATA call eeWrite bcf STATUS,RP0 bcf STATUS,RP1 movlw .2 movwf TEMPEEADDR movlw .50 ; init tripcurrent data movwf TEMPEEDATA call eeWrite bcf STATUS,RP0 bcf STATUS,RP1 movlw .3 movwf TEMPEEADDR movlw .88 ; init autotime data movwf TEMPEEDATA call eeWrite BANKSEL PIR1 ;bank0 return ; *********************************************** end