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.

Can CCP do this on 16F876A? :(

Status
Not open for further replies.
BTW, I simulated your code with MPLAB SIM, and used the stimulus feature to feed it a 500 cycle pulse (100 microseconds) and it got the right answer (500).

I think you should change it so that when it reaches the end it just does a GOTO back to right after where you set T1CON, so that it looks for another pulse.

Mike
 
Hi Mike,

Mate, I have tried using the code below and I am getting some weird values on PORTD and PORTB.

Basically, I am using a signal generator with TTL square wave. When the input is 1kHz, the value on PORTD [HIGH byte] is 1 and the value on PORTB is 244 [in binary]. I was hoping to get a value of the half period [width of the signal] i.e. 2 msec. And when I am using a signal of 10kHz, the only value is on PORTB which is 51[in binary].

Please enlighten me on this.

Cheers.


Code:
	list p=16f877a

       include "p16f877a.inc"
		errorlevel -302

	__config _LVP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF & _DEBUG_OFF

	cblock	0x020			;start of general purpose registers
		H1
		H2
		L1
		L2
		AnsH
		AnsL	
		endc
; Start at the reset vector
             	org     0x000
       		goto    Start

Start	org		0x010
		clrf	PORTB
		clrf	PORTD
		clrf	PORTC
		clrf	H1
		clrf	H2
		clrf	L1
		clrf	L2
		clrf	AnsH
		clrf	AnsL
		clrf	TMR1H
		clrf	TMR1L
	;	clrf 	CCP1CON 
		clrf	CCPR1H
		clrf	CCPR1L
        	           bsf     STATUS,RP0      ;bank 1
       		 bcf     STATUS,RP1
		movlw	b'00000100'
		movwf	TRISC
       		 movlw   b'00000000'
       		 movwf   TRISB           ;portb [7-0] outputs
		movlw   b'00000000'
       		 movwf   TRISD			;portd output
		movlw	0x06
		movwf	ADCON1
      						    ; all inputs DIGITAL
		bcf      STATUS,RP0		;bank0
	
;**********************************************

Main:		
		movlw 	b'00000001'       ;timer 1 using to capture, prescaler 1:1 
		movwf 	T1CON 

		movlw 	b'00000101'
		movwf 	CCP1CON    		 ;start with rising CAPTURE 
		bcf	PIR1,CCP1IF
Wait:
		btfss 	PIR1,CCP1IF 
		goto 	Wait
		movf 	CCPR1H,W     ;save the value in H2 and L2 {lower value} 
		movwf	H2
		movf 	CCPR1L,W
		movwf	L2
		bcf	PIR1,CCP1IF
;
		movlw 	b'00000100'                    ;config CCP1 to faling 
		movwf 	CCP1CON   
		bcf	PIR1,CCP1IF
Wait1:
		btfss 	PIR1,CCP1IF 
		goto 	Wait1

		movf    CCPR1H,W 		;save now the value in H1,L1
		movwf	H1
		movf    CCPR1L,W  
		movwf	L1
		bcf 	PIR1,CCP1IF     ;clr flag CCP1                     

;SUB Higher value H2,L2 from current captured value H1,L1

SUB:
		movf	L2,W
		subwf	L1,W
		movwf	AnsL
		movwf	PORTB

		btfss  STATUS, C
		goto   BORROW
		goto   SUB_1
BORROW:
		decf   H1, F
	
SUB_1:	movf	H2,W
		subwf	H1,W
		movwf	AnsH
		movwf	PORTD
		goto	Main
	
;************************************************
		
		end
 
bjox1 said:
Hi Mike,
Mate, I have tried using the code below and I am getting some weird values on PORTD and PORTB.

Basically, I am using a signal generator with TTL square wave. When the input is 1kHz, the value on PORTD [HIGH byte] is 1 and the value on PORTB is 244 [in binary]. I was hoping to get a value of the half period [width of the signal] i.e. 2 msec. And when I am using a signal of 10kHz, the only value is on PORTB which is 51[in binary].

Please enlighten me on this.

Cheers.
Are you sure that your signal generator was set to 1KHz and 10KHz?

The values you got (1,244) and (0,51) are what you would expect if the signal generator was set to 10KHz and 100KHz.

high byte = 1
low byte = 244
is a value of 01F4h which is 500. This number is a count of the instruction cycles counted. Since your clock is at 20MHz (it is at 20MHz, right?) then one instruction cycle is .2 microseconds (instruction clock is 20MHz/4 = 5MHz). So 0.2 times 500 is 100 microseconds per cycle, which is 10 KHz.
You would also get this if you used the formula I gave earlier:

frequency = 5,000,000 / time = 5,000,000 / 500 = 10,000 = 10 KHz

Likewise

high byte = 0
low byte = 51
is a value just 51. So 0.2 times 51 is 10.2 microseconds per cycle, which is 98 KHz...close to 100 KHz.

I think either your signal generator isn't doing what you think, or your clock is running at 2 MHz instead of 20 MHz.

Mike
 
Mike,

I am sorry for not making it clear [I am sure I did in my last few post]. I am using 4MHz XT.

frequency = 5,000,000 / time = 5,000,000 / 500 = 10,000 = 10 KHz
Mike, i am getting 2kHz where I am supposed to get 500Hz. [1us times 500 =2kHz]

Are you sure that your signal generator was set to 1KHz and 10KHz?
Mike, Just now I have double checked it using an oscilloscope.

Thanks again.

<EDIT> Mike, I think I made a fool of myself. :D

I guess,I am not sure, but 1kHz is 1000us in time. Halving it gives 500us. So half in time domain is double in freq domain. Thus 2kHz.

Mike, please advice me if I am correct.
 
Last edited:
bjox1 said:
I think I made a fool of myself. :D

I guess,I am not sure, but 1kHz is 1000us in time. Halving it gives 500us. So half in time domain is double in freq domain. Thus 2kHz.

Mike, please advice me if I am correct.

As Mike50 isn't around, I'll answer your question.

As your crystal is 4MHz then the timer is clocked at 1MHz or every 1uS. Therefore your frequency calculation is,
frequency = 1,000,000 / time = 1,000,000 / 500 = 2,000 = 2 KHz

As you are only measuring half the waveform, from rising to falling edge, you are getting a value that is double the frequency. Hence your frequency is 1kHz.

Mike.
 
Pommie said:
As Mike50 isn't around, I'll answer your question.

As your crystal is 4MHz then the timer is clocked at 1MHz or every 1uS. Therefore your frequency calculation is,
frequency = 1,000,000 / time = 1,000,000 / 500 = 2,000 = 2 KHz

As you are only measuring half the waveform, from rising to falling edge, you are getting a value that is double the frequency. Hence your frequency is 1kHz.

Mike.
Mike,

Good thing you were there. I forgot that he was only measuring from leading to trailing edge, not the whole cycle. And I thought his clock was 20 MHz, as that is what I had been assuming all along.

But your analysis makes perfect sense...It looked to me that something was off by a factor of 10, and a 4 MHz clock and only measuring half the waveform gives exactly a factor of 10.

So now, to complete your project you want to get a 20 MHz crystal and the rest is just a small matter of programming :)

Mike
 
Brilliant explanation guys!

I truly appreciate that.

-I was wondering what will be the max freq up to I can measure the width?

and - While doing the 16 bit division, do I need the 16 bit remainder value as well??

Thanks again guys.
 
bjox1 said:
Brilliant explanation guys!

I truly appreciate that.

-I was wondering what will be the max freq up to I can measure the width?
Well that depends on how much accuracy you need. But, best you can do will depend on how many instructions you execute between the time that CCP1IF turns on and the time that you are ready to read it again. In the code you have running that comes to about 13 instruction times. With your 4MHz clock, that is about 13 microseconds. From the time you copy out the capture register until the next time you could copy it out is about 13 microseconds. So the highest frequency you could detect would be about 77 KHz. But that is well above the highest frequency you said you needed to detect (which was 10 KHz).

With the 4 MHz clock and a 10 KHz signal, there are 100 clocks from leading edge to leading edge. So you wouldn't be able to measure the phase angle to a precision better than about 4 degrees. At 20 MHz you could measure it to within 1 degree.

bjox1 said:
and - While doing the 16 bit division, do I need the 16 bit remainder value as well??
Well, what do you think? You could use it to round the answer, but personally I wouldn't worry about it.

Mike
 
Thanks a trillion Mike. I really appreciate that.

mike50 said:
With the 4 MHz clock and a 10 KHz signal, there are 100 clocks from leading edge to leading edge. So you wouldn't be able to measure the phase angle to a precision better than about 4 degrees. At 20 MHz you could measure it to within 1 degree.

Mike

But how did you calculate 4 deg??:confused:
 
bjox1 said:
Thanks a trillion Mike. I really appreciate that.



But how did you calculate 4 deg??:confused:

With a 4 MHz crystal, Timer1 increments each microsecond. With a 10 KHz signal you get a leading edge every 100 microseconds. So the time you will measure between sucessive leading edges will be 100. The delay you measure between the leading edge of signal 1 and the leading edge of signal 2 must be between 0 and 100. So you can only divide the 360 degrees into 100 parts. If you increase the measured value by 1 it increases the phase angle by 3.6 degrees...which I rounded up to 4.

Mike
 
Mike,
Does it mean that with the same settings, the phase error @ 10kHz is 3.6 degrees but now if the user changes the signal to 1kHz, does it mean that the phase error for the different freq will be different??
 
With a 4 MHz crystal, Timer1 increments each microsecond. With a 1 KHz signal you get a leading edge every 1000 microseconds. So the time you will measure between sucessive leading edges will be 1000. The delay you measure between the leading edge of signal 1 and the leading edge of signal 2 must be between 0 and 1000. So you can only divide the 360 degrees into 1000 parts. If you increase the measured value by 1 it increases the phase angle by .36 degrees.

See how that works?

Mike
 
Mike,

Thank you once again for ur kind explanation. :)

Mate, After successfully doing the width exercise, I have attempted the actual code. The code is set to find the phase difference between CCP1 and CCP2 pin signals. I am not getting any values on the output LEDs. :(

I am feeding 1kHz signal on CCP1 pin and the CCP2 pin has the same signal with 150 us delay.

So CCP1- 1kHz signal
CCP2 pin – 1kHz with 150 usec delay.

My code does this:

- Capture CCP1a , CCP1b and CCP2.

- Sub -routine ‘SUB1’ subtracts CCP1a from CCP1b to give me the period of the signal. The 16 bit ans is then saved in memory reg btmH and btmL. i.e. Bottom H and Bottom L [bottom refers to the denominator in the Division sub- routine].

- Then sub-routine ‘SUB2’ subtracts CCP1b from CCP2 and the ans is saved in memory registers topH and topL [Top refers to the numerator].

- Then the sub-routine ‘Div’ performs 16 by 16 bit division and put the quotient [RESULTS] value in qH and qL thus on PORTD and PORTB.

Mike, I am not even getting any values on the LEDs.

Could you please look at my code. The division routine worked fine separately. I am guessing the division might be the wrong bit.

-As the numerator [delay value between 0-1000] is going to be always smaller than the denominator[the denominator,time period, is 1000], the quotient will always be less the 1. Is that the reason my code doesn’t work??
- Mike, with 150 usec delay, what value will I be expecting on the LEDs??

I will be very very grateful if you could help me on this as well.

Thanks again mike.

Code:
list p=16f877a

       include "p16f877a.inc"
		errorlevel -302

	__config _LVP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF & _DEBUG_OFF

	cblock	0x020			;start of general purpose registers
			CCP1aH
			CCP1aL
			CCP1bH
			CCP1bL
			CCP2H
			CCP2L	
			topH  
		endc

	cblock	0x070
  			 
			topL   				
			btmH    		
			btmL   			
			qH     
			qL    
			count   
			index   
		endc


; Start at the reset vector
        	org     0x000
        	goto    Start

Start		org		0x010
			clrf	PORTB
			clrf	PORTD
			clrf	PORTC
			clrf	CCP1aH
			clrf	CCP1aL
			clrf	CCP1bH
			clrf	CCP1bL
			clrf	CCP2H
			clrf	CCP2L
			clrf	TMR1H
			clrf	TMR1L
			clrf 	count
			clrf	topH
			clrf	topL
			clrf	btmH
			clrf	btmL
	;	clrf 	CCP1CON 
			clrf	CCPR1H
			clrf	CCPR1L
			clrf	CCPR2H
			clrf	CCPR2L
       		bsf     STATUS,RP0      ;bank 1
       	    bcf     STATUS,RP1
			movlw	b'00000110'
			movwf	TRISC
      		movlw   b'00000000'
        	movwf   TRISB           ;portb [7-0] outputs
			movlw   b'00000000'
       		movwf   TRISD			;portd output
      						    ; all inputs DIGITAL
			bcf		STATUS,RP0		;bank0
	;		bcf		PIR1,CCP1IF
;**********************************************

Main:	
			movlw 	b'00000000' 	 ;timer 1 using to capture, prescaler 1:1 
			movwf 	T1CON 
			bsf		T1CON,TMR1ON	

			movlw 	b'00000101'
			movwf 	CCP1CON    		 ;start with rising CAPTURE 
			movlw 	b'00000101'
			movwf 	CCP2CON    		 ;start CCP2 with rising CAPTURE 
			bcf		PIR1,CCP1IF
			bcf		PIR2,CCP2IF
Wait:
			btfss 	PIR1,CCP1IF 
			goto 	Wait
			movf 	CCPR1H,W 		;save the value in H2 and L2 {lower value} 
			movwf	CCP1aH
			movf 	CCPR1L,W
			movwf	CCP1aL
			bcf		PIR1,CCP1IF
;
Wait1:
			btfss 	PIR1,CCP1IF 
			goto 	Wait1

			movf    CCPR1H,W 		;save now the value in H1,L1
			movwf	CCP1bH
			movf    CCPR1L,W  
			movwf	CCP1bL
			bcf 	PIR1,CCP1IF     ;clr flag CCP1                     


		
Wait2
			btfss 	PIR2,CCP2IF 
			goto 	Wait2

			movf    CCPR2H,W 		;save now the value in H1,L1
			movwf	CCP2H
			movf    CCPR2L,W  
			movwf	CCP2L
			bcf 	PIR2,CCP2IF     ;clr flag CCP1  

;*********CCP1b-CCP1a*******************		
SUB1:
		

;*******CCP2-CCP1b****************
SUB2:

	
;***********DIVISION***********************
		
Div:
             call	Divide                
             movf   qL,w           ;@@@@@ RESULTS @@@@@@
             movwf	PORTB
             movf	qH,w            ; on LEDs connected to rb and rc. 
             movwf	PORTD
             goto	Main           ;-------LOOP BACK TO START----

Divide:     
			 movf 	btmH,w             ; Check for division by 0.
             iorwf	btmL,w               
             btfsc 	STATUS,Z             
             bsf	PORTB,0	          ; //**Error code If btm is Zero:PORTB PIN 0 Light LED//** 
             movlw 	d'1'              ; Otherwise, initialize variables
             movwf 	count
             clrf 	index              ; for the division. 
             clrf 	qH                    
             clrf 	qL                    

Divide_sh_loop:
			 btfsc	btmH,7          ; Shift divisor left
             goto   Divide_d1
             bcf	STATUS,C            ; until msb is in 
             rlf 	btmL,1                ; btmH.7. 
             rlf 	btmH,1                ; count = no. of shifts+1. 
             incf   count,1                 
             goto   Divide_sh_loop       
 
Divide_d1:
		     bcf	STATUS,C               
             rlf	qL,1                   ; Shift quotient left.
             rlf 	qH,1                     
             movf	btmL,w              ; top = top - btm. 
             subwf  topL,1
             btfsc  STATUS,C          ; If top - btm < 0 then 
             goto   Divide_d2
             movlw  d'1'               ; top = top + btm
             subwf  topH,1
             btfsc  STATUS,C           ; The idea is to do the 
             goto   Divide_d2
             incf   topH,1                 ; the subtraction and comparison
             movf   btmL,w                ; (top > btm?) in one step. 
             addwf  topL,1
             goto   Divide_reentr         ; Then, if btm > top, undo 

Divide_d2:
		     movf   btmH,w                ; the subtraction by adding
             subwf  topH,1
             btfss  STATUS,C             ; top and btm back together
             goto   Divide_less           ;
             bsf    qL,0      
          
Divide_reentr
             bcf    STATUS,C             
             rrf    btmH,1                  
             rrf    btmL,1                   
             decfsz count,1               
             goto   Divide_d1
             retlw  0h                   ; Return w/ remainder in top
                                        ; and result in q.&nsp;
Divide_less  
			 movf   btmL,w                ; btm > top, so 
             addwf  topL,1
             btfsc  STATUS,C           ; undo the subtraction by
             incf   topH,1                 ; adding them back together. 
             movf   btmH,w                
             addwf  topH,1
             goto   Divide_reentr      ; 

             
             
             end
 
Last edited:
bjox1 said:
Mike,

Thank you once again for ur kind explanation. :)

Mate, After successfully doing the width exercise, I have attempted the actual code. The code is set to find the phase difference between CCP1 and CCP2 pin signals. I am not getting any values on the output LEDs. :(

I am feeding 1kHz signal on CCP1 pin and the CCP2 pin has the same signal with 150 us delay.

So CCP1- 1kHz signal
CCP2 pin – 1kHz with 150 usec delay.

My code does this:

- Capture CCP1a , CCP1b and CCP2.

- Sub -routine ‘SUB1’ subtracts CCP1a from CCP1b to give me the period of the signal. The 16 bit ans is then saved in memory reg btmH and btmL. i.e. Bottom H and Bottom L [bottom refers to the denominator in the Division sub- routine].

- Then sub-routine ‘SUB2’ subtracts CCP1b from CCP2 and the ans is saved in memory registers topH and topL [Top refers to the numerator].

- Then the sub-routine ‘Div’ performs 16 by 16 bit division and put the quotient [RESULTS] value in qH and qL thus on PORTD and PORTB.

Mike, I am not even getting any values on the LEDs.

Could you please look at my code. The division routine worked fine separately. I am guessing the division might be the wrong bit.

-As the numerator [delay value between 0-1000] is going to be always smaller than the denominator[the denominator,time period, is 1000], the quotient will always be less the 1. Is that the reason my code doesn’t work??
Yes, of course. Don't you remember that you need to multiply by 360 BEFORE you do the divide?
bjox1 said:
- Mike, with 150 usec delay, what value will I be expecting on the LEDs??
Hard to say what you are expecting, but if you had multiplied by 360 before doing the divide, I would expect that the result would be 54 degrees.
bjox1 said:
I will be very very grateful if you could help me on this as well.

Thanks again mike.

Code:
list p=16f877a

       include "p16f877a.inc"
		errorlevel -302

	__config _LVP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF & _DEBUG_OFF

	cblock	0x020			;start of general purpose registers
			CCP1aH
			CCP1aL
			CCP1bH
			CCP1bL
			CCP2H
			CCP2L	
			topH  
		endc

	cblock	0x070
  			 
			topL   				
			btmH    		
			btmL   			
			qH     
			qL    
			count   
			index   
		endc


; Start at the reset vector
        	org     0x000
        	goto    Start

Start		org		0x010
			clrf	PORTB
			clrf	PORTD
			clrf	PORTC
			clrf	CCP1aH
			clrf	CCP1aL
			clrf	CCP1bH
			clrf	CCP1bL
			clrf	CCP2H
			clrf	CCP2L
			clrf	TMR1H
			clrf	TMR1L
			clrf 	count
			clrf	topH
			clrf	topL
			clrf	btmH
			clrf	btmL
	;	clrf 	CCP1CON 
			clrf	CCPR1H
			clrf	CCPR1L
			clrf	CCPR2H
			clrf	CCPR2L
       		bsf     STATUS,RP0      ;bank 1
       	    bcf     STATUS,RP1
			movlw	b'00000110'
			movwf	TRISC
      		movlw   b'00000000'
        	movwf   TRISB           ;portb [7-0] outputs
			movlw   b'00000000'
       		movwf   TRISD			;portd output
      						    ; all inputs DIGITAL
			bcf		STATUS,RP0		;bank0
	;		bcf		PIR1,CCP1IF
;**********************************************

Main:	
			movlw 	b'00000000' 	 ;timer 1 using to capture, prescaler 1:1 
			movwf 	T1CON 
			bsf		T1CON,TMR1ON	

			movlw 	b'00000101'
			movwf 	CCP1CON    		 ;start with rising CAPTURE 
			movlw 	b'00000101'
			movwf 	CCP2CON    		 ;start CCP2 with rising CAPTURE 
			bcf		PIR1,CCP1IF
			bcf		PIR2,CCP2IF
Wait:
			btfss 	PIR1,CCP1IF 
			goto 	Wait
			movf 	CCPR1H,W 		;save the value in H2 and L2 {lower value} 
			movwf	CCP1aH
			movf 	CCPR1L,W
			movwf	CCP1aL
			bcf		PIR1,CCP1IF
;
Wait1:
			btfss 	PIR1,CCP1IF 
			goto 	Wait1

			movf    CCPR1H,W 		;save now the value in H1,L1
			movwf	CCP1bH
			movf    CCPR1L,W  
			movwf	CCP1bL
			bcf 	PIR1,CCP1IF     ;clr flag CCP1                     


		
Wait2
			btfss 	PIR2,CCP2IF 
			goto 	Wait2

			movf    CCPR2H,W 		;save now the value in H1,L1
			movwf	CCP2H
			movf    CCPR2L,W  
			movwf	CCP2L
			bcf 	PIR2,CCP2IF     ;clr flag CCP1  

;*********CCP1b-CCP1a*******************		
SUB1:
			movf	CCP1aL,W
			subwf	CCP1bL,W
			movwf	btmL
			;movwf	PORTB

			btfss  STATUS, C
			goto   BORROW1
			goto   SUB_1
BORROW1:
			decf   CCP1bH, F
	
SUB_1:	
			movf	CCP1aH,W
			subwf	CCP1bH,W
			movwf	btmH
			;movwf	PORTD

;*******CCP2-CCP1b****************
SUB2:
			movf	CCP1bL,W
			subwf	CCP2L,W
			movwf	topL
			;movwf	PORTB

			btfss  STATUS, C
			goto   BORROW2
			goto   SUB_2
BORROW2:
			decf   CCP2H, F
	
SUB_2:
			movf	CCP1bH,W
			subwf	CCP2H,W
			movwf	topH
		;	movwf	PORTD
	
;***********DIVISION***********************
		
Div:
             call	Divide                
             movf   qL,w           ;@@@@@ RESULTS @@@@@@
             movwf	PORTB
             movf	qH,w            ; on LEDs connected to rb and rc. 
             movwf	PORTD
             goto	Main           ;-------LOOP BACK TO START----

Divide:     
			 movf 	btmH,w             ; Check for division by 0.
             iorwf	btmL,w               
             btfsc 	STATUS,Z             
             bsf	PORTB,0	          ; //**Error code If btm is Zero:PORTB PIN 0 Light LED//** 
             movlw 	d'1'              ; Otherwise, initialize variables
             movwf 	count
             clrf 	index              ; for the division. 
             clrf 	qH                    
             clrf 	qL                    

Divide_sh_loop:
			 btfsc	btmH,7          ; Shift divisor left
             goto   Divide_d1
             bcf	STATUS,C            ; until msb is in 
             rlf 	btmL,1                ; btmH.7. 
             rlf 	btmH,1                ; count = no. of shifts+1. 
             incf   count,1                 
             goto   Divide_sh_loop       
 
Divide_d1:
		     bcf	STATUS,C               
             rlf	qL,1                   ; Shift quotient left.
             rlf 	qH,1                     
             movf	btmL,w              ; top = top - btm. 
             subwf  topL,1
             btfsc  STATUS,C          ; If top - btm < 0 then 
             goto   Divide_d2
             movlw  d'1'               ; top = top + btm
             subwf  topH,1
             btfsc  STATUS,C           ; The idea is to do the 
             goto   Divide_d2
             incf   topH,1                 ; the subtraction and comparison
             movf   btmL,w                ; (top > btm?) in one step. 
             addwf  topL,1
             goto   Divide_reentr         ; Then, if btm > top, undo 

Divide_d2:
		     movf   btmH,w                ; the subtraction by adding
             subwf  topH,1
             btfss  STATUS,C             ; top and btm back together
             goto   Divide_less           ;
             bsf    qL,0      
          
Divide_reentr
             bcf    STATUS,C             
             rrf    btmH,1                  
             rrf    btmL,1                   
             decfsz count,1               
             goto   Divide_d1
             retlw  0h                   ; Return w/ remainder in top
                                        ; and result in q.&nsp;
Divide_less  
			 movf   btmL,w                ; btm > top, so 
             addwf  topL,1
             btfsc  STATUS,C           ; undo the subtraction by
             incf   topH,1                 ; adding them back together. 
             movf   btmH,w                
             addwf  topH,1
             goto   Divide_reentr      ; 

             
             
             end
 
Thanks again for the reply mike.

Yes, of course. Don't you remember that you need to multiply by 360 BEFORE you do the divide?

Mike, I was wondering if it is at all possible for me to display just the time lag rather than phase as it would certainly save another routine of 16 by 16 multiplication??

And if I skip the 360 multiplication part, will I be stuck as the numerator will be smaller than the denominator??:confused:

Thanks again mate.
 
Last edited:
bjox1 said:
Thanks again for the reply mike.



Mike, I was wondering if it is at all possible for me to display just the time lag rather than phase as it would certainly save another routine of 16 by 16 multiplication??
You can do whatever you want to do. If you want to display the time lag that is fine with me. I don't know why you would ask me that...you should ask your instructor if that is okay. Of course, the time lag doesn't tell you the phase unless you also know the frequency.
bjox1 said:
And if I skip the 360 multiplication part, will I be stuck as the numerator will be smaller than the denominator??:confused:
You could multiply by 256 instead of 360. That is easy to do...just set topH equal to topL and then set topL to zero before you do the divide. In that case your output will be from 0 to 255...dividing a circle into 256 parts instead of 360.

But I don't know why you wouldn't just add the code to do the multiply (get it from the same place you got the divide routine).

Mike
 
mike50 said:
But I don't know why you wouldn't just add the code to do the multiply (get it from the same place you got the divide routine).

Mike

Mike,

I apologise if I ask too much but I found the code + u already have suggested this link. I am just out of my mind and can't understand it. :(

It says it's a simple 32 by 16 division but I don't understand the steps.

Let’s say I have got 4 reg: reg1,reg2,reg3,reg4 [numerator, values after multiplying 360 to topH & topL ] and btmH and btmL [denominator].

Could you Please explain or help me to re-write the following code.
Also I would like to check the ans on the LEDs on PORTB and PORTD.

I will really really appreciate that mike.

Thanks again.


Code:
divide movlw 32      ; 32-bit divide by 16-bit
       movwf bitcnt
       clrf remdrH   ; Clear remainder
       clrf remdrL

dvloop clrc          ; Set quotient bit to 0
                     ; Shift left dividend and quotient
       rlf divid0    ; lsb
       rlf divid1
       rlf divid2
       rlf divid3    ; lsb into carry
       rlf remdrL    ; and then into partial remainder
       rlf remdrH

       skpnc         ; Check for overflow
       goto subd
       movfw divisH  ; Compare partial remainder and divisor
       subwf remdrH,w
       skpz 
       goto testgt   ; Not equal so test if remdrH is greater
       movfw divisL  ; High bytes are equal, compare low bytes
       subwf remdrL,w
testgt skpc          ; Carry set if remdr >= divis
       goto remrlt

subd   movfw divisL  ; Subtract divisor from partial remainder
       subwf remdrL
       skpc          ; Test for borrow

       decf remdrH   ; Subtract borrow
       movfw divisH
       subwf remdrH
       bsf divid0,0  ; Set quotient bit to 1
                     ; Quotient replaces dividend which is lost
remrlt decfsz bitcnt
       goto dvloop
       return
 
Why would you want to re-write this divide code? Why not just use it as is?

I'm sure I could figure out how this divide code works if I wanted to spend the time, but I don't. You don't have to understand it to use it.

The simulator in MPLAB is a much better way to test out code like this to see if it does what you want than trying to run it on real hardware with LEDs for output.

Mike
 
mike50 said:
Why would you want to re-write this divide code? Why not just use it as is?

I'm sure I could figure out how this divide code works if I wanted to spend the time, but I don't. You don't have to understand it to use it.

The simulator in MPLAB is a much better way to test out code like this to see if it does what you want than trying to run it on real hardware with LEDs for output.

Mike

Mike,

So where shall I put the PORTB command? I mean the code doesn't explain where the quotient is saved?:confused:

Am I right in assuming that:
-divid0:divid3 are the numerator values and divisH and divisL are denominator?
- But I can't analyse where the output bytes are saved? I mean it doesn't say anywhere about the ans. Where will the ans be stored.Which register? :(

Thanks again Mike.
 
Last edited:
Oh, I thought you wanted to know exactly how it performed a divide.

Input to the divide is the dividend (the numerator) which is in divid0, divid1, divid2, and divid3. divid0 is the least significant byte and divid3 is the most significant and the divisor which is in divisH and divisL.

The output is in divid0, divid1, divid2 and divid3. Again with the least significant byte in divid0.

You didn't see this comment near the end of the code?

Code:
                     ; Quotient replaces dividend which is lost

You do know the words dividend, divisor and quotient, right?

Mike
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top