PDA

View Full Version : Interrupt Problem



Kamikaze47
- 16th November 2005, 13:11
I've set up a very basic program to experiment with interrupts on a 16F84 (ive basically just used the example interrupt code from the pbp manual)

This main program should loop forever until RB0/INT goes high (via a pushbutton), and the interrupt routine should trigger and turn on the LED, and then go back to the endless loop in the main program.

However, when I press the button, the LED comes on for about 2 seconds and then turns off again. So i checked to see if it was resetting by putting code at the beginning of the program that makes the LED flash on and off a few times.

Sure enough, when i pressed the button, the LED came on for 2 seconds and then flashed, so the program was reset for some reason. It even resets if i pull out the oscillator after pressing the button. Now this seems to point me towards thinking that the watchdog timer is going off, but i dont know why it would.



DEFINE OSC 10 ' Oscillator = 10MHz
define INTHAND int_handler ' Define interrupt handler

INTEDG VAR OPTION_REG.6 ' RB0 Interrupt edge select: 1=Rising Edge 0=Falling Edge
INTF VAR INTCON.1 ' RB0 Interrupt flag
INTE VAR INTCON.4 ' RB0 Interrupt enable
GIE VAR INTCON.7 ' Global interrup enable

LED var PORTB.1 ' LED on RB1

wsave var byte $20 system ' Variable for saving W Register on Interrupt
ssave var byte bank0 system ' Variable for saving STATUS Register on Interrupt
psave var byte bank0 system ' Variable for saving PCLATH Register on Interrupt
fsave var byte bank0 system ' Variable for saving FSR Register on Interrupt

HIGH LED ' Flash LED Twice
pause 50
low led
pause 50
high led
pause 50
low led

INTEDG=1 ' RB0 Interrupt to Trigger on Rising Edge
INTF=0 ' Enable RB0 Interrupt
INTE=1 ' Enable RB0 Interrupt
GIE=1 ' Global Interrupt Enable

loop: Goto loop ' Endless Loop


'-----------------------------------------------------------------------------'
' Interrupt Handler '
'-----------------------------------------------------------------------------'

asm
int_handler
; Save Resisters ;
movwf wsave ; Save W Register into wsave
swapf STATUS,W ; Save STATUS Register into ssave
clrf STATUS
movwf ssave
movf PCLATH,W ; Save PCLATH Register into psave
movwf psave
movf FSR,W ; Save FSR Register into fsave
movwf fsave

; Interrupt Code ;
bsf _LED ; Turn on LED

; Restore Resisters ;
movf fsave,W ; Restore FSR Resister
movwf FSR
movf psave,W ; Restore PCLATH Resister
movwf PCLATH
swapf ssave,W ; Restore STATUS Resister
movwf STATUS
swapf wsave,F ; Restore W Resister
swapf wsave,W
retfie
endasm

Ingvar
- 16th November 2005, 14:59
If my memory serves me right i think that the line .......
loop: Goto loop ' Endless Loop
...... will not kick the watchdog. You probably need to insert atleast one statement between the label and the goto.

/Ingvar

Kamikaze47
- 16th November 2005, 15:03
Tried that... Didnt help im afraid...

It looks like its not even making it out of the interrupt routine, and just locking up and resetting at some point after it turns on the led.

J_Brittian
- 16th November 2005, 15:18
I think Ingvar's right. I'm not sure you're leaving any room for an interrupt to occur. Try it like this:

loop:
For y = 0 to 100
pause 1
Next y
Goto loop

Kamikaze47
- 16th November 2005, 15:27
well the interrupt is def occuring or the led wouldnt come on at all. an interrupt handled in assembly doesnt need "room" for it to occur. It will jump right to the interrupt handler no matter what the processor is doing at the time... but ill try what you suggest

*edit* just tried it and no change... when i press the button attached to the interrupt pin the led goes high for 2 secs and then the whole thing crashes and restarts

J_Brittian
- 16th November 2005, 15:34
I'm sorry. I just realized that. Do you reset you're interrupt flag somewhere? Should there be an Intf = 0 just before the retfie?

tom
- 16th November 2005, 15:37
first off all you forgot to clear int flag
in your int handler so your PIC will always
be in interrupt routine. you have to put line


bcf INTCON,1

before retfie instruction.
also I suggest you to turn on and off
LED in int routine with little delay
in between (although it is not adviceable to use
delays in interrupt)
to see the interrupt more clearly. you can
use this int handler for example:



asm
int_handler
; Save Resisters ;
movwf wsave ; Save W Register into wsave
swapf STATUS,W ; Save STATUS Register into ssave
clrf STATUS
movwf ssave
movf PCLATH,W ; Save PCLATH Register into psave
movwf psave
movf FSR,W ; Save FSR Register into fsave
movwf fsave
endasm
high LED
pause 100
low LED
; Interrupt Code ;
;bsf _LED ; Turn on LED
asm
; Restore Resisters ;
movf fsave,W ; Restore FSR Resister
movwf FSR
movf psave,W ; Restore PCLATH Resister
movwf PCLATH
swapf ssave,W ; Restore STATUS Resister
movwf STATUS
swapf wsave,F ; Restore W Resister
swapf wsave,W
bcf INTCON,1
retfie
endasm

Kamikaze47
- 16th November 2005, 15:38
I would have thought the interrupt flag would be reset automatically when it returns from the interrupt handler. I havnt seen interrupt routines that reset the flag, but I guess its worth a try.

Kamikaze47
- 16th November 2005, 15:44
Ahh yep, that did the trick. Thanks Ingvar.

Just a single line at the end of the interrupt handler: bcf _INTF

Kamikaze47
- 16th November 2005, 15:46
Tom: is there any down side of including picbasic commands in your interrupt handler. I thought to work as a proper interrupt it had to be in asm?

tom
- 16th November 2005, 15:48
You always have to clear interrupt flag in software
before retfie instruction. If you don't clear the flag,
instruction retfie will set GIE bit and PIC will be
interrupted again. Logical AND function beetwen
int flag bit and int enabled bit (AND-ed with GIE)
will result in interrupt.

tom
- 16th November 2005, 15:51
kamikaze 47:
well, of course it's better to use asm in my opinion
but this also work. I try it.

Darrel Taylor
- 16th November 2005, 18:32
Kamikaze47 is right.

There is definately a problem using PAUSE in an ASM interrupt.

Pause uses 2 internal PBP variables. (R0 and R1). So if, another PBP statement that uses either R0 or R1 gets interrupted, the interrupt routine will change those values and the main program will get confused.

It's possible to have a pause in the interrupt, IF you save both of the system vars first, then restore them when the int is finished.

In that case, toms example would look like this...

R0save VAR WORD
R1save VAR WORD

asm
int_handler
; Save Resisters ;
IF (CODE_SIZE <= 2)
movwf wsave ; Save W Register into wsave
swapf STATUS,W ; Save STATUS Register into ssave
clrf STATUS
movwf ssave
movf PCLATH,W ; Save PCLATH Register into psave
movwf psave
movf FSR,W ; Save FSR Register into fsave
movwf fsave
endif
endasm
R0save = R0
R1save = R1
high LED
pause 100
low LED
R1 = R1save
R0 = R0save
asm
; Restore Resisters ;
movf fsave,W ; Restore FSR Resister
movwf FSR
movf psave,W ; Restore PCLATH Resister
movwf PCLATH
swapf ssave,W ; Restore STATUS Resister
movwf STATUS
swapf wsave,F ; Restore W Resister
swapf wsave,W
bcf INTCON,1
retfie
endasm

But then, like tom says ... "it is not advisable to use delays in interrupt"
<br>

Kamikaze47
- 16th November 2005, 19:02
Thanks for that info Darrel.

Is there a reference somewhere that tells you what (if any) internal variables PBP uses for each command?

Darrel Taylor
- 16th November 2005, 19:32
No, unfortunately.

Depending on how and where certain statements are used in the program, the actual system variables used might change. So there's really no way to make a "List".

You pretty much have to sift thru the .LST file to find out which vars are used. That includes following every CALL to other routines too. It can take a while.

PAUSE was easy though, it's pretty small, and only has 1 CALL.

Of course, you can take the easy route and just save them all to be sure. But then we're back to OXIMBIT's routine again.
<br>

rhino
- 16th November 2005, 20:58
Kamikaze47 -
There's a little info about this HERE (http://www.picbasic.co.uk/forum/showthread.php?t=2226) from Darrel. Look at post #9 on down. I guess it's out there if you have the time to dig through the files and look for them.