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.

PIC 16F interrupt question

Status
Not open for further replies.

tarts

Member level 2
Joined
Dec 13, 2009
Messages
43
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,615
Ok here is typical entry and exit from Interrupt routine in 16f microcontrollers:

Entry
Code:
			movwf	W_TEMP 						; Copy W to TEMP register
			swapf	STATUS,W					; Swap status to be saved into W
			clrf	STATUS
			movwf	STATUS_TEMP 					; Swaps are used because they do not affect the status bits
										; Save status to bank zero STATUS_TEMP register
			movfw	PCLATH						; save PCLATH regisers
			movwf	PCLATH_TEMP
			clrf	PCLATH
			movf	FSR,w
			movwf	FSR_TEMP
exit:
Code:
exit	
			movf FSR_TEMP,w
			movwf FSR
			movfw	PCLATH_TEMP					; restore PC
			movwf	PCLATH						; (sets bank to original state)
			swapf	STATUS_TEMP,W					; Swap STATUS_TEMP register into W
			movwf	STATUS						; Move W into STATUS register
			swapf	W_TEMP,F					; Swap W_TEMP
			swapf	W_TEMP,W
			retfie

But recently I used up all general purpose registers in page 0(starts at 0x20h), then I started to use registers in bank 1 (starts at 0xA0h)
Now when I'm in bank 1 and I enter the Interrupt routine then before I clear STATUS in entry I save W into W_TEMP, but actually it won't be saved in W_TEMP because this register is in bank0 and I'm still in bank 1, so it will be saved in some GPR in bank 1.

Has anyone encountered this problem?
I havent seen anyone mentioning it in tutorial website etc.
 

You haven't stated which PIC you are using, most have a shared memory region, which is accesible in all banks. If yours has this, use "org xxx" (xxx = start of shared area) before declaring the interrupt variables so they are saved in the shared bank. In most cases though, you don't need to worry about the bank during an interrupt as the stack is wide enough to hold the entire address so switching banks isn't necessary.

Brian.
 
  • Like
Reactions: tarts

    tarts

    Points: 2
    Helpful Answer Positive Rating
This is nice thread

I need verify one. when return from ISR (tetfil) I need to send PC( Program counter) where it generates interrupt

please help
 

The stack always holds the return address when an interrupt is called. In other words, the PCLATH bits and PCL are saved on the stack. When the 'retfie' instruction is found, these are copied back to their original registers so the program execution continues from the point the interrupt was called. There is no access to the stack contents on PIC16 devices so you can't read or modify the program counter directly.

Brian.
 
Thanks Brain for reply

this is as a example

let say

Code:
1                        ORG        0X004
2                         CALL       ISR
3
4
5                         BTFSS    PIR1,0  ; interrupt generate here
6                         GOTO      $-1
7
8                         movlw   b'00001111'   ; I want execute this return from ISR
9
10
11              ISR
12                         BCF         PIR1,0
13                         RETFIL
14

my question is I want execute 8 row instruction because interrupt generate from line number 5
 

My PIC was 16f690. I have never seen shared memory mentioned in manual so I'm sure this device doesn't have that. My solution to the proböem was to create two W_TEMP registers one in bank 0 and other in bank 1 (W_TMP_B1). So If iterrupt occurs in bank 0, w goes to W_TMP if it occurs in bank1 then w is saved in W_TMP_B1. But the key here is to place these registers on same addresses.

Code:
	cblock 0x20																		
						
	W_TEMP								; temorary W register in first address (0x20)
	STATUS_TEMP
	PCLATH_TEMP
	FSR_TEMP
	...
	endc
	
	cblock 0xA0	

	W_TEMP_B1							; if we enter interrupt in bank1 then w will be saved here instead of W_TEMP, this is also in first address (0xA0)
	Register1								
	Register2							
	....

	endc

PA3040 I don't think I really unerstand your question. Your current code does nothing. don't test PIR1,0 in your main loop, it is always clear. If it's set you are already in interrupt routine. Instead use GPR-s(general purpose registers). Besides you have a call instruction but no return, that won't work


Code:
1                        ORG        0X004
3       ISR
4                         BCF         PIR1,0
5                         BSF      MYREGISTER,0
6                         RETFIE
7
8                       ORG        0x00
9                         BTFSS    MYREGISTER,0  ; wait for iterrupt to occur
10                         GOTO      $-1
11                         BCF      MYREGISTER,0    ; continues here if interrupt occurred
12
13                         movlw   b'00001111'   ; 
14
 
Last edited:

I agree with @tarts. The code does nothing and is confusing to read. Please use the names of registers and the bits in them instead of their number.
For example:
BCF PIR1,0 ;what is bit 0 ?
BCF PIR1,TMR1IF ;now we know !

As stated, there is no point in checking if the interrupt flag is set, assuming it was caused by timer1 it must be set to have reached the interrupt routine at all. My advice would be for you to study how interrupts work and what to do inside them. The general rules are:

1. save at least the W and STATUS register as you will probably want these to hold the same value when the main program resumes.
2. as you are in the ISR, one or more interrupt flags must be set, check to see which ones and call the routines to deal with the interrupt situation.
3. clear the interrupt flags.
4. restore the registers you saved in step 1.
5. use the 'retfie' instruction to resume normal program flow.

Also, it is considered good practice to get out of the ISR as quickly as possible. The reason for this is the GIE bit is cleared when the ISR is entered, this prevents other interrupts occuring. It follows that if possible, avoid loops that might delay the ISR from returning. Never change the GIE bit inside the ISR or you risk a crash, it will automatically be restored by the retfie instruction.

Final tip: don't use "$-1" as a destination. On 16F devices it means go back one instruction but on most other PIC families it will not work properly. It is better to use a label and jump to it. for example, dont use:

BTFSS PIR1,0 ; interrupt generate here
GOTO $-1

instead use:
Code:
MyLabel
  btfss PIR1,TMR1IF
  goto MyLabel
which will work on all PIC families.

Brian.
 
  • Like
Reactions: PA3040

    PA3040

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top