PDA

View Full Version : Sorry, but another interrupt problem



tbirchall
- 30th August 2005, 00:39
I'm a newbie just can't seem to get this working. I've checked the other posts but I don't see what I'm doing wrong. I'm trying to receive an interrupt from push button connected to portb/0. I am using a PIC16F84A and here is the code:

Include "modedefs.bas"

CLEAR
LOW 7

TRISB.0 = 1
INTCON = %10010000
ON INTERRUPT GOTO handleInterrupt

main:
PAUSE 1
GOTO main

DISABLE
handleInterrupt:

HIGH 7 ' turn on LED so I know it worked
PAUSE 1000
LOW 7

INTCON.1 = 0
RESUME

ENABLE

END

If the problem isn't in the code, it might also be how I've got the push button hooked up. (Like I said, I'm a newbie.) I've tried several things, but right now I have one lead on the push button connected to 5v+ and the other lead connected to portb/0. I've tested the LED and switch separately, and they both work and the code compiles as well.

Any help is GREATLY appreciated.

mister_e
- 30th August 2005, 01:04
what else on the PORTB.0 pin??? any pull-down resistor???
Should have one, if not it could act weird.

Another altenative is to use the internal PULL-UP and connect your push-buuton between RB0 and GND


OPTION_REG = 0 ' enable internal pull-up and interrupt on RB0 falling edge

Yuantu Huang
- 30th August 2005, 01:09
You should initialise the INTEDG bit of OPTION_REG. If you would like to make falling edge interrupt, just add OPTION_REG.6 = 0 after INTCON = %10010000

mister_e
- 30th August 2005, 01:17
This is why i suggest my previous. BTW in the first post PB was connected to VCC and OPTION_REG.6 is set to 1 at start-up wich is already rising edge.

tbirchall
- 30th August 2005, 20:08
Thank you very much. That did the trick. It is really great to have such knowledgable people to turn to. Thanks for taking the time.

-Tom

tbirchall
- 31st August 2005, 01:20
OK, I hate to be a pest but... I got the sample code working, but when I apply it to my real code, it only works once. Basically, what I'm trying to achieve is to have the program wake on interrupt, do something, then go back to napping. This is to save power since it is a battery powered project. So, my loop looks like this:

loop:
NAP 0
PAUSE 1

GOSUB blah
GOTO loop

The idea is that all the interrupt does is to clear the flag, then the code will resume at the next line of code - in this case, the PAUSE statement. If I have a simple HIGH/LOW FOR/NEXT loop that lights an LED, it works perfectly over and over again. If I have my gosub (like above), then it works once and that's it - the interrupt never gets called again. Can someone tell me conceptually what is going on? My gosub has one other gosub nested in it, so I don't think it is too deep. Oh, and blah does have a return and my interrupt routine is wrapped in DISABLE and ENABLE calls. Thank you!

-Tom

Melanie
- 31st August 2005, 02:18
Whilst I prefer to use @SLEEP rather than NAP, I did once experience an anomaly (about three years back - probably PBP v2.42) whereby a couple of instructions following the @SLEEP were not executed properly. I cured the problem (without investigating further due to lack of time) by inserting half a dozen @NOP statements before I resumed with any proper code... the reasoning behind that was if it was going to misbehave and skip a couple instructions then the NOP's would absorb the anomaly and contine as it was intended. Anyhow, it worked for me, might be worth trying to see if it does it for you.

mister_e
- 31st August 2005, 03:06
Out of topic by why people say half dozen?
SIX
3 letters, same mean. sorry. couldn't resist

Yuantu Huang
- 31st August 2005, 03:17
Hi Tom,

The problem might be caused by gosub, which might take too much time, because PBP uses very latency interrupt implementation, and it never jumps into interrupt subroutinue within gosub. Please read Section 9.2 "Interrupt in Basic" in PBP manual. If you use goto instead of gosub, the problem may be fixed. That is,

change

gosub AAA
...

AAA:
...
return

into

goto BBB
CCC:
...

BBB:
...
goto CCC

If the above does not work, you have no choice but using assembly interrupt.

mister_e
- 31st August 2005, 03:39
FALSE, interrupt will jump from anywhere in your code. gosub or goto make absolutely no difference. Latency will be caused by some function BUTTON,SOUND,PAUSE to name only those.

Personnally, for my design, i've never found a REAL BIG difference between regular and assembly interrupt once the code is properly written.

BTW, post a whole code, not only a snip of it, we will help.

Ioannis
- 31st August 2005, 07:18
Ooh, come on now, don't be a Scrutz!!


Out of topic by why people say half dozen?
SIX
3 letters, same mean. sorry. couldn't resist

Six means exactly six.

But "half a dozen" displays the authors/speakers feeling about the quantity (which I guess in Melanies case was too many instructions).

Ioannis

tbirchall
- 31st August 2005, 19:23
OK, I tried adding the 12/2 @NOPs, but it reacted the same. Here is some code:

loop:

nap 0
pause 15

' this works repeatedly just fine
' for index = 0 to 5
' high 7
' pause 250
' low 7
' pause 250
' next

@NOP
@NOP
@NOP
@NOP
@NOP
@NOP

' this works the first button press but never again
gosub callTime

GOTO loop

' my interrupt routine
disable
handleInterrupt:

high 7
pause 250
low 7

INTCON.1 = 0
resume

enable

callTime:

' clear the display
gosub clearDisplay

' show time
gosub displayTime

pause 2000

' clear the display
gosub clearDisplay

return

clearDisplay:

for index = 1 to 2
shiftout LEDData, LEDCLK, MSBFIRST, [index]
shiftout LEDData, LEDCLK, MSBFIRST, [-1]
pulsout LEDLoad, 5
next

for index = 3 to 4
shiftout LEDData, LEDCLK, MSBFIRST, [index]
shiftout LEDData, LEDCLK, MSBFIRST, [%00000000]
pulsout LEDLoad, 5
next

return

displayTime:

' read time from DS1302
GOSUB ReadRTCBurst

' get hours
I = Hours
if (I > 12) then I = (I - 12)
if (I < 8) then
high 0
I = (I - 1)
I = (%01000000 >> I)
shiftout LEDData, LEDCLK, MSBFIRST, [3]
else
low 0
I = (I - 8)
I = (%01000000 >> I)
shiftout LEDData, LEDCLK, MSBFIRST, [4]
endif
shiftout LEDData, LEDCLK, MSBFIRST, [I]
pulsout LEDLoad, 5

' get tens of minutes
I = (Minutes >> 4)
shiftout LEDData, LEDCLK, MSBFIRST, [1]
shiftout LEDData, LEDCLK, MSBFIRST, [I]
pulsout LEDLoad, 5

' get minutes
I = (Minutes & $0F)
shiftout LEDData, LEDCLK, MSBFIRST, [2]
shiftout LEDData, LEDCLK, MSBFIRST, [I]
pulsout LEDLoad, 5

return

---------------------------------
So, did anyone read this far? Sorry for the length. Basically, I'm reading time from a DS1302 and then pumping it out to a MAX7219 LED driver. Part of the time is in LED's and part is in segment displays. The time stuff and display all seems to work fine - if I'm not calling it from after an interrupt.

Thank you again!

-Tom

CocaColaKid
- 31st August 2005, 20:13
Tom, Trying using the insert code option. Make it much easier to read. The command is:


(code)
blah
blah
blah
(/code)


The the () with [].

Yuantu Huang
- 1st September 2005, 00:37
Hi Tom,

You can try goto instead of gosub and change 'pause n' into

for i = 1 to n
pause 1
next i

everywhere except inside of the interrupt subroutinue. Of course, if statements within gosub takes several mill-seconds, then leave it is.

I use the above method in my project and it works. You may try it and let me know the result.

Once again, PBP is very latency interrupt implementation because it must finish the current statement execution before jumping into the interrupt subroutinue. So make sure the jobs within each statement take short time as possible as you can.

tbirchall
- 1st September 2005, 22:40
Ahhhhh! I can't belive it. I'm embarrassed to say it was a leftover line of code from when I was trying to get it working originally. In the displayTime routine, I had a call to LOW 0. This would have changed the pin to be an output and therefore no longer would be triggered by the interrupt button. Doh!

Thank you everyone for all the help. You rock!

-Tom