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.

Cant get timer0 to interrupt

Status
Not open for further replies.

2camjohn

Member
I have been trying to get timer0 to work on my pic16f628. I have read the datasheets and various websites on the subject. I think I must be overlooking something that is very simple.

Here is what I have done:




At the start of the program:

OPTION_REG.PS0 = 1
OPTION_REG.PS1 = 1
OPTION_REG.PS2 = 0

(Option reg bits 0 - 2 = 110 - sets prescalar to 4th option)

INTCON.INTE = 1
INTCON.T0IE = 1

(intcon bits INTE and T0IE to 1 - enable RB0 and timer0 interrupts)

INTCON.GIE = 1

(enable interrupts - all)





during the interrupt sequence I have

If INTCON.INTF = 1 Then
(if interrupt is generated by RB0)
*some code here, dependant on timer*

else
(else it must have been the timer)
*timer code here*

end if

INTCON.INTF = 0
INTCON.T0IF = 0
(enable timer and RB0 interrupts)
resume


The config i am using is:
IntRC osscilator
Power up timer Enabled
Watchdog timer Disabled


The problem is the RB0 interrupt code works, but the timer0 code never activates. Can anyone tell from my pseudocode what I have missed?

Ive been tearing my hair out trying to work it out.

Thanks in advance for your time

John
 
2camjohn said:
I have been trying to get timer0 to work on my pic16f628. I have read the datasheets and various websites on the subject. I think I must be overlooking something that is very simple.

Here is what I have done:




At the start of the program:

OPTION_REG.PS0 = 1
OPTION_REG.PS1 = 1
OPTION_REG.PS2 = 0

(Option reg bits 0 - 2 = 110 - sets prescalar to 4th option)

INTCON.INTE = 1
INTCON.T0IE = 1

(intcon bits INTE and T0IE to 1 - enable RB0 and timer0 interrupts)

INTCON.GIE = 1

(enable interrupts - all)

You should also configure bits T0SE, TOCS and PSA of the OPTION_REG.
They configure what signal to use to feed Timer0. Look for it in the datasheet.

2camjohn said:
during the interrupt sequence I have

If INTCON.INTF = 1 Then
(if interrupt is generated by RB0)
*some code here, dependant on timer*

else
(else it must have been the timer)
*timer code here*

end if

INTCON.INTF = 0
INTCON.T0IF = 0
(enable timer and RB0 interrupts)
resume

I don't see anything about context saving during your interrupt routine. Look for it in the datasheet.
 
Try:

OPTION_REG.T0CS = 0

to select the source clock to the internal instruction cycle clock unless you have a clock source at T0CLKI.

Also:

OPTION_REG.PSA = 0

to assign the prescaler to TMR0 if that is your intention.
 
Here's some tmr0 code I was playing with the other week, perhaps it might help?.

Code:
;tmr0 test - Nigel Goodwin 2004
	LIST	p=16F628		;tell assembler what chip we are using
	include "P16F628.inc"		;include the defaults for the chip
	__config 0x3D18			;sets the configuration settings (oscillator type etc.)

	cblock 	0x20 			;start of general purpose registers
		count1 			;used in delay routine
		counta 			;used in delay routine 
		countb 			;used in delay routine
	endc
	
	org	0x0000			;org sets the origin, 0x0000 for the 16F628,
					;this is where the program starts running	
	movlw	0x07
	movwf	CMCON			;turn comparators off (make it like a 16F84)

   	bsf 	STATUS,		RP0	;select bank 1
   	movlw 	b'00000000'		;set PortB all outputs
   	movwf 	TRISB
	movwf	TRISA			;set PortA all outputs
	bcf	STATUS,		RP0	;select bank 0
	call	Initialise
Loop	
	movlw	0xff
	movwf	PORTA			;set all bits on
	movwf	PORTB
	nop				;the nop's make up the time taken by the goto
	nop				;giving a square wave output
	movlw	d'115'
	call	Delay16			;this waits for a while!
	movlw	0x00
	movwf	PORTA
	movwf	PORTB			;set all bits off
	movlw	d'115'
	call	Delay16
	goto	Loop			;go back and do it again

Initialise
	bsf     STATUS,RP0      ;select page 1
	movlw   B'00000010'     ;fosc/256 --> TMR0
	movwf   OPTION_REG       ;       /
	bcf     STATUS,RP0      ;select page 0
	clrf    TMR0
	bcf     INTCON,T0IF     ;clear flag
	bcf     INTCON,T0IE     ;enable mask
	return	

;delay16 waits for approx 16.4mSecs using TMR0 interrupts
;fosc speed is 4Mhz.
Delay16
	movwf    TMR0		;set tmr0 from W
CheckAgain
	btfss   INTCON,T0IF     ;timer overflowed?
	goto    CheckAgain      ;no check again
	bcf     INTCON,T0IF     ;clear flag
	return

	end
 
2camjohn said:
PS what is context saving?

Your interrupt routine needs to save any registers it changes, then restore them before exiting the interrupt routine. In particular W and STATUS are two very important ones, here's an example from one of my tutorials:
Code:
	ORG	0x0004


INT
		movwf	w_temp		; Save W register
		swapf	STATUS,W	; Swap status to be saved into W
		movwf	s_temp		; Save STATUS register
		movfw	PCLATH
		movwf	p_temp		; Save PCLATH 
		.
		.
		.
		movfw	p_temp
		movwf	PCLATH		; Restore PCLATH
		swapf	s_temp,W
		movwf	STATUS		; Restore STATUS register - restores bank
		swapf	w_temp,F
		swapf	w_temp,W	; Restore W register
		retfie
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top