Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Subtract PIC16f690

Status
Not open for further replies.

lepass_7

New Member
Hey guys,
I am stuck on this and I 'll appreciate your help on this silly, i think, question. I try to compare two numbers the MAX_TEMP_HIGH and the HIGH_BYTE.
Code:
...
movlw	b'00000000'
	movwf	MAX_TEMP_HIGH
	movlw	b'00110010'
	movwf	MAX_TEMP_LOW
...
...
;make the comparison
		movf	HIGH_BYTE, 0			;w <-- HIGH_BYTE
		subwf	 MAX_TEMP_HIGH, 0	;w = MAX_TEMP_HIGH - w
		
		btfsc	STATUS, Z			;if STATUS<Z> == 1 its equal
		goto	checkLowByte
		btfsc	STATUS, C			;if STATUS<C> == 1 MAX_TEMP_HIGH < HIGH_BYTE
		goto	continueHeat
		goto	stopHeat

	checkLowByte
			
		movf	LOW_BYTE, 0			;w <-- LOW_BYTE
		subwf	MAX_TEMP_LOW, 0		;w = MAX_TEMP_LOW - w
		
		btfsc	STATUS, Z			;if STATUS<Z> == 1 its equal
		goto	stopHeat
		btfsc	STATUS, C			;if STATUS<C> == 1 MAX_TEMP_LOW < HIGH_LOW
		goto	continueHeat
if the HIGH_BYTE is zero so the PIC will try to compare the low Byte, but for some reason this wont happen. Any ideas?
 
Hi,

Just run your code in Mplab Sim with HighByte set to zero it runs fine as you can see, Z is 1 so it goes straight to checklowbyte as you say it should ....
 

Attachments

  • ScreenShot001.jpg
    ScreenShot001.jpg
    65.4 KB · Views: 150
On Nigels tutorials

Code:
;**************** 16 bit compare ****************

; Upon return, a code in w will indicate the outcome of the comparison. 
; If n1 > n2 then w = 1. If n1 < n2 then w =2. If n1 = n2 then w = 0. 
Comp16       	bcf 	Flags,		Z_	; Clear aux Z bit.
             	        movf 	n2L,		w 	; w = n2L
             	        subwf n1L,		0	; w = n1L-n2L <Microchip instruction>
             	        btfsc 	STATUS,		Z	; Copy Z bit to Z_. 
             	        bsf 	Flags,		Z_             
             	        movf 	n2H,		w 	; If n1L-n2L underflowed, 
             	        btfsc 	STATUS,		C 	; then increment n2H (same
             	        goto 	Comp16_cont
             	        incf 	n2H,		w 	; as decrementing n1H).
             	        btfsc 	STATUS,		Z 	; If n2H overflows, n1 must be < n2
             	        retlw 	D'2'			; so return with 2 in w.
Comp16_cont  	subwf 	n1H,		0	; w = n1H-n2H  <Microchip instruction>
             	        btfss 	STATUS,	C	; If n1H underflows, n1<n2 retw 2 ; so return with 2 in w. jnb Z_,:cont2 ; By now we're suren1'>=n2. 
             	        btfsc 	STATUS,   Z	 ; If both z and Z_ are set, 
             	        retlw 	D'0'			; both subtractions resulted in 0, so
Comp16_cont2 	retlw 	D'1'			; n1=n2. Otherwise n1>n2.
 
Hey guys, thank you for answering me, i think i figure out what was the problem. The HIGH_BYTE is ADRESH and the LOW_BYTE is ADRESL of an A/D conversion but for some reason the first conversion was always wrong so the first time the code run was wrong so i run two conversions before storing the values to my variables:

Code:
	;call	Delay1min
		;test
		call	Delay1s
		call	A2d_read			;the result store into highByte, lowByte
		call	A2d_read	
			

		;here, we can check if the user turn the system off manually
		;we have to use a switch and not a button because every 1 min this will occure
		;read value
		btfss	PORTA, 1	
		goto	checkTime	 		;if PORTA<1> == 1 execute off button
		call	Delay1ms
		btfsc	PORTA, 1
		goto	stopHeat			;after debounce act

		

	checkTime
		
		;increase counter
		incf	COUNTER, 1			;COUNTER++
		movf	COUNTER, 0			;w <-- COUNTER
		subwf	MAX_TIME, 0			;w = MAX_TIME - w
		btfsc	STATUS, Z			;if MAX_TIME == COUNTER the next instruction is executed
		goto	stopHeat			;the system will work for MAX_TIME 	
		
		
		
		;make the comparison
		movf	HIGH_BYTE, 0			;w <-- HIGH_BYTE
		subwf	MAX_TEMP_HIGH, 0	;w = MAX_TEMP_HIGH - HIGH_BYTE
		btfsc	STATUS, Z			;if STATUS<Z> == 1 its equal
		goto	checkLowByte
		btfsc	STATUS, C			;if STATUS<C> == 1 MAX_TEMP_HIGH < HIGH_BYTE
		goto	continueHeat
		;goto	test
		bsf		PORTB, 6			;yellow led, the water is hot
		goto	stopHeat
	
		
	checkLowByte
		movf	LOW_BYTE, 0			;w <-- LOW_BYTE
		subwf	MAX_TEMP_LOW, 0		;w = MAX_TEMP_LOW - w
		
		btfsc	STATUS, Z			;if STATUS<Z> == 1 its equal
		goto	stopHeat
		btfsc	STATUS, C			;if STATUS<C> == 1 MAX_TEMP_LOW < HIGH_LOW
		goto	continueHeat
 
Hi,

The first ADC reading can be a little lower than the rest, as you say its settling all the voltages etc.

Although you have a delay before the first adc read you do another call straight away, unless your adc routine has some small delay its worthwhile doing another small delay before the second call.

As you take just single readings you will find the temp displayed may still fluctucate slightly, depends what resoultion you are working to.

I find it better to strip off the 2 lsbs and make the 10 bit result into 8 bits which is then very handy for running in say a x16 averaging routine which will give a much more stable result.
 
Hi,
First of all thank you. Yes you are right i make two calls of the adc routine and it will be silly if i didnt put some delay inside the routine(which i did, about five NOP). And i find it very usefull to stripp off the 2 lsbs, i ll use that suggestion.
And again thank you all guys.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top