Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Unexplained action of TMR0 in PIC

Status
Not open for further replies.

pebe

Advanced Member level 4
Full Member level 1
Joined
Dec 1, 2008
Messages
116
Helped
18
Reputation
36
Reaction score
18
Trophy points
1,298
Location
Scotland
Visit site
Activity points
1,893
I want to PWM a port of a PIC 12F629. I need a fairly high repetition rate so decided to do it within the timer interrupt sequence.

When the timer interrupt occurs, early in the procedure I turn on the port. Then I compare TMR0 with a reference number (ref) and when they are equal, the port is turned off. Then I exit the routine. As soon as TMR0 overflows there will be another interrupt and the port will turn on again. In that way the on/off ratio is determined by the value of ref/256.

Unfortunately, TMR0 does not seem to change once inside the interrupt routine. Looking at the block diagram in the 12F629 data sheet, I can see no reason why it shouldn’t.

Any ideas?
 

The entire program (a bit long to display here?) or just the interrupt routine?
 

I use that method to produce several PWM outputs at once in software so it should work. Possible reasons for failure could be:
1. Are you clearing the TMR0 interrupt flag to allow it to interrupt again?
2. Are you using any delay routines in the ISR that could be longer than the interrupt period itself?

We will have to see the code to be sure. If you post it, please use the ' # ' code tags from the message menu so it doesn't lose it's formatting.

Brian.
 

I've put the main prog in as well, in case the fault is in that.

The program has an initial delay of 2secs when switched on at port1(low), then the MS ratio ramps up from zero to 231/256 in a time period of about 6secs. When switched off with port1, the ramp reverses at the same rate.

The port is switching OK, but the PW rate does not change.

Code:
;MAIN PROGRAM ************************
start
	bcf		GPIO,0		;ensure port is off
		;wait for switch on
	btfsc 	GPIO,1             
	goto	start		;bit is set - input is high - switch is off
		;switch is on  -  start with reference number = 0
	clrf 		ref		;start ramp at zero
	
		;initial 2sec delay
	bcf		flags,running		;allow normal timer int	
	call 		timer2sec
	bsf 		GPIO,2		;##### test LED ##########
twosecdelay	
	btfss 	flags,tim
	goto 	twosecdelay		;loop until end of delay
		;end of 2sec delay
	bcf		flags,newstart		
  	bsf		flags,running	;show interrupt that prog is in normal running mode
    	       ;set clock counter to 13
  	movlw	.13
    	movwf	count     
    	
    	  ;-----------program loops here between interrupts--------
mainloop    	 ;wait for interrupt which will switch on port
	btfss	flags,newstart	      ;flag to send prog back to give 2sec time delay again
	goto	 mainloop			;normal measure in interrupt routine
	goto 	prestart    		;meter has gone to zero - new start required	
	
	  
measure	;'''''''''call to here from interrupt program''''''''''''''
			;pulse width ramps up form zero to a ratio of 231 in 256, in approx 6secs
			;ref = turn-off time.  ramps up to maxref 
					
	bcf		GPIO,4		;####### test LED ###########	
	bcf		GPIO,5		;####### test LED ###########	
	bsf 		GPIO,0		;turn on port	
	  ;measure 'on' period  (port is now on)
		;look for  tmr0 = ref to turn port off
int2		
	movwf	ref		;get ref number
	subwf	TMR0,0
	btfss	STATUS,Z
	goto	int2
	bcf		GPIO,0		;TMR0 = ref.  Turn off port			
			;port-on period ended		
	  
	decfsz	count,1		;1 in 13 ramp rate
	return		;loop until time to step up/down ref register (13 x 2ms)	
		;reload counter after 13 x 2.048ms = 26.62ms
		;(25.62ms x 231 = 6.15sec)
	movlw	.13
	movwf	count
	
		    ;test switch input			    
	btfsc 	GPIO,1             
	goto	s1		;bit is set - input is high - switch is off
	goto	s2		;input is low - switch is on

s1
	bsf		GPIO,4		;####### test LED #########
	movwf	ref		;switch is off - test file for 0
	btfss	STATUS,Z
	goto	s1a		;not zero
	bsf		flags,newstart		;gauge has run back to zero. loop back to include 2sec delay
	return	
s1a
	decf 	ref,1		;not at 0, so decrement	
	return	

s2
	bsf		GPIO,5		;####### test LED ##########		
	movwf	ref		;test if ref = maximum allowed
	subwf	maxref,0
	btfsc	STATUS,C	
	return		;ref = >maxref
	incf		ref,1		;ref was <maxref  
	return
		;end of 'measure' routine from timer interrupt

;end of main prog ********************
	

;SUBROUTINES ***************************

;Timer  (prescaler = div 8.  TMR0 clocks tim1 every 2.048ms. 
				;tim1 clocks tim2 every 524ms)				
				;set timer for 2sec count of   t1 =209;  t2 = 3
				;(209 x 2.048ms + 3 x 524ms = 2secs)
timer2sec				
	movlw	.209		;count of 209 x tim1
	movwf 	tim1  		;store
	movlw	3    		;count of 3 x tim2
	movwf	tim2
	bcf		flags,tim	;clear flag
	clrf		TMR0     	;reset timer counter
	bcf       	INTCON,2      ;T01F - Clear TMR0 flag bit to allow interrupt
	return
	
	;********end of timer subs**********

- - - Updated - - -

Sorry, I missed off the interrupt code!

Code:
	ORG     0x004             ; interrupt vector location
	movwf   w_temp            ; save off current W register contents
	movf	STATUS,w          ; move status register into W register
	movwf	status_temp       ; save off contents of STATUS register
	

	bcf       	INTCON,2      ;T01F - Clear TMR0 flag bit to allow interrupt and keep timer running	
	btfss     	flags,running   ;jump if not in delay mode
	goto	normal_int		;in 2sec delay  mode
	call		measure		;sub to prog to measure port turn-on time
		;go to interrupt routine to measure TMR0
	goto	endtimint		;exit	
	
normal_int
  	  		 ;2sec timer interrupt routine *******************			
	decfsz 	tim1,1		;decrement reg
	goto	endtimint
	decfsz	tim2,1		;decrement reg
	goto	endtimint
	bsf		flags,tim   	;set flag to show end of 2secs		
	
endtimint
	movf    	status_temp,w     ; retrieve copy of STATUS register
	movwf	STATUS            ; restore pre-isr STATUS register contents
	swapf   	w_temp,f
	swapf  	 w_temp,w          ; restore pre-isr W register contents
	retfie                    ; return from interrupt
 

I found the problem.
In two cases I had used "MOVWF ref" instead of "MOVF ref,0"
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top