>>took ages to program and i still have bugs
Interesting .... I found your code here with google
http://www.siliconchip.com.au/cms/at...month=November
>>took ages to program and i still have bugs
Interesting .... I found your code here with google
http://www.siliconchip.com.au/cms/at...month=November
Last edited by paul borgmeier; - 25th September 2007 at 07:29.
Paul Borgmeier
Salt Lake City, UT
USA
__________________
you've got me -
the code is legit no malware
the code is available with current kit based speed alert devices but I need to modify it for a personal project. I just Downloaded MPLAB today and ran the first couple of instructions and found a list of errors. I was expecting everything to be in order:
Heres the code in full:
part 1:
- if need be i'll contact the developers website on why their code is ridden with bugs. Thanks for look at it.Code:; File SPEED254.ASM changes from SPEED.ASM to allow speed readings up to 254km/h ; Uses assembly code for PIC16F84 microcontroller ; This program is for a car speed alarm. It utilises three 7-segment displays ; which show the set speed. The speed setting can be altered with up and down pushbutton ; switches from 0 to 255km/h in 5km/h steps. When the speed of the vehicle reaches the set speed, ; the alarm sounds and an LED lights up. The alarm is a short beep beep sound while the LED ; remains lit until the speed is reduced below the alarm speed or the alarm speed is increased ; above the vehicles speed. ; ; A rotating magnet or magnets installed on the vehicles tail shaft or drive shaft ; trigger an inductive (coil) sensor to detect vehicle speed and this signal is detected via ; an interrupt in the processor. ; ; Calibration can be made by setting an alarm speed on the display and then bringing the ; vehicle speed up to the alarm speed as shown on the vehicles speedometer. ; The Calibrate switch is then pressed. The display will show CAL until ; calibrated. Display will show Err (error) if too few pulses or none are present while calibrating. ; No calibration allowed in speedometer mode. ; ; Each pressing the Mode switch will cycle between alarm speed indication, speedometer ; and off which disables the speed alarm. ; ; Alarm indication occurs for speedometer and alarm speed modes. ; ; Pressing the Up switch at power up will set the speed alarm for either a ; repeat warning of overspeed or single alarm. The repeat alarm will produce a tone every ; 10-seconds until the speed goes below the setting or the speed setting is increased above ; the speed. ; ; When pressing the Up switch at power up, a 'r' on the right display indicates repeat ; alarm and a '-' indicates no-repeat alarm option. ; ; Pressing the Mode switch at power up will toggle the speed alarm with the speedometer on or off ; If the display shows an 'S' then the speedometer function will operate and a '-' indicates that ; the speedometer is off. ; ; Pressing the Down switch at power up will set the speed alarm threshold point either high or ; low. The low threshold means that the alarm will sound at the set speed and switch off ; when the speed goes 1km/h or less below this speed. The high threshold will set the alarm ; when the speed is 1km/h or more above the set speed and go off for speeds at or below the ; set speed. A high setting will be indicated by an 'H' and a low setting by an 'L'as shown during ; power up with the down switch pressed. ; ; Processor pin allocations are as follows: ; RA0 Output disp1 driving transistor for common anode display ; RA1 Output disp2 ; RA2 Output disp3 ; RA3 Output for alarm ; RA4 Input from switches ; RB0 Input for wheel sensor (interrupt) ; RB1 c segment drive for seven segment LED display ; RB2 d segment drive ; RB3 e segment drive ; RB4 f segment drive ; RB5 a segment drive ; RB6 b segment drive ; RB7 g segment drive ; CPU configuration ; list P=16F84 #include "p16f84.inc" __config _XT_OSC & _WDT_OFF & _PWRTE_ON ; Define variables at memory locations ; EEPROM DATA EEPROM1 equ H'00' ; non-volatile storage for display1 EEPROM2 equ H'01' ; non-volatile storage for display2 EEPROM3 equ H'02' ; non-volatile storage for display3 EEPROM4 equ H'03' ; non-volatile storage to toggle repeat alarm feature and mode EEPROM5 equ H'04' ; non-volatile storage of LS byte of calibration number EEPROM6 equ H'05' ; non-volatile storage of MS byte of calibration number ; RAM DISP1 equ H'0C' ; working storage for Display1 value alarm speed mode DISP2 equ H'0D' ; working storage for Display2 value alarm speed mode DISP3 equ H'0E' ; working storage for Display3 value alarm speed mode STATUS_TMP equ H'0F' ; temp storage for status during interrupt W_TMP equ H'10' ; temporary storage for w during interrupt VALUE_1 equ H'11' ; delay value storage VALUE_2 equ H'12' ; delay value storage FLAG_1 equ H'13' ; flag, bit 0 = flag for closed switch, bit 1 for interrupt indicator ; bit 2 for alarm tone required, bit 3 for tone duty cycle, ; bit 4 alarm off, bit 5 overspeed, bit 6 EEPROM ; write repeat number, bit 7 for calibrate flag FLAG_2 equ H'14' ; alarm tone period settable from 00-FE FLAG_3 equ H'15' ; alarm tone sequence 00000000=on,00000001=off,00000010=on >=00000011 off, ; use a more significant bit to set reocurrence, bit 6 or 7 REPEAT equ H'16' ; bit 0 working store repeat alarm flag stored in EEPROM4, bit 1 on/off flag ; bit 1 on/off flag, bit 2 speedo/alarm select flag, bit 3 speedo on/off flag ; bit 4 alarm threshold SPEED_EQV equ H'17' ; storage for speed equivalent (value of 5 per 5km/h) 160km/h=160 TEMP_1 equ H'18' ; temporary working storage TEMP_2 equ H'19' ; temp storage TIME_CNT1 equ H'1A' ; counter for pulse count period TIME_CNT2 equ H'1B' ; counter for pulse count period TIME_CNT3 equ H'1C' ; working lsb calibration number stored in EEPROM5 TIME_CNT4 equ H'1D' ; working msd calibration number stored in EEPROM6 PULSE_CNT equ H'1E' ; counter for speed pulses compared with speed_eqv ERR_FLG equ H'1F' ; bit 0 is error flag for counter overrange during calibration SPEEDO equ H'20' ; latched value for speedometer obtained from PULSE_CNT SPEED1 equ H'21' ; display1 value during speedometer mode SPEED2 equ H'22' ; display2 value during speedometer mode SPEED3 equ H'23' ; display3 value during speedometer mode TEMP equ H'24' ; temporary register for BCD conversion BCD_0 equ H'25' ; decimal value MSD BCD_1 equ H'26' ; decimal packed BCD LS digits BIN_0 equ H'27' ; binary value for BCD conversion CNT_8 equ H'28' ; counter for BCD conversion TEMP_X equ H'29' ; temporary register for speed equivalent calculation ; preprogram EEPROM DATA ORG 2100 DE 0x00, 0x06, 0x00 ; preset EEPROM1-EEPROM3 ( initial speed setting is 60) DE 0x03 ; set EEPROM4 (repeat alarm on bit 0 and set to on/off bit 1) ; bit 2 speedo/set bit to set alarm mode, bit 3 speedo on ; bit 4 alarm threshold low DE 0xB3, 0x11 ; set calibration EEPROM5 & EEPROM6 (set to 100Hz = 160km/h ; calibration calculated out at 1.6s update time 160km/h = 160 pulses counted. ; 3.579545MHz/4/2/(256-100+2) = 353.1175us and require 4531Decimal for 1.6 sec or 11B3Hex ; Program begins ; define reset and interrupt vector start addresses org 0 ; start at address 0000h goto MAIN ; normal service routines from Reset vector org 4 ; interrupt vector 0004h, start interrupt routine here goto INTER ; go to start of interrupt routine, bypass subroutines ; subroutine to get seven segment display data. (This is placed at front of programm to prevent computed ; goto crossing 256 bit boundary. *PCL control only over least significant 8-bits*) SVNSEG andlw 0x0F; remove most significant bits if present prevents value >16h addwf PCL,f ; add value of display to program counter retlw B'10000000' ; 7-segment code 0 retlw B'10111100' ; 7-segment code 1 retlw B'00010010' ; 7-segment code 2 retlw B'00011000' ; 7-segment code 3 retlw B'00101100' ; 7-segment code 4 retlw B'01001000' ; 7-segment code 5 retlw B'01000000' ; 7-segment code 6 retlw B'10011100' ; 7-segment code 7 retlw B'00000000' ; 7-segment code 8 retlw B'00001000' ; 7-segment code 9 ;*******************************************************************************************
Part 2
Code:; INTERRUPT ; interrupt from counter used to multiplex display ; this sucessively switches on Disp1, Disp2, Disp3 in sequence plus ; blanking leading zeros on display for Disp2 and Disp3 for either ; speedometer or set alarm speed modes ; uses internal timer to initiate display update ; also updates time period counters which set period of speed pulse counting ; checks speed against alarm setting ; speed sensor update ; start interrupt by saving w and status registers before altered by interrupt routine INTER movwf W_TMP ; w to w_tmp storage swapf STATUS,w ; status to w movwf STATUS_TMP ; status in status_tmp ; which interrupt (INT or TMRO) btfsc INTCON,T0IF ; TMRO overflow interrupt flag then goto litchk goto LITCHK ; TMRO overflow so multiplex display SENSOR btfsc INTCON,INTF ; INT interrupt flag set then goto speed goto SPEED ; speed sensor signal update goto RECLAIM ; end of interrupt reclaim w and status ; multiplex display routine LITCHK btfsc REPEAT,1 ; check if speed alarm unit on or off goto ALM_BY ; on so skip resetting alarm (alarm bypass) ; reset alarm function clrf PULSE_CNT ; clear pulse counter so no alarm clrf TIME_CNT1 ; clear time counter 1 clrf TIME_CNT2 ; clear time counter 2 ALM_BY bcf STATUS,RP0 ; select bank 0 movlw D'100' ; speed up multiplex rate for suitable tone in piezo alarm (100 ; is used in calibration number calculation and for output freq) ; freq is 3.579545MHz/2/4/(256-100+2)/2 = 1.4159kHz addwf TMR0,f ; add to timer registerand takes 2 cycles to start counting bcf INTCON,T0IF ; clear TMRO interrupt flag bsf FLAG_1,0 ; indicate another interrupt has occurred btfsc REPEAT,2 ; check if speedometer or alarm speed mode goto SPD_LTE ; display update in speedometer mode btfss PORTA,0 ; skip if display 1 not lit goto LIT1 ; display 1 lit btfss PORTA,1 ; skip if display 2 not lit goto LIT2 ; display 2 lit btfss PORTA,2 ; skip if display 3 not lit goto LIT3 ; display 3 lit movlw B'11111110' ; seven segments off movwf PORTB bcf PORTA,2 ; no displays lit so set disp3 (used if error in output) goto LITCHK ; goto check which is lit now LIT1 bsf PORTA,0 ; disp1 off movf DISP3,w ; look at display3 xorlw 0x00 ; compare display3 with 0 btfss STATUS,Z ; skip if zero goto NOBLNK ; do not blank display2 movf DISP2,w ; look at display2 xorlw 0x00 ; compare disp2 with 0 btfss STATUS,Z ; skip if 0 goto NOBLNK ; do not blank disp2 movlw B'11111110' ; 7-segment display off goto BLANK ; blank disp2 when disp2 and disp3 = 0 NOBLNK movf DISP2,w ; disp2 to w call SVNSEG ; goto subroutine to get seven segment code BLANK btfss ERR_FLG,0 ; calibrate error goto CAL_M ; mid display movlw B'10000110' ; set display for 'r' (Err) goto LIT_r ; light an r CAL_M btfsc FLAG_1,7 ; calibrate flag skip if clear movlw B'00000100' ; set display to show an A (for CAL) btfss REPEAT,1 ; is speed alarm unit on or off, 1 is on 0 is off movlw B'01111110' ; set 'g' segment on display LIT_r movwf PORTB ; seven segment value to portB bcf PORTA,1 ; disp2 powered goto TIMECNT ; end of multiplex LIT2 bsf PORTA,1 ; disp2 off movf DISP3,w ; disp3 to w xorlw 0x00 ; compare with 0 btfss STATUS,Z ; skip if zero goto SHOW ; show digit on disp3 movlw B'11111110' ; 7-segment display off goto BLNK ; value to blank display SHOW movf DISP3,w ; look at display3 call SVNSEG ; get 7-segment value BLNK btfss ERR_FLG,0 ; calibrate error goto CAL_L ; Left display movlw B'01000010' ; set display for 'E' (Err) goto LIT_E ; light an E CAL_L btfsc FLAG_1,7 ; calibrate flag skip if clear movlw B'11000010' ; set display to show a C (for CAL) btfss REPEAT,1 ; is speed alarm unit on or off, 1 is on 0 is off movlw B'01111110' ; set 'g' segment on display LIT_E movwf PORTB ; portB has seven-segment code bcf PORTA,2 ; disp3 powered goto TIMECNT ; end of multiplex LIT3 bsf PORTA,2 ; disp3 off movf DISP1,w ; disp1 to w call SVNSEG btfss ERR_FLG,0 ; calibrate error goto CAL_R ; Right display movlw B'10000110' ; set display for 'r' (Err) goto LIT_rr ; light an r CAL_R btfsc FLAG_1,7 ; calibrate flag skip if clear movlw B'11100010' ; set display to show an L (for CAL) btfss REPEAT,1 ; is speed alarm unit on or off, 1 is on 0 is off movlw B'01111110' ; set 'g' segment on display LIT_rr movwf PORTB bcf PORTA,0 ; disp1 powered goto TIMECNT ; display update for speedometer mode SPD_LTE btfss PORTA,0 ; skip if display 1 not lit goto SPD_LT1 ; display 1 lit btfss PORTA,1 ; skip if display 2 not lit goto SPD_LT2 ; display 2 lit btfss PORTA,2 ; skip if display 3 not lit goto SPD_LT3 ; display 3 lit movlw B'11111110' ; seven segments off movwf PORTB bcf PORTA,2 ; no displays lit so set disp3 (used if error in output) goto SPD_LTE ; goto check which is lit now SPD_LT1 bsf PORTA,0 ; disp1 off movf SPEED3,w ; look at display3 xorlw 0x00 ; compare display3 with 0 btfss STATUS,Z ; skip if zero goto NOBLNK1 ; do not blank display2 movf SPEED2,w ; look at display2 xorlw 0x00 ; compare disp2 with 0 btfss STATUS,Z ; skip if 0 goto NOBLNK1 ; do not blank disp2 movlw B'11111110' ; 7-segment display off goto BLANK1 ; blank disp2 when disp2 and disp3 = 0 NOBLNK1 movf SPEED2,w ; disp2 to w call SVNSEG ; goto subroutine to get seven segment code BLANK1 movwf PORTB ; seven segment value to portB bcf PORTA,1 ; disp2 powered goto TIMECNT ; end of multiplex SPD_LT2 bsf PORTA,1 ; disp2 off movf SPEED3,w ; disp3 to w xorlw 0x00 ; compare with 0 btfss STATUS,Z ; skip if zero goto SHOW1 ; show digit on disp3 movlw B'11111110' ; 7-segment display off goto BLNK1 ; value to blank display SHOW1 movf SPEED3,w ; look at display3 call SVNSEG ; get 7-segment value BLNK1 movwf PORTB ; portB has seven-segment code bcf PORTA,2 ; disp3 powered goto TIMECNT ; end of multiplex SPD_LT3 bsf PORTA,2 ; disp3 off movf SPEED1,w ; disp1 to w call SVNSEG movwf PORTB bcf PORTA,0 ; disp1 powered ; update time period counters for speed pulse counter TIMECNT btfsc FLAG_1,7 ; calibrate flag skip if clear (no calibrate) goto CALBRAT ; calibrate switch pressed so do calibration movf TIME_CNT4,w ; MS Byte of calibration value to w xorwf TIME_CNT2,w ; compare MS Byte counter with calibration btfss STATUS,z ; skip if equal goto INC_CT1 ; movf TIME_CNT3,w ; LS Byte of calibration value xorwf TIME_CNT1,w ; compare LS byte counter with calibration btfss STATUS,z ; skip if equal goto INC_CT1 ; clrf TIME_CNT1 ; clear timer counter 1 clrf TIME_CNT2 ; and timer 2 movf PULSE_CNT,w ; look at pulse counter value movwf SPEEDO ; speedometer value latched pulse counter value
part 3
Code:; routine to convert speedo memory to speed 1, 2 & 3 display memory sublw 0xFF ; compare with maximum value (255km/h) btfsc STATUS,Z ; is it at maximum goto LIMIT ; maximum of 255 on display ; convert speedo to BCD place in Speed 3,Speed 2 and Speed1 movf SPEEDO,w ; look at speedo value movwf BIN_0 ; to binary register call BCD ; convert to BCD movf BCD_0,w ; ms digit movwf SPEED3 ; display MSD movf BCD_1,w ; LS Digits andlw 0x0F ; mask bits 7-4 movwf SPEED1 ; ls digit swapf BCD_1,w ; look at ms nibble andlw 0x0F movwf SPEED2 ; middle digit goto CK_SPD LIMIT movlw 0x08 ; place 8 in speed1-3 memory so display - movwf SPEED1 ; - shows 888 for overrange speedometer movwf SPEED2 movwf SPEED3 ; check speed against alarm setting CK_SPD movf SPEED_EQV,w ; speed equivalent value to w btfsc REPEAT,4 ; skip if alarm threshold low addlw 0x01 ; increase speed equiv by hysteresis value subwf PULSE_CNT,w ; subtract speed equivalent from pulse counter btfsc STATUS,c ; if positive or zero (c=1) then sound overspeed alarm goto SETALM ; add hysteresis (addition of 1 to pulse counter gives 1km/h hysteresis) movf PULSE_CNT,w ; pulse counter value btfss REPEAT,4 ; skip if alarm threshold high addlw 0x01 ; increase by factor for hysteresis (on to off alarm speed) movwf PULSE_CNT movf SPEED_EQV,w subwf PULSE_CNT,w ; subtract speed equivalent from new pulse counter value btfsc STATUS,c ; if positive or zero (c=1) then leave set alarm on goto ALM_CL ; continue alarm goto CLRALM ; clear alarm as below overspeed INC_CT1 incfsz TIME_CNT1,f ; increase counter 1 skip if overflowed goto ALARM incf TIME_CNT2,f ; increase counter 2 when counter 1 overflows goto ALARM ; calibrate time counters CALBRAT incfsz TIME_CNT1,f ; increase counter 1 skip if overflowed goto CMP_PLS incfsz TIME_CNT2,f ; increase counter 2 on overflow skip if overflowed goto CMP_PLS ; not overrange so compare pulse count with speed equiv bsf ERR_FLG,0 ; error flag set as counter 2 has overranged bcf FLAG_1,7 ; calibrate off flag goto C_ALM CMP_PLS movf PULSE_CNT,w ; pulse counter to w xorwf SPEED_EQV,w ; compare pulse counter with speed equivalent (display value) btfss STATUS,Z ; skip if equal goto C_ALM ; store time counters TIME_CNT1 & 2 into TIME_CNT3 & 4 and into EEPROM5 & 6 - new calibration movf TIME_CNT1,w ; time counter 1 to w movwf TIME_CNT3 ; time counter 3 = 1 movf TIME_CNT2,w ; time counter 2 to w movwf TIME_CNT4 ; time counter 2 = 4 bcf FLAG_1,7 ; calibrate flag clear, calibrate off ; clear alarm CLRALM clrf PULSE_CNT ; clear pulse counter for recount clrf TIME_CNT1 ; clear time counter 1 clrf TIME_CNT2 ; clear time counter 2 C_ALM bcf FLAG_1,5 ; overspeed flag bcf FLAG_1,4 ; clear alarm off flag bsf PORTA,3 ; alarm output high goto ALARM ; continue program ; set alarm SETALM clrf PULSE_CNT ; clear pulse counter for recount clrf TIME_CNT1 ; clear time counter 1 clrf TIME_CNT2 ; clear time counter 2 btfsc FLAG_1,5 ; is overspeed flag set. Skip if not goto ALARM ; set so skip setting alarm again, wait till cleared bsf FLAG_1,5 ; overspeed flag bsf FLAG_1,2 ; set alarm tone flag bsf FLAG_1,4 ; set alarm off flag clrf FLAG_2 ; alarm tone period bcf FLAG_1,3 ; clear on off flag clrf FLAG_3 ; alarm tone sequence ; alarm tone routine generates a beep beep tone for over-speed ALM_CL clrf PULSE_CNT clrf TIME_CNT1 ; clear time counter 1 clrf TIME_CNT2 ; clear time counter 2 ALARM btfss FLAG_1,4 ; alarm off flag goto SENSOR ; alarm not required incf FLAG_2,f ; alarm tone period btfss FLAG_1,2 ; skip if alarm tone required goto RDFLG_2 ; no alarm go to check sensor interrupt btfsc FLAG_1,3 ; alternate on and off flag for tone goto SET_OUT ; if flag set then stop tone on RA3 output btfsc PORTA,3 ; is alarm out low goto SET_OUT bsf PORTA,3 ; alarm out pin high goto CNT_SEQ SET_OUT bcf PORTA,3 ; alarm out pin low CNT_SEQ bcf FLAG_1,3 btfss FLAG_3,0 ; read alarm tone sequence (bit 0 low then alarm tone) goto RDFLG_2 bsf FLAG_1,3 ; no tone bsf PORTA,3 ; alarm output high btfss FLAG_3,1 ; check count goto RDFLG_2 bcf FLAG_1,2 ; alarm off bcf PORTA,3 ; alarm out low goto SENSOR RDFLG_2 movf FLAG_2,w ; read alarm tone period counter sublw 0xFE ; alarm tone on-time (FE = max) (00 = min) btfss STATUS,C ; skip if less than on-time goto SET_FLG goto SENSOR SET_FLG incf FLAG_3,f ; next sequence clrf FLAG_2 ; start period count btfss FLAG_3,7 ; look at bit for repeat tone period, 7 is longest interval, 6 half the period etc goto SENSOR ; if bit set then repeat alarm btfss REPEAT,0 ; skip if repeat flag set goto SENSOR bsf FLAG_1,2 ; allow alarm again clrf FLAG_3 ; clear repeat bit goto SENSOR ; speed sensor update SPEED bcf INTCON,INTF ; clear INT flag incfsz PULSE_CNT,f ; increase pulse counter value for each speed sensor input goto RECLAIM movlw 0xFF ; max value movwf PULSE_CNT ; place max count in pulse counter do not allow overrange ; end of interrupt reclaim w and status RECLAIM swapf STATUS_TMP,w ; status temp storage to w movwf STATUS ; w to status register swapf W_TMP,f ; swap upper and lower 4-bits in w_tmp swapf W_TMP,w ; swap bits and into w register retfie ; return from interrupt
Code:;********************************************************************************************** ; RESET ; Set ports A & B MAIN clrf FLAG_1 ; clear flag memory clrf ERR_FLG ; clear error flag used in calibration clrf TIME_CNT1 ; clear time period counter for speed pulse update clrf TIME_CNT2 ; clear time period counter clrf PULSE_CNT ; clear speed pulse counter clrf SPEED1 ; clear speedometer display1 clrf SPEED2 ; clear speedometer display2 clrf SPEED3 ; clear speedometer display3 bsf STATUS,RP0 ; select memory bank 1 movlw B'00000001' ; w = 00000001 binary (RB0 input, RB1-RB7 output) movwf TRISB ; port B data direction register movlw B'10000000' ; w = 10000000 binary movwf OPTION_REG ; TMRO prescaler no division, PORTB pullups disabled movlw B'00010000' ; w = 10000 binary (RA0-RA2, RA3 outputs, RA4 input) movwf TRISA ; A port data direction register bcf STATUS,RP0 ; select memory bank 0 movlw B'11111110' ; w is all 1's for RB7-RB1, 0 for RB0 movwf PORTB ; portB outputs high movlw B'00001111' movwf PORTA ; portA RA0 high, RA1,RA2 outputs high, RA3 high ; get memory in EEPROM1, EEPROM2 & EEPROM3 for speed setting, place in DISP1, DISP2, DISP3 movlw EEPROM1 ; address for EEPROM1 call EEREAD ; read EEPROM storage sublw 0x09 ; compare with 9 btfss STATUS,C ; skip if positive therefore a 9 or less goto CLR1 ; greater than 9 then clear to 0 movf EEDATA,w ; restore w movwf DISP1 ; EEPROM1 to DISP1 goto EEPRM2 CLR1 clrf DISP1 ; Disp1 = 0 as disp1 was more than 9 (illegal value) EEPRM2 movlw EEPROM2 ; address for EEPROM2 call EEREAD sublw 0x09 ; compare with 9 btfss STATUS,C ; skip if positive therefore a 9 or less goto CLR2 movf EEDATA,w ; restore w movwf DISP2 ; EEPROM2 to DISP2 goto EEPRM3 CLR2 clrf DISP2 ; disp2 = 0 as disp2 was more than 9 (illegal value) EEPRM3 movlw EEPROM3 ; address for EEPROM3 call EEREAD sublw 0x01 ; compare with 1 btfss STATUS,C ; skip if positive therefore a 1 or less goto CLR3 movf EEDATA,w ; restore w movwf DISP3 ; EEPROM3 to DISP3 goto EEPRM5 CLR3 clrf DISP3 ; disp3 = 0 as disp3 was more than 1 (illegal value) ; get EEPROM5 and EEPROM6 calibration values and place in TIME_CNT3 and TIME_CNT4 EEPRM5 movlw EEPROM5 ; address for EEPROM5 call EEREAD movwf TIME_CNT3 ; store in LS byte calibration register movlw EEPROM6 ; address for EEPROM6 call EEREAD movwf TIME_CNT4 ; store in MS byte calibration register ; get memory EEPROM4 and place in REPEAT. This is the indicator for ; repeat alarm on or off, bit 0. ON/OFF flag, bit 1, bit 2 is speedo, bit 3 is speedo on/off ; bit 4 is alarm threshold high or low EEPRM4 movlw EEPROM4 ; address for EEPROM4 call EEREAD movwf REPEAT ; store in repeat register ; check for pressed up switch bcf PORTA,2 ; clear RA2 to check if up switch pressed nop nop ; allow time for levels to settle btfsc PORTA,4 ; is up switch pressed goto CHK_DN ; switch open so check down switch btfsc REPEAT,0 ; test for repeat flag bit 0 goto CLRREP ; clear repeat off alarm bsf REPEAT,0 ; set repeat for alarm movlw B'10000110' ; 'r' on display for repeat alarm goto SWOPEN CLRREP bcf REPEAT,0 ; clear repeat movlw B'01111110' ; '-' on display for no repeat alarm SWOPEN movwf TEMP_1 SWCLSD bsf PORTA,0 ; display off bsf PORTB,5 ; clear a segment bsf PORTB,6 ; clear b segment bsf PORTB,3 ; e segment bsf PORTB,4 ; f segment bsf PORTB,7 ; g segment bsf PORTB,2 ; clear display at RB bcf PORTA,2 ; clear RA2 to check if up switch pressed call DELMO btfsc PORTA,4 ; wait for switch to open goto MODESTO ; store repeat setting when switch opens ; multiplex display until switch opens bsf PORTA,2 ; RA2 high nop nop nop bcf PORTA,0 ; RA0 low so display 1 lit movf TEMP_1,w ; retrieve temp storage value movwf PORTB ; port B a-g segments on again call DELMO ; more delay time goto SWCLSD ; check for pressed switch ; check for pressed down switch CHK_DN bsf PORTA,2 ; RA2 high so Disp3 will be off bsf PORTA,0 ; RA0 high so disp1 off nop nop bcf PORTA,1 ; clear RA1 to check if down switch pressed nop nop ; allow time for levels to settle btfsc PORTA,4 ; is down switch pressed goto CHK_MDE ; switch open so check mode switch btfsc REPEAT,4 ; test for threshold flag bit 4 goto CLRTRS ; clear threshold flag bit bsf REPEAT,4 ; set threshold high movlw B'00100100' ; 'H' on display for high threshold goto DNOPEN CLRTRS bcf REPEAT,4 ; clear threshold flag movlw B'11100010' ; 'L' on display for low threshold DNOPEN movwf TEMP_1 DNCLSD bsf PORTB,6 ; clear b segment bsf PORTB,1 ; clear c segment bsf PORTB,3 ; e segment bsf PORTB,4 ; f segment bsf PORTB,7 ; g segment bsf PORTB,2 ; d segment bcf PORTA,1 ; clear RA1 to check if down switch pressed call DELMO ; more delay time (multiplex) call DELMO ; more delay time btfsc PORTA,4 ; wait for switch to open goto MODESTO ; store repeat setting when switch open ; multiplex display until switch opens movf TEMP_1,w movwf PORTB ; port B a-g segments on again call DELMO ; more delay time goto DNCLSD ; check for pressed switch
Code:; check for pressed Mode switch CHK_MDE bsf PORTA,1 ; RA1 high so disp2 off bsf PORTA,2 ; RA2 high so disp3 off nop nop bcf PORTA,0 ; clear RA0 to check if mode switch pressed nop nop btfsc PORTA,4 ; is mode switch pressed goto NO_OPEN ; switch open so no change btfss REPEAT,3 ; test for speedo on/off flag bit 3 goto CLRSPED ; clear speedo on/off bcf REPEAT,3 ; set speedo movlw B'01001000' ; 's' on display for speedo movwf TEMP_1 goto MODEOPN CLRSPED bsf REPEAT,3 ; set speedo on/off flag movlw B'01111110' ; '-' on display for no speedo movwf TEMP_1 bcf REPEAT,2 ; clear speedometer flag MODEOPN bsf PORTA,2 ; display off bsf PORTB,5 ; clear a segment bsf PORTB,1 ; clear c segment bsf PORTB,2 ; d segment bsf PORTB,4 ; f segment bsf PORTB,7 ; g segment bcf PORTA,0 ; clear RA0 to check if mode switch pressed call DELMO ; more delay time (multiplex time) call DELMO ; more delay time btfsc PORTA,4 ; wait for switch to open goto MODESTO ; store repeat setting when switch open ; multiplex display until switch opens bsf PORTA,0 ; RA0 high nop nop nop bcf PORTA,2 ; RA2 low so display 1 lit movf TEMP_1,w movwf PORTB ; call DELMO ; more delay time (multiplex) goto MODEOPN ; delay period for multiplex rate DELMO movlw D'255' ; delay period movwf TEMP_2 SMALR decfsz TEMP_2,f ; reduce temp_2 goto SMALR ; temp_2 smaller by 1 return ; end delay ; write new mode option to EEPROM4 MODESTO movlw EEPROM4 ; address for EEPROM4 movwf EEADR ; address for write movf REPEAT,w ; flag stored call EWRITE ; write to EEPROM ; calculate speed equivalent value NO_OPEN call SPDEQIV ; calculate speed equivalent goto INT_SET ; subroutine to read EEPROM memory EEREAD movwf EEADR ; indirect special function register bsf STATUS,RP0 ; select memory bank 1 bsf EECON1,RD ; read EEPROM RD_RD nop btfsc EECON1,RD ; skip if RD low (read complete) goto RD_RD ; wait for low RD (read RD) bcf STATUS,RP0 ; select bank 0 movf EEDATA,w ; EEPROM value in w return ; subroutine to calculate speed equivalent of 8 per 5km/h this value is compared with ; counted pulses from speed sensor. SPDEQIV bcf FLAG_1,5 ; overspeed flag bcf FLAG_1,4 ; clear alarm off flag clrf PULSE_CNT ; clear pulse counter clrf TIME_CNT1 ; clear time counter 1 clrf TIME_CNT2 ; clear time counter 2 bsf PORTA,3 ; alarm output high clrf SPEED_EQV ; clear speed equivalent store ; Convert the display readings to a binary speed equivalent value movf DISP3,w ; look at DISP3 value btfsc STATUS,z ; check if 0 goto ZERO xorlw 0x01 ; check if a 1 btfsc STATUS,z ; z is 1 if a 1 goto ONE ; movlw D'100' ; 100 movwf SPEED_EQV ; 100 in speed equivalent ONE movlw D'100' addwf SPEED_EQV,f ; 200 if disp3 was a 2 ZERO movf DISP2,w ; look at display 2 movwf TEMP_X ; place in temporary register INC_SE movlw D'10' ; 10 addwf SPEED_EQV,f ; increase speed equivalent by 10 decfsz TEMP_X,f ; reduce disp2 value goto INC_SE ; do again movf DISP1,w ; display 1 value addwf SPEED_EQV,f ; add display 1 value return ; allow interrupts INT_SET btfss REPEAT,1 ; bit 1 on/off flag goto RB0_INT ; no RB0 interrupt if speed alarm unit in off mode bsf INTCON,INTE ; set interrupt enable for RB0 RB0_INT bsf INTCON,T0IE ; set interrupt enable for TMR0 SWITCH bsf INTCON,GIE ; set global interrupt enable for above ; check if a switch is pressed bcf FLAG_1,0 ; clear multiplex update flag MULTIP btfss FLAG_1,0 ; check if multiplex update occured goto MULTIP ; wait for new multiplex update for display btfsc PORTA,4 ; if a switch is pressed, then bit 4 will be low goto SWITCH ; no switch pressed so look again ; check for Cal switch bcf INTCON,GIE ; clear interrupts bcf ERR_FLG,0 ; clear error flag when any switch pressed movf PORTA,w ; look at RA0-RA2 movwf TEMP_1 ; store in temporary memory iorlw B'00000111' ; bit 0-2 high movwf PORTA ; place in port A, displays off movlw 0x1F ; delay period movwf VALUE_1 ; VALUE_1 = w DELOOP decfsz VALUE_1,f ; decrease VALUE_1, skip if zero goto DELOOP btfss PORTA,4 ; is the cal switch pressed goto CALIBRT ; yes it is the cal switch movf TEMP_1,w ; retrieve port A bit 0-2 movwf PORTA ; port A bits 0-2 as before nop ; give time for ports to change nop nop btfsc PORTA,4 ; if a switch is pressed, then bit 4 will be low goto SWITCH ; no switch pressed so look again btfsc PORTA,0 ; is it the mode switch goto D_U_CHK goto MODE D_U_CHK btfss REPEAT,1 ; is on/off flag on goto WAIT ; no up down selection allowed when speed alarm unit is off btfsc PORTA,1 ; is it the Down switch goto U_CHK goto DOWN U_CHK btfsc PORTA,2 ; is it the UP switch goto SWITCH ; no switch reading goto UP
Code:MODE btfss REPEAT,1 ; bit 1 a '1' for on (on/off flag) goto SET_1 ; was off so turn on btfsc REPEAT,3 ; speedo on/off flag goto BYSPD btfss REPEAT,2 ; speedometer or alarm set mode goto SET_2 ; repeat1 status same, repeat2 =1 BYSPD bcf REPEAT,1 ; if set then clear on/off flag bcf REPEAT,2 ; clear speedometer flag bcf INTCON,INTE ; clear interrupt enable for RB0 clrf PULSE_CNT ; clear pulse counter clrf TIME_CNT1 ; clear time counter 1 clrf TIME_CNT2 ; clear time counter 2 goto WAIT SET_2 bsf REPEAT,2 ; set speedometer flag goto NO_SET1 SET_1 bsf REPEAT,1 ; if clear then set on/off flag NO_SET1 bsf INTCON,INTE ; set interrupt enable for RB0 goto WAIT UP movf DISP1,w ; display1 to w register xorlw 0x05 ; compare with decimal'5' btfss STATUS,Z ; skip next instruction if Disp <9 decimal goto UP_1 ; increase display1 ; check for maximum on display movf DISP2,w ; look at display 2 xorlw 0x05 ; compare with a 5 btfss STATUS,Z ; is it 5 then check DISP3 goto DISP_UP movf DISP3,w ; look at disp3 xorlw 0x02 ; compare with a 1 btfsc STATUS,Z ; is it a 2 goto WAIT ; maximum of 255 on display so stop counting up ; digit overflow DISP_UP clrf DISP1 ; Disp value cleared as it was beyond BCD range (0-9) movf DISP2,w ; display2 value to w xorlw 0x09 ; compare with decimal'9' (H'9') btfss STATUS,Z ; skip next instruction if Disp <9 decimal goto UP_2 ; increase display2 clrf DISP2 ; Disp value cleared as it was beyond BCD range (0-9) goto UP_3 ; increase display3 UP_1 movlw 0x05 ; a 5 in the display (count by 5's) movwf DISP1 ; display1 increased goto WAIT UP_2 incf DISP2,f ; display2 increased goto WAIT UP_3 incf DISP3,f ; display3 increased goto WAIT DOWN movf DISP1,w ; display1 to w register xorlw 0x00 ; compare with decimal'0' to see if was zero btfss STATUS,Z ; skip next instruction if Disp 0 decimal goto DN_1 ; decrease display1 ; check for display minimum movf DISP2,w ; look at display 2 xorlw 0x00 ; compare with 0 btfss STATUS,Z ; goto DISP_DN ; not 0 so can count down movf DISP3,w ; look at display 3 xorlw 0x00 ; compare with 0 btfsc STATUS,Z goto WAIT ; do not decrease beyond 000 DISP_DN movlw H'05' ; place a 5 in display1 movwf DISP1 ; disp1 = 5 movf DISP2,w ; display2 value to w xorlw 0x00 ; compare with decimal'0' to see if 0 btfss STATUS,Z ; skip next instruction if Disp 0 decimal goto DN_2 ; decrease display2 movlw H'09' ; Disp value = 9 movwf DISP2 goto DN_3 ; decrease display3 DN_1 clrf DISP1 ; display1 decreased to 0 goto WAIT DN_2 decf DISP2,f ; display2 decreased goto WAIT DN_3 decf DISP3,f ; display3 decreased ; wait period (delay plus EEPROM write time) ; delay loop plus apply tone to piezo alarm as switch press acknowledgement WAIT bsf INTCON,GIE ; allow global interrupts movlw D'100' ; set delay period for repeat of value 2 delay (sets key ; acknowledge tone frequency) movwf VALUE_1 ; VALUE_1 = w movlw D'50' ; set delay period value 2 (also sets key acknowledge tone period) LOOP_1 movwf VALUE_2 ; VALUE_2 = w LOOP_2 decfsz VALUE_2,f ; decrease VALUE_2, skip if zero goto LOOP_2 btfsc PORTA,3 ; alarm output check if high or low goto CLR_T bsf PORTA,3 ; alarm out high DEC_V1 decfsz VALUE_1,f ; decrease VALUE_1, skip if zero goto LOOP_1 bsf PORTA,3 ; alarm out high goto DELTME ; delay time CLR_T bcf PORTA,3 ; alarm out low goto DEC_V1 ; more delay time DELTME movlw D'50' ; set delay period movwf VALUE_1 ; VALUE_1 = w movlw D'255' ; set delay period value 2 LP_1 movwf VALUE_2 ; VALUE_2 = w LP_2 decfsz VALUE_2,f ; decrease VALUE_2, skip if zero goto LP_2 decfsz VALUE_1,f ; decrease VALUE_1, skip if zero goto LP_1 ; EEPROM write. Store new display values in EEPROM EPWRT movlw EEPROM1 ; address for EEPROM1 movwf EEADR ; address to write movf DISP1,w ; display1 data to w call EWRITE ; EEPROM write sequence movlw EEPROM2 ; address for EEPROM2 movwf EEADR ; address for write movf DISP2,w call EWRITE movlw EEPROM3 ; address for EEPROM3 movwf EEADR ; address for write movf DISP3,w call EWRITE movlw EEPROM4 ; address for EEPROM4 movwf EEADR ; address to write to movf REPEAT,w ; repeat values (bit 0 is alarm repeat, bit 1 is on/off) call EWRITE ; when a new speed setting is selected recalculate speed equivalent value bcf INTCON,GIE ; disable interrupts call SPDEQIV ; recalculate speed equivalent value bsf INTCON,GIE ; enable interrupts goto CLOSED ; out from EEPROM write ; subroutine to write to EEPROM EWRITE bcf FLAG_1,6 ; EEPROM write repeat flag movwf TEMP_2 ; store w in temporary storage EWRIT movf TEMP_2,w ; place value in w (used for read data sequence) movwf EEDATA ; data register bcf INTCON,GIE ; disable interrupts bsf STATUS,RP0 ; select bank 1 bsf EECON1,WREN ; enable write movlw 0x55 ; place 55H in w for write sequence movwf EECON2 ; write 55H to EECON2 movlw 0xAA ; AAH to w movwf EECON2 ; write AA to EECON2 bsf EECON1,WR ; set WR bit and begin write sequence bsf INTCON,GIE ; enable interrupts bcf EECON1,WREN ; clear WREN bit WRITE btfsc EECON1,WR ; skip if write complete WR=0 when write complete goto WRITE ; not written yet bcf EECON1,EEIF ; clear write interrupt flag ; read EEPROM DATA and check if written correctly bsf STATUS,RP0 ; select memory bank 1 bsf EECON1,RD ; read EEPROM RD_AGN nop btfsc EECON1,RD ; skip if RD low (read complete) goto RD_AGN ; wait for low RD bcf STATUS,RP0 ; select bank 0 movf EEDATA,w ; EEPROM value in w subwf EEDATA,w ; compare read value with value stored btfsc STATUS,z ; skip if not the same return ; value correctly written btfsc FLAG_1,6 ; write repeat bit, skip if clear and rewrite return bsf FLAG_1,6 ; set repeat flag rewrite once only goto EWRIT ; rewrite as not written correctly ; wait for switch to open (must test for closed switch when RA0, RA1 and RA2 are low ; because switch will appear open at RA4 when switch pull down via RA0-RA2 is high) CLOSED bcf FLAG_1,1 ; clear flag that indicates switch closed call ON ; check for closed switch call ON ; do three times to return to original switch closure call ON ; call ON ; do again just in case missed an interrupt during call call ON ; do again just in case missed one interrupt during call btfsc FLAG_1,1 ; was switch closed goto CLOSED ; yes go to check again goto SWITCH ; switch open so out ; subroutine to wait for switch to reopen ON bcf INTCON,T0IE ; prevent multiplex update bcf FLAG_1,0 ; clear flag that indicates update interrupt for display RE_CHK btfsc PORTA,4 ; check if switch closed goto OPEN bsf FLAG_1,1 ; switch closed so set flag bsf INTCON,T0IE ; allow multiplex interrupt goto RE_CHK ; closed so check till open OPEN bcf FLAG_1,0 ; clear multiplex update flag wait for next multiplex update bsf INTCON,T0IE ; allow multiplex update FLG_TST btfss FLAG_1,0 ; is flag set indicating a new interrupt for multiplexing goto FLG_TST ; wait return ; calibrate routine CALIBRT btfss REPEAT,1 ; is on/off flag on goto WAIT ; no calibration allowed when speed alarm unit is off btfsc REPEAT,2 ; is speedometer on goto WAIT ; no calibration if speedometer mode bcf INTCON,GIE ; disable interrupts clrf PULSE_CNT ; clear pulse counter clrf TIME_CNT1 ; clear time counter 1 clrf TIME_CNT2 ; clear time counter 2 bsf FLAG_1,7 ; calibrate flag set bcf INTCON,T0IF ; clear timer interrupt flag bcf INTCON,INTF ; clear interrupt flag bsf INTCON,GIE ; allow interrupts FLG1_CK btfsc FLAG_1,7 ; wait for end of calibrate, skip if end goto FLG1_CK ; recheck flag 1 bit 7 (cleared at end of calibration) ; store new calibration count numbers in EEPROM movlw EEPROM5 ; address for EEPROM5 movwf EEADR ; address to write movf TIME_CNT3,w ; counter 3 to w call EWRITE ; EEPROM write sequence movlw EEPROM6 ; address for EEPROM6 movwf EEADR ; address to write movf TIME_CNT4,w ; counter 4 to w call EWRITE ; EEPROM write sequence goto SWITCH ; check for a new closed switch ; Subroutine to convert from 8-bit binary to 2-digit BCD (packed) ; Binary value is in BIN_0 ; Result in BCD is in BCD_0 & BCD_1. ; BCD_0 is MSB, BCD_1 is LSB BCD bcf STATUS,c ; clear carry bit movlw D'8' movwf CNT_8 ; 8 in count clrf BCD_0 clrf BCD_1 ; set BCD registers to 0 LOOPBCD rlf BIN_0,f ; shift left binary registers rlf BCD_1,f ; MSB shift left rlf BCD_0,f ; LSB shift left BCD registers decfsz CNT_8,f ; reduce count value return when 0 goto DECADJ ; continue decimal adjust return ; completed decimal to BCD operation ; subroutine decimal adjust DECADJ movlw BCD_1 ; BCD LSB address movwf FSR ; pointer for BCD1 call ADJBCD ; subroutine to adjust BCD movlw BCD_0 ; BCD MS address movwf FSR ; pointer for BCD0 call ADJBCD goto LOOPBCD ; subroutine adjust BCD ADJBCD movlw 0x03 ; w has 03 addwf INDF,w ; add 03 to BCDx register (x is 0-1) movwf TEMP ; store w btfsc TEMP,3 ; test if >7 movwf INDF ; save as LS digit movlw 0x30 ; 3 for MSbyte addwf INDF,w ; add 30 to BCDx register movwf TEMP ; store w in temp btfsc TEMP,7 ; test if >7 movwf INDF ; save as MS digit return ; end subroutine end
Bookmarks