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.

Returning fom Interrupt

Status
Not open for further replies.

Suraj143

Active Member
I’m thinking about this from a long time but still I couldn’t do.

When RB0 interrupt occurred its going to org 0004h & updating Select register.

When returning from interrupt I want to goto to the updated line of Select register not from the last save value (before going to ISR)

Ex: when Select Register = 1 it must go to PAT1 (pattern 1 is in the main routine)

Any method to do? Please help me.


Code:
	org	0000h
	goto	Main
		
	org	0004h
		
	incf	Select,F	;increment the Select register on each press
	movf	Select,W
	bcf	STATUS,Z
	xorlw	.1		;if it is press once?
	btfsc	STATUS,Z
	goto	PAT1		;YES,then goto Pattern1
	movf	Select,W
	bcf	STATUS,Z
	xorlw	.2		;if it is press twice?
	btfsc	STATUS,Z
	goto	PAT2		;YES,then goto Pattern2
	movf	Select,W
	bcf	STATUS,Z
	xorlw	.3		;if it is press thrise?
	btfsc	STATUS,Z
	goto	PAT3		;YES,then goto Pattern3	
	retfie

	
Main	bsf 	STATUS,RP0
	movlw	b'00000001'
	movwf	TRISB
	bsf	INTCON,GIE
	bsf	INTCON,INTE
	bcf 	STATUS,RP0
	clrf	PORTB
	clrf	Select
	goto	PAT1
			
********
Patterns
********
			
PAT1	--
	---
	call	Delay
	goto	PAT1


		
PAT2	---
	---
	call	Delay
	goto	PAT2

		
PAT3	---
	---
	call	Delay
	goto	PAT3	
		
*****
Delay
*****

Delay	decfsz	Del0, f
	goto	$-1
	decfsz	Del1, f
	goto	$-3	
	return	

	
	end
 
What PIC are you using? You MUST save the state of the STATUS & W registers when entering an ISR and restore them before leaving. Something like this:
Code:
w_temp		EQU	0x71	; bank free variable used for context saving
status_temp	EQU	0x72	; bank free variable used for context saving


	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

; isr code can go here or be located as a call subroutine elsewhere

	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
Both status_temp and w_temp must be located in bank free memory. The locations of these depend on the PIC you are using.
The best way to signal from an interrupt routine to the main code is to use a flag. I'll show you how to do this once you tell me which PIC you are using. ;)
 
Hi kchriste thanks for for great help I was thinking this all the time how to do this.
Earlier I did with checking the RB0 in the Delay loop.But I want to do this with the RB0 external interrupt.

I'm using PIC16F628A.

Thanks for your help.
 
Without knowing what you are trying to do it is very difficult to advise. I would however suggest that you start by using the template file supplied by Microchip. I would tell you which one but you don't tell us which pic you are using. Have a look in C:\Program Files\Microchip\MPASM Suite\Template\Code to find the right template file.

If you are simply writing different values to a port then just write these values to variables in your ISR and the pattern will change. Jumping out of the ISR is a bad idea.

If your intention is to write your pattern change routine and nothing else then your current approach will work. If you want to add more functionality at a later stage then you need to change how you write code.

Mike.
 
Pommie said:
Without knowing what you are trying to do it is very difficult to advise.
Hi mike I’m trying to do
when power up it shoes pattern1.when I press RB0 button the pattern will be changed to the other pattern. Then it will loop inside that pattern, when I press the RB0 button again the pattern will be changed to pattern three.

If you are simply writing different values to a port then just write these values to variables in your ISR and the pattern will change. Jumping out of the ISR is a bad idea.
Yuo mean to write the three pattern inside the ISR?

If your intention is to write your pattern change routine and nothing else then your current approach will work. If you want to add more functionality at a later stage then you need to change how you write code.

Exactly what I need.
 
I haven't checked your code for full functionality, but here is how I would modify it to use flags to pass the data from the ISR to the main code:


Code:
	list      p=16f628A           ; list directive to define processor
	#include <p16F628A.inc>       ; processor specific variable definitions

	errorlevel  -302              ; suppress message 302 from list file

	[COLOR="Red"]__CONFIG   _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT[/COLOR] 

[COLOR="Red"]#define Pat_1 0x1
#define Pat_2 0x2
#define Pat_3 0x3[/COLOR]


[COLOR="Red"]w_temp        EQU     0x71        ; variable used for context saving 
status_temp   EQU     0x72        ; variable used for context saving

	cblock 0x20
	PatFlags
	Del0
	Del1
	Select
	endc[/COLOR]




	org	0000h
	goto	Main
		
	org	0004h
		
	[COLOR="Red"]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
[/COLOR]
	[COLOR="Red"]clrf	PatFlags[/COLOR]
	incf	Select,F	;increment the Select register on each press
	movf	Select,W
	bcf	STATUS,Z
	xorlw	.1		;if it is press once?
	btfsc	STATUS,Z
	[COLOR="Red"]bsf	PatFlags, Pat_1	;YES,then set Pattern1[/COLOR]
	movf	Select,W
	bcf	STATUS,Z
	xorlw	.2		;if it is press twice?
	btfsc	STATUS,Z
	[COLOR="Red"]bsf	PatFlags, Pat_2		;YES,then set Pattern2[/COLOR]
	movf	Select,W
	bcf	STATUS,Z
	xorlw	.3		;if it is press thrise?
	btfsc	STATUS,Z
	[COLOR="Red"]bsf	PatFlags, Pat_3		;YES,then set Pattern3[/COLOR]

	[COLOR="Red"]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[/COLOR]
	retfie

	
Main	bsf 	STATUS,RP0
	movlw	b'00000001'
	movwf	TRISB
	bsf	INTCON,GIE
	bsf	INTCON,INTE
	bcf 	STATUS,RP0
	clrf	PORTB
	clrf	Select
[COLOR="Red"]	clrf	PatFlags
	bsf		PatFlags, Pat_1 ; Set pattern 1 as default at startup.
loop
	btfsc 	PatFlags, Pat_1
	call	PAT1
	btfsc 	PatFlags, Pat_2
	call	PAT2
	btfsc 	PatFlags, Pat_3
	call	PAT3
	goto	loop[/COLOR]
			
;********
;Patterns
;********
			
PAT1;	--
;	---
	call	Delay
	[COLOR="Red"]return[/COLOR]


		
PAT2;	---
;	---
	call	Delay
	[COLOR="Red"]return[/COLOR]

		
PAT3;	---
;	---
	call	Delay
	[COLOR="Red"]return[/COLOR]	
		
;*****
;Delay
;*****

Delay	decfsz	Del0, f
	goto	$-1
	decfsz	Del1, f
	goto	$-3	
	return	

	
	end

Edit: looking at your code again, all you really need to do is increment Select in the ISR and then do your jumping to the various pattern routines in the main routine based on the value in Select. I should write code for Micro$oft! :eek:
 
Last edited:
Wow kchriste your coding is superb.It will work for sure.Thats what I need how to shift from the ISR to the main code:.Thank you very much kchriste.A great help from you.

Now I really understand how to do that.

Thank you very much.
 
Hi kchriste when an interrupt occur in the middle of a pattern (Let say my pattern is too long) it will goto ISR & update the new pattern.but when returning to the main routing does it come to the other half of the pattern? if so it will take time to shift to the other pattern because the remaining pattern is saved by the W register is this real?
 
The way I modified the code it would work like this:
If the interrupt happens in the middle of a long pattern, then the pattern would have to finish before the next pattern would be run. The second pattern would still be run, but only once the first one was finished.
To solve this, you would have to check the status of PatFlags within your pattern routines:
Pattern1 example:

Code:
PAT1
Pat1Loop:
;	--
;	---
; Code here to exit Pat1 when finished normally
        btfsc PatFlags, Pat_1 ; Exit if Pat1 is not longer needed
goto Pat1Loop
Pat1Exit:
	call	Delay
	return
 
Hi kchriste I ran your coding by adjusting some minor changes it worked.

Code:
	org	0004h
	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

 	clrf	PatFlags
	incf	Select,F	;increment the Select register on each press
	movf	Select,W
	bcf	STATUS,Z
	xorlw	.1		;if it is press once?
	btfsc	STATUS,Z
	bsf	PatFlags, [COLOR="Red"]Pat_2[/COLOR]	;YES,then set Pattern1
	movf	Select,W
	bcf	STATUS,Z
	xorlw	.2		;if it is press twice?
	btfsc	STATUS,Z
	bsf	PatFlags, [COLOR="Red"]Pat_3[/COLOR]		;YES,then set Pattern2
	movf	Select,W
	bcf	STATUS,Z
	xorlw	.3		;if it is press thrise?
	[COLOR="Red"]btfss	STATUS,Z
	goto	$+3
	clrf	Select
	bsf	PatFlags,1[/COLOR]
	movf    status_temp,w     
	movwf	STATUS            ; restore pre-isr STATUS register contents
	swapf   w_temp,f
	swapf   w_temp,w          ; restore pre-isr W register contents	
	retfie

Only thing I want to do is to debounce the RB0 button otherwise the patterns are skipping mostly.
 
Last edited:
It is easier to electronically debounce an interrupt pin than to do it in software. Since the RB0/INT pin when used as an external interrupt pin is a Schmitt input, then a simple 0.1uF capacitor across the push button with a 10K pullup should work. Can you post the entire code that you have so far; I don't see any reference to clearing the INTF bit in INTCON anywhere in your interrupt routine (BCF INTCON, INTF) yet it still works?
 
Hi kchriste I have added bcf INTCON, INTF bit before returning from interrupt.For this code I forgot to write it down.

Hardware debounce is ok for me.software debounce i'm doing like this

*check the button
*NO then return
*if it pressed then call a small delay
*check it still pressed
*NO then return
*Do what ever i want to do
*check the button has released
*YES the code continues

But this is for a normal button.I don't know how to do it to the RB0 interrupt condition.To debounce i'm not familiar much with TMR0.

Can i use a delayloop to debounce my RB0 within the ISR?
 
Can i use a delayloop to debounce my RB0 within the ISR?
Yes but this would cause the main routine to halt during the debounce time. It is generally not a good idea to put a delay routine in an ISR. One of the rules of writing code for ISRs is to keep it as short (time wise) as possible. It would mean that your LED flash routine would pause briefly when a button was pushed or released.
But this is for a normal button.I don't know how to do it to the RB0 interrupt condition.To debounce i'm not familiar much with TMR0.
It is probably best to reverse our thinking a bit. I assume the LEDs blink at a constant rate in repeating patterns. It would be best to blink the 3 LED patterns in the ISR which is called by the timer at set intervals.
Then do the button check and debounce in the main routine and pass the selected pattern type to the ISR via flags. This would simplify the code quite a bit.
 
Last edited:
Oh I see now I got it. For the time being I’ll put a hardware debounce for RB0 as you mentioned. This is not such a sensitive program. Only to change patterns, so the additional cap will help a lot in this case.

Anyway thanks for your great help you done kchriste you gave me lot of information through this thread.

Thank you very much for your support.
Bye & take care
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top