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] Strange interrupt problem

Status
Not open for further replies.

jerryd

Member level 2
Joined
Feb 4, 2013
Messages
48
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,709
edaboard,
pic18f2550 MPLAB X IDE XC8
This interrupt code works when PORTB.0 is pulled low with a switch, but if I uncomment either of the lines:
;btfsc RBIE ;is RBIE enabled?
;btfss RBIF ;it is, so check the flag

it complies and loads but the interrupt INTOIE no longer works. I'm not trying to get an IOC interrupt yet.

Checking with a scope PORTB.0,4,5,6,7 are high with the internal pull ups. I have this hardware and all the interrupts working with a C program.

Code:
PSECT textISR,class=CODE,reloc=4

;interrupt function
isr:
    ;check for PORTB.0 external interrupt
    btfsc       INT0IE  ;is INTO enabled?
    btfss       INT0IF  ;it is, so check the flag
    goto        notINT0 ;not an external interrupt
    bcf         INT0IF  ;it is, so clear the INT0IF flag
    incf _button4,1,0   ;button 4 was pressed
    retfie              ;now get out
notINT0:
    ;check for RBIE interrupt on change
    ;btfsc     RBIE     ;is RBIE enabled?
    ;btfss     RBIF     ;it is, so check the flag
    retfie              ;not an IOC interrupt
    bcf        RBIF     ;clear the RBIF flag
    movlw 1
    movwf _button, 0    ;a button on PORTB 4,5,6, or 7 was pressed
retfie                  ;return from interrupt

Any suggestions?

jerrd

[ code tags added by moderator]
 
Last edited by a moderator:

In a PIC, INT0IF is set regardless of whether the interrupt is enabled or not, in your code you skip resetting it if INT0IE isn't set.

Brian.
 

betwixt,
I've seen that note in the manual but I set it and check it anyway.
No matter, the interrupt still won't work if I uncomment either line:
;btfsc RBIE ;is RBIE enabled?
;btfss RBIF ;it is, so check the flag

Strange.

Any help?

jerryd
 

No, I think it is normal operation.
The issue with interrupts on PIC 12, 16 and 18 devices is they have only one vector (unless you count high priority on PIC18) so the ISR code has to decide what caused it. Using the interrupt flags alone isn't a reliable solution because they are always active, a more reliable method is to check the interrupt you want is also enabled. Interrupt flags will be set even if the corresponding interrupt isn't enabled.
What you have to be careful of, and I think it is the underlying problem in your code, is that the interrupt flag is reset and ready for the next time it's needed. If you don't reset the interrupt flag it stays set and the ISR will be called again immediately you leave it.

Your code flow should be:
1. check the RBIF and RBIE are both set
2. Process the interrupts as necessary
3. reset RBIF
4. exit with a RETFI.

In your example, step 3 gets skipped if step 1 fails so RBIF remains set when the ISR terminates.

Brian.
 

edaboard,
Still chasing this problem.

To check out my hardware and hardware setup I changed the interrupt function to
isr:
;check for RBIE interrupt on change
btfsc RBIE ;is RBIE enabled?
btfss RBIF ;it is, so check the flag
retfie ;get out
movf PORTB,0,0 ;read PORTB
bcf RBIF ;clear the RBIF flag
movlw 1
movwf _button4, 0 ;a button on PORTB 4,5,6,or7 was pressed
retfie ;return from interrupt

This works but if I remove the line " movf PORTB,0,0", make any reference to INT0IF or even put a "nop" in somewhere it stops working. The same things happen if I start out only checking for INT0IE and INT0IF.

None of this causes a warning or error. This behavior makes me suspicious of XC8.

Any comments/help?
jerryd
 

On these PIC devices, there is a 'trick' to the 'port change' interrupt and it is explained in 'Note 1 for the RBIF bit description on page 99 of the data sheet.
While you can clear the RBIF bit as you have done, the bit will simply be set again by the hardware until you read the port. It is the at of reading the port that clears the internal circuitry that is detecting the mismatch. Think of it as a hidden register that holds the bit settings of the PORT the last time you read it. When the port itself changes the hardware compares the current port bits with the 'hidden' register and flags there is a difference. This difference will remain until you read the port again.
I'm not sure about your comments regarding INT0IE/IF but fix one problem at a time.
Susan
 

Susan,
I'm not having a problem clearing the RBIF flag. What I'm trying to do is check for the RBIF and INT0IF flags in same isr but when I do that the interrupt never happens. I can do one of the other but not both?

jerryd
 

The show us ALL of the code, even if only the ISR.
Susan
 

edaboard,
Reading the gate structure on page 100 of the pic18f2550 manual I made some progress with the interrupt problem. This is known good hardware.

Included is a file with a cut down version of code that exhibits an interrupt problem. As you can see both sections of the isr set the button4 variable. This is just for debug.

When I run the program the INT0IF portion works as expected. I can press the external button during the wait loops and it will cause an interrupt both times.

Trying the same thing by pressing one of the IOC buttons will only cause an interrupt once.

jerryd
 

Attachments

  • match.zip
    1.1 KB · Views: 66

Hi,

I don't open .zip files on my tablet.
Why not just press the [c o d e] button to insert your code?

Klaus
 

KlausST,
I didn't know about the
Code:
 feature.
 Do I just click on [code] and then paste the code as a post?
jerryd
--- Updated ---

Here's the code.
#include <xc.inc>

GLOBAL _Random
GLOBAL _match
GLOBAL _button4
GLOBAL _delay
GLOBAL _delay1
GLOBAL _delay0

PSECT text0,class=CODE,reloc=2

// variable delays
Delay:
movlw 0XFF
movwf _delay1,0
repeat:
movf _delay,0,0
movwf _delay0,0
dloop:
nop
nop
nop
nop
decfsz _delay0,1,0 // decrement delay0 and skip when zero
goto dloop

decfsz _delay1,1,0 // decrement delay1 and skip when zero
goto repeat
return // end Delay:


// match function
_match:

call _HWsetup // setup the hardware
call _Random // empty function call

movlw 100
movwf _delay,0 // set the Delay length

movlw 0x00
movwf _button4,0 // clear button4

movlw 0b11011000
movwf INTCON,0 // enable GIE, PIE, INT0IE and RBIE

// loop until button4 has been pressed
movlw 1
wait4:
CPFSEQ _button4, 0
goto wait4

// button4 has been pressed
movlw 0X00
movwf INTCON,0 // turn off all interrupts
movf PORTB,0,0 // read PORTB

movlw 0
movwf _button4, 0 // clear button4

movlw 0b00000110
movwf PORTC,0 // turn on some leds
call Delay

movlw 0X00
movwf PORTC,0 // turn off all leds

movlw 0b11011000
movwf INTCON,0 // enable GIE, PIE, INT0IE and RBIE
movf PORTB,0,0 // read PORTB

// loop until button4 has been pressed
movlw 1
wait5:
CPFSEQ _button4, 0
goto wait5

// button4 has been pressed
movlw 0X00
movwf INTCON,0 // turn off all interrupts
movf PORTB,0,0 // read PORTB

movlw 0
movwf _button4, 0 // clear button4

movlw 0b01000001
movwf PORTC,0 // turn on some leds
call Delay

movlw 0X00
movwf PORTC,0 // turn off all leds

return // end of _match



PSECT text0,class=CODE,reloc=2
// hardware setup function
_HWsetup:
movlw 0b01000010 // oscillator frequency 1 mhz
movwf OSCCON,0

movwf ADCON0,0 // Turn off all ADC

movlw 0x0F
movwf ADCON1,0 // Disable all analog functions

movlw 0x00
movwf TRISA,0 // All PORTA as outputs
movlw 0b11111111
movwf PORTA,0 // All PORTA high

movlw 0b11110001
movwf TRISB,0 // PORTB 1,2,3 as output and 0,4,5,6,7 as interrupts

movlw 0x00
movwf TRISC,0 // All PORTC as output
movwf PORTC,0 // All PORTC low

BCF RBPU // Enable pull-up on PORTB
BCF INTEDG0 // Falling edge asserts external interrupt

movlw 0X00
movwf INTCON,0 // clear all interrupts
movf PORTB,0,0 // read PORTB

return // end of _HWsetup:



PSECT textISR,class=CODE,reloc=4
;interrupt function
isr:
;check for external interrupt on PORTB 0
btfsc INT0IE ;is INTO enabled?
btfss INT0IF ;it is, so check the flag
goto notINT0F ;not an external interrupt
bcf INT0IF ;it is, so clear the INT0IF flag
movf PORTB,0,0 ;read PORTB
movlw 1
movwf _button4, 0 ;set the button4 variable
goto exitISR ;now get out
notINT0F:
;check for IOC on PORTB 4,5,6,7
btfsc RBIE ;is RBIE enabled?
btfss RBIF ;it is, so check the flag
goto exitISR ;not an IOC interrupt
bcf RBIF ;clear the RBIF flag
movf PORTB,0,0 ;read PORTB
movlw 1
movwf _button4, 0 ;set the button4 variable
exitISR:
retfie ;return from interrupt

END
 
Last edited:

Do I just click on
Code:
 and then paste the code as a post?
It's rather self-explanatory. There is no dedicated help, because one usually does not need it.
Especially when you see the outcome of the CODE in post#11.

And you are free to use the [preview] ... to check your post before it goes online.

Additionally you have limited time to edit your post after it is online.


I didn't know about the
Hmm .... but you see the icons at the top of the editor window?
--> The forum software provides them all for your use. And the use is for free.

Klaus
 

I am not entirely sure (and I'm certain that others will correct me if I'm wrong) but reading the data sheet for the 'btfsc' and 'btfss' instructions, they take 2 or 3 parameters, the last of which is the 'a' value that defaults to 1 - i.e it will use the BSR when accessing memory. I think you need to specify this parameter as 0 so that the 'access bank' will be used always.
What I'm not sure of is how the 'INT0IE', 'INT0IF', 'RBIE' and 'RBIF' names are expanded to in assembler. If they are the full 3 parameters then what you have is probably right; if not then you may need to be explicit in the parameters that you use.
(Looking on the Internet, I see assembler code such as:
Code:
BTFSS INTCON, INT0IE
....
but I know things could be different with the XC8 assembler.)
Susan
 

Aussie Susan,
MPLAB X IDE v6.05 XC8 v2.41
The project has a main.c and an asm.s. The main.c only calls the _match function in the asm.s.

Yes, those commands should require f,b,[a] but if I add anything after f the compiler gives me a syntax error. #including <pic18f2550> must take care of this.

I have tried adding BANKSEL (INTCON) at the start of the isr: but it doesn't help.

This code is not very complicated and I've had this all working in C.

I decided to work around this for now but then discovered that I can't set another variable in the isr: function.

I tried adding the line "bsf button,0" but it doesn't get set. These variables are defined in the .c module as "volatile unsigned int" and in the asm.s as "GLOBAL". My project depends on setting variables in the isr: function so if I can't get this working I'll have to give up on doing this with assembly.

Thanks.
jerryd
 

I tried adding the line "bsf button,0" but it doesn't get set. These variables are defined in the .c module as "volatile unsigned int" and in the asm.s as "GLOBAL".
Not really surprising if 'button' is itself a variable as the instruction expects an address. I'm not able to access the help or user guide at the moment but there is information in them about how to access variables between asm and .c code.

Brian.
 

edaboard,
I do use the _ prefex with these variables and can manipulate outside of the isr function.

I did redefine them in the asm.s file with DS 1. This is the only way the compiler would allow me to define variables in assembly but I had the same problem.

jerryd
 

It seems you have not configured INTEDG or INTEDGx (x can be 0, 1, 2) based on how many external interrupts the PIC18 device has and which PIC device you are using.
 

electronicspro1989,
Thanks for the reply.

The device is a pic18f2550. I use this one because it has exactly the number of I/0s and interrupts needed for the project.

I set INTEDG0 (falling edge) and RBPU (pullups) in the WHsetup function.

jerryd
--- Updated ---

edaboard,
I have found a way to get the RBIE/RBIF interrupt to work all the time. Clearing the RBIF and reading PORTB in the isr function doesn't seem to actually do what you would expect.

Looking at the gate structure on page 100 of the manual it should but I have found that I can still clear RBIF in the isr function but I have to read PORTB back in my _match function. I can't explain it but at least I can move on.

My current problem will be in another post.

Thanks to all who posted here.
jerryd
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top