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.

Cannot get Interrupt on TIMER0 to work on 16F628

Status
Not open for further replies.

johankj

New Member
Hi all,

Can anyone help me out with this? I'm sure it's a simple thing for someone who has done this before. The datasheet is a bit scarce on information regarding TIMER0. Basically, I want the 'main' code to run as normal, and then after a TIMER0 interrupt, I want to run the interrupt code. Timing and prescalers are not so important at the moment, I just want to be able to get the interrupt. Here is the code:
Code:
; PIC is 16F628
; Internal clock @ 4Mhz.
;

		LIST		P=PIC16F628
		INCLUDE		"P16f628.INC"
		ERRORLEVEL	0,	-302	; Suppress bank selection messages
		__CONFIG	_BODEN_ON & _CP_OFF & _DATA_CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT

; Varable declarations
TIMER1		EQU		H'20'		; Used in delay routine
TIMER2		EQU		H'21'		;  "	"	"	
TEMP		EQU		H'22'		; Requires this for non-descructive subs
RELAYCNT	EQU		H'23'		; Counter for relay timer.		
		
		ORG			0x0000
		GOTO		BEGIN

		ORG			0x0004			; Interrupt starts here
		DECFSZ		RELAYCNT,F
		GOTO		DONE_IRQ
		MOVLW		.15
		MOVWF		RELAYCNT
		BSF			PORTA,0
		;MOVLW		B'00000001'		; XOR MASK
		;XORWF		PORTA,F			; Change PORTA,0
DONE_IRQ
		BCF			INTCON,T0IF		; Clear TIMER0 interrupt flag
					RETFIE			; Return from Interrupt
					

; Sub-Routines
DELAY_25MS			movlw		0x86		; 24993 cycles, 25000 Cycles total = 25ms @ 4MHz
		movwf		TIMER1
		movlw		0x14
		movwf		TIMER2
DELAY_25MS_0		decfsz		TIMER1, f
		goto		$+2
		decfsz		TIMER2, f
		goto		DELAY_25MS_0
		goto		$+1
		nop
		return

DELAY_1MS			movlw		0xC6		; 993 Cycles, 1000 Cycles total = 1ms @ 4MHz
		movwf		TIMER1
		movlw		0x01
		movwf		TIMER2
DELAY_1MS_0			decfsz		TIMER1, f
		goto		$+2
		decfsz		TIMER2, f
		goto		DELAY_1MS_0
		goto		$+1
		nop
		return

SETUP
		BCF			STATUS,RP0	; BANK 0		
		MOVLW		0X07		;
		MOVWF		CMCON		; Turn off comparator
		
		BSF			STATUS,RP0	; Bank 1
		MOVLW		B'00000000'	; INITIALISE PORT A
		MOVWF		TRISA		;
		MOVLW		B'00000000'	; INITIALISE PORT B
		MOVWF 		TRISB		;
		MOVLW		B'11000111'	; Prescaler (256)
		MOVWF		OPTION_REG	; -"-
		MOVLW		B'10100000'	; Interrupt Control
		MOVWF		INTCON		; -"-

		BCF			STATUS,RP0	; Bank 0
		CLRF		PORTA		;
		CLRF		PORTB		;
		CLRF		TMR0		; Clear TIMER0 counter
		BCF			INTCON,T0IF	; Clear interrupt flag
		MOVLW		.15
		MOVWF		RELAYCNT
		RETURN					; Return To MAIN
		
; Main Program
BEGIN  	CALL		SETUP		; SET UP PIC
MAIN_LOOP	

		MOVLW		B'01011011'	; 2
		MOVWF		PORTB
		MOVLW		B'00001000'	;
		MOVWF		PORTA
		CALL		DELAY_1MS
		MOVLW		B'11001111'	; 3
		MOVWF		PORTB
		MOVLW		B'00000100'	;
		MOVWF		PORTA
		CALL		DELAY_1MS
		MOVLW		B'01100110'	; 4
		MOVWF		PORTB
		MOVLW		B'00000010'
		MOVWF		PORTA
		CALL		DELAY_1MS
	
		GOTO		MAIN_LOOP

		END

Basically, the PIC spends most of its time on the three LED digits, and then on TIMER0 interrupt triggers the relay on.

Is there an advantage to using TIMER2? I have no preferableness, as I have not programmed timer interrupts before.

Input is most appreciated, as always...

-Johan
 

Attachments

  • ProtoBoardUVTimer.jpg
    ProtoBoardUVTimer.jpg
    55.3 KB · Views: 242
I think the interrupt is working as expected but you don't see the change on port A as your main code is writing to port A as well.

You should also think about saving and restoring the context in your interrupt. See section 14.7 of the data sheet.

Mike.
 
Last edited:
Thanks Pommie. I modified the code, so not to write whole PORTA, thanks for spotting that :)

However, unless I 'infinite loop' the program in the interrupt code, nothing happens. I know the interrupt works now, but if I let the program return from the interrupt, PORTA,0 never goes high??

Here's my modified code:
Code:
; PIC is 16F628
; Internal clock @ 4Mhz.
;

		LIST		P=PIC16F628
		INCLUDE		"P16f628.INC"
		ERRORLEVEL	0,	-302	; Suppress bank selection messages
		__CONFIG	_BODEN_ON & _CP_OFF & _DATA_CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT

; Varable declarations
TIMER1		EQU				H'20'			; Used in delay routine
TIMER2		EQU				H'21'			;  "	"	 "	
TEMP		EQU				H'22'			; Requires this for non-descructive subs
RELAYCNT	EQU				H'23'			; Counter for relay timer.		
		
			ORG				0x0000
			GOTO			BEGIN

			ORG				0x0004			; Interrupt starts here
			DECFSZ			RELAYCNT,F
			GOTO			DONE_IRQ
			MOVLW			.15
			MOVWF			RELAYCNT
			BSF				PORTA,0
			;MOVLW			B'00000001'		; XOR MASK
			;XORWF			PORTA,F			; Change PORTA,0
;HERE		NOP
;			GOTO			HERE
DONE_IRQ
			BCF				INTCON,T0IF		; Clear TIMER0 interrupt flag
			RETFIE							; Return from Interrupt
					

; Sub-Routines
DELAY_25MS	movlw			0x86			; 24993 cycles, 25000 Cycles total = 25ms @ 4MHz
			movwf			TIMER1
			movlw			0x14
			movwf			TIMER2
DELAY_25MS_0	decfsz		TIMER1, f
			goto			$+2
			decfsz			TIMER2, f
			goto			DELAY_25MS_0
			goto			$+1
			nop
			return

DELAY_1MS	movlw			0xC6			; 993 Cycles, 1000 Cycles total = 1ms @ 4MHz
			movwf			TIMER1
			movlw			0x01
			movwf			TIMER2
DELAY_1MS_0	decfsz			TIMER1, f
			goto			$+2
			decfsz			TIMER2, f
			goto			DELAY_1MS_0
			goto			$+1
			nop
			return

SETUP
			BCF				STATUS,RP0		; BANK 0		
			MOVLW			0X07			;
			MOVWF			CMCON			; Turn off comparator
			
			BSF				STATUS,RP0		; Bank 1
			MOVLW			B'00000000'		; INITIALISE PORT A
			MOVWF			TRISA			;
			MOVLW			B'00000000'		; INITIALISE PORT B
			MOVWF 			TRISB			;
			MOVLW			B'11000111'		; Prescaler (256)
			MOVWF			OPTION_REG		; -"-
			MOVLW			B'10100000'		; Interrupt Control
			MOVWF			INTCON			; -"-

			BCF				STATUS,RP0		; Bank 0
			CLRF			PORTA			;
			CLRF			PORTB			;
			CLRF			TMR0			; Clear TIMER0 counter
			BCF				INTCON,T0IF		; Clear interrupt flag
			MOVLW			.15
			MOVWF			RELAYCNT
			RETURN							; Return To MAIN
		
; Main Program
BEGIN  		CALL			SETUP			; SET UP PIC
MAIN_LOOP	
			MOVLW			B'01011011'		; 2
			MOVWF			PORTB
			BCF				PORTA,1
			BCF				PORTA,2
			BSF				PORTA,3
			CALL			DELAY_1MS
			MOVLW			B'11001111'		; 3
			MOVWF			PORTB
			BCF				PORTA,1
			BSF				PORTA,2
			BCF				PORTA,3
			CALL			DELAY_1MS
			MOVLW			B'01100110'		; 4
			MOVWF			PORTB
			BSF				PORTA,1
			BCF				PORTA,2
			BCF				PORTA,3
			CALL			DELAY_1MS
		
			GOTO			MAIN_LOOP

			END
 
You should also think about saving and restoring the context in your interrupt. See section 14.7 of the data sheet.

Mike.

Would that affect how PORTA is written to? I wouldn't expect Bank-bits to change, and W I don't case about...
 
If you have a large load (an LED without a resistor) on PORTA.0 then the other bsf in the main code will clear it. To find out if this is the problem remove all writes to port A in the main code.

As for the context stuff, it won't have any effect at the moment but as your code gets more complex it will cause problems.

Mike.
 
Turned off PORTA writes in my main, and now the relay turns on.

PORTA,0 is connected to a 2N3904 transistor via a 820 Ohms resistor, which sinks current out of a Rayex LU-5 relay to turn it on. This must be sinking too much current out of the port then.

I would never had expected it to be a HW issue.

Thank you Mike :)

PS: I'll take you up on your advice to save context on interrupt.
 
Changed the resistor on the transistor from 33 Ohm to 1.5k Ohm, and now it works perfectly.

I don't know why I used such a low value.
 
You have to be careful that you don't take too much current out of a port pin. The good news is that the problem is now solved and you can move onto the next part of your project.

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top