I wasn't using anything but internals on this Arch. I'll check out what you posted and give it a whirl. Thanks for the help. I think my brain began to die after I passed 50.
I wasn't using anything but internals on this Arch. I'll check out what you posted and give it a whirl. Thanks for the help. I think my brain began to die after I passed 50.
Had a few extra minutes and rewrote the code - I think it should work - I don't have any 16F676's to try it on.
(yer way ahead of me... my brain died off around 5 or so)...
Code:@ DEVICE PIC16F676,INTRC_OSC_NOCLKOUT,WDT_ON,PWRT_OFF,BOD_OFF,PROTECT_OFF,CPD_OFF,MCLR_OFF LED var PORTA.0 BlinkCount var byte CounterA var byte OLDPORTA VAR byte NEWPORTA VAR byte ; DISABLE ANALOG INPUT, COMPARATOR ON PORTA, A/D reference... ANSEL = 0 : CMCON = 7 : VRCON = 0 TRISA = %00111110 ; PortA In/Out states WPUA = %00000110 INTCON = %10000000 : IOCA = %00111000 : OPTION_REG = %00001000 LED = 0 : PAUSE 1000 : LED = 1 GOTO BASE ; ; SUBROUTINES MYINT: NEWPORTA = PORTA ; read current PortA state INTCON = %10000000 ; IF NEWPORTA.5 <> OLDPORTA.5 THEN BlinkCount = 3 ; Set up for 4 blinks ENDIF ; IF NEWPORTA.4 <> OLDPORTA.4 THEN BlinkCount = 2 ; Set up for 3 blinks ENDIF ; IF NEWPORTA.3 <> OLDPORTA.3 THEN BlinkCount = 1 ; Set up for 2 blinks ENDIF ; for CounterA = 0 to BlinkCount LED = 0 : PAUSE 1000 : LED = 1 : PAUSE 1000 next CounterA RESUME Base ; The above section could have an error trap in case none of the IF's are true for some reason. ; A "Select Case" might use less code space. ; ; Start main program loop here ; BASE: BlinkCount=0 : OLDPORTA = PORTA ; ON INTERRUPT GOTO MYINT INTCON = %10001000 ; LOOP: SLEEP 240 : GOTO LOOP end
Arch
Arch, once again I'd like to thank you. That was it. At one time programing was one of my strong points, but it seems I get lost pretty easy these days. Thanks for helping me out again.
Well, that definately looks better, and it may work better for now, but it still needs a couple things.
The Interrupt "Handler" should be enclosed within DISABLE/ENABLE statements to keep the Interrupt Handler itself from being interrupted again.
The clearing of the Flag should be done in the handler, not the point that execution resumes. If you RESUME without clearing the flag first, you can end up right back in the Handler again.
And, "resume BASE" should only be "RESUME".
When specifying a location to RESUME to, it essentially does a GOSUB to that routine when the Handler is finished. However, in this program, the PIC is told to go to Sleep, without ever returning from that GOSUB. So on each interrupt, it pushes another address on the stack, which overflows after 8 interrupts. For a 16F, the Stack will wrap around to the beginning again without causing a reset, so you may never see the problem right now, but if there are any other subroutines involved, they will never get a chance to RETURN, or will return to the wrong place.
Because of the "Spaghetti" nature of this program, these problems may not be evident because it just falls back into the program and continues on, but when you start adding things later, you will lose a large portion of whatever hair you may have left trying to figure it out.
<br>
DT
Hi Darrel,
I'm a bit confused by the idea that a "RESUME (label)" is like a GOSUB. From the following quote in the PBP manual, it sounds more like RESUME (label) acts like a GOTO:
I've always used RESMUE with a label, as I want to RESUME at a known location in the code, and have never had any issues, even in large programs with lots of other sub-routines.When the RESUME statement is encountered at the end of the BASIC
interrupt handler, it sets the GIE bit to re-enable interrupts and returns to
where the program was before the interrupt occurred. If RESUME is
given a label to jump to, execution will continue at that location instead.
All previous return addresses will be lost in this case.
Any further info would be great. Thanks,
Arch
BUT as it erase all previous return address... it just clear the stack at the same time imho.
Let's say you're limited to a 4 level deep stack, everytime you'll RESUME you will eat one in place in the stack. Since your code don't do any Gosubs, it never give you problem, but one day, if you're at the stack limit, and then you add a RESUME LABEL, you may get this problem. Something to be tested i guess.
Steve
It's not a bug, it's a random feature.
There's no problem, only learning opportunities.
Hi Steve,Originally Posted by mister_e
Well, that's what got me wondering. In other code with lots of gosubs, using a RESUME (label) has not caused any problems.
If the stack gets cleared with the RESUME (label), how would the stack overflow occur?
Thanks,
Arch
EDIT
Interesting info Darrel. Can't figure how any other code I've written with ON INTERRUPT continues to work - by the look of what you posted, the code should crash or go off in odd directions - but for some reason it does work OK even after a RESUME (label) followed by several subroutines. I'll have to try and figure that one out one of these days.
On that little sample above - I don't think the DISABLE / ENABLE are needed, as the interrupt handler comes before the ON INTERRUPT statement (at least that's what the manual says).
EndEDIT
Last edited by Archilochus; - 5th May 2006 at 03:22.
Yes, the manual is a bit vague. But if we take a look at the macro's themself it should be a little clearer.
These are from the PBPPIC14.mac file.With only the RESUME it does a retfie (Return from Interrupt) which causes the hardware to turn GIE back on and pops the last address off the stack to return to.Code:;**************************************************************** ;* RESUME? : Macro - Resume * ;* * ;* Input : None * ;* Output : None * ;* * ;* Notes : * ;**************************************************************** RESUME? macro RST?RP retfie endm endmod ;**************************************************************** ;* RESUME?L : Macro - Resume Label * ;* * ;* Input : Label * ;* Output : None * ;* * ;* Notes : * ;**************************************************************** RESUME?L macro Label bsf INTCON, GIE L?GOTO Label endm endmod
But, if you include a label with the resume, all it does is set the GIE bit manually, then GOTO's the label. At this point, the address from the interrupt is still on the stack. Once the Subroutine has finished and does a RETURN. It will return to the point where the interrupt first happened.
If the subroutine doesn't do a RETURN, the stack keeps building up.
Also, that subroutine should be enclosed in DISABLE/ENABLE statments to keep it from being interrupted before it returns.
If you're OK with the idea of the stack wrapping around and Discarding all previous gosubs after an interrupt, then it'll still work that way on a 16F. But don't try it with an 18F.
HTH,
Darrel
Bookmarks