PIC newbie - took ages to program and i still have bugs


Closed Thread
Results 1 to 15 of 15

Hybrid View

  1. #1
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default

    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

  2. #2
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default

    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

  3. #3
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default part 4

    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

  4. #4
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default part 5

    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

  5. #5
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default part 6

    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

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi,
    I'm not saying that you won't get any help but since this is a forum for PicBasic you MAY not get the help you're looking for. Something like the PICList may be more suitable if you're "writing" in, or having problems with ASM.

    BUT, with that being said, have you selected 16F84 in MPLAB? Configure/Select Device and then point to 16F84.

    /Henrik Olsson.

  7. #7
    Join Date
    Feb 2003
    Location
    Salt Lake City, Utah USA
    Posts
    517


    Did you find this post helpful? Yes | No

    Default

    as a starters,

    C:\DOCUMENTS AND SETTINGS\\MY DOCUMENTS\SPEED254.ASM 323 : Symbol not previously defined (z) Error[113]
    C:\DOCUMENTS AND SETTINGS\\MY DOCUMENTS\SPEED254.ASM 362 : Symbol not previously defined (c) Error[113]
    change commands that look like this (with c or z in them)

    Code:
    	btfsc	STATUS,z	; check if 0
    to this

    Code:
    	btfsc	STATUS,Z	; check if 0
    Paul Borgmeier
    Salt Lake City, UT
    USA
    __________________

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts