Kevin,
I think the interrupt stuff is more precise documented in the "PICmicro
MID-Range MCU Family" documentation (310??a.pdf, interrupts are discussed in
31008a.pdf).
They said you do not have to do such tricks, just clear the TMR1IF at the
end of the handler. They advise that you have a good structure of your ISR
like this:
1. save the state of the MCU (W register + STATUS & whatever you need)
2. poll which interrupt occurs and jump to the relevant handler routine
3. at the end of the handler clear the interrupt flag so that you are
ready for the next interrupt to be occur
4. restore state of the MCU
5. return from the interrupt
If timer interrupt occures while you are staying at the ISR it will
automatically carry on (no recursive interrupt) until you return with
RETFIE(which re enables interrupts). At that point after 1 cycle the timer
interrupt calles your ISR, so that the timer interrupt will not lost. Your
polling routine tells you which interrupt occured so will jump to your timer
ISR...
If you touch the GIE by yourself all the interrupts in the queue will be
lost!
Here is the sample from Microchip:
org ISR_ADDR ;
PUSH_MACRO ; MACRO that saves required context
registers,
; or in-line code
CLRF STATUS ; Bank0
BTFSC PIR1, TMR1IF ; Timer1 overflow interrupt?
GOTO T1_INT ; YES
BTFSC PIR1, ADIF ; NO, A/D interrupt?
GOTO AD_INT ; YES, do A/D thing
: ; NO, do this for all sources
: ;
BTFSC PIR1, LCDIF ; NO, LCD interrupt
GOTO LCD_INT ; YES, do LCD thing
BTFSC INTCON, RBIF ; NO, Change on PORTB interrupt?
GOTO PORTB_INT ; YES, Do PortB Change thing
INT_ERROR_LP1 ; NO, do error recovery
GOTO INT_ERROR_LP1 ; This is the trap if you enter the ISR
; but there were no expected
; interrupts
T1_INT ; Routine when the Timer1 overflows
: ;
BCF PIR1, TMR1IF ; Clear the Timer1 overflow interrupt flag
GOTO END_ISR ; Ready to leave ISR (for this request)
AD_INT ; Routine when the A/D completes
: ;
BCF PIR1, ADIF ; Clear the A/D interrupt flag
GOTO END_ISR ; Ready to leave ISR (for this request)
LCD_INT ; Routine when the LCD Frame begins
: ;
BCF PIR1, LCDIF ; Clear the LCD interrupt flag
GOTO END_ISR ; Ready to leave ISR (for this request)
PORTB_INT ; Routine when PortB has a change
: ;
END_ISR ;
POP_MACRO ; MACRO that restores required registers,
; or in-line code
RETFIE ; Return and enable interrupts
Hope it helps a bit,
Tamas
On 31/07/06, Kevin Timmerman <spam_OUTlistsTakeThisOuT
pcmx.net> wrote:
{Quote hidden}>
> I have an application that has to capture the time of an event with
> the greatest precision possible, so the capture feature is being
> used. The 16 bit resolution was not enough, so the Timer 1 overflow
> interrupt is used to increment a counter and provide an additional 8
> bits of resolution.
>
> First problem: TMR1 overflow ISR is called twice for each overflow.
> Simply clearing TMR1IF does not work. A search of the PIC list
> archive found a suggestion to disable the overflow interrupt
> (TMR1IE), clear the interrupt flag, and then enable the interrupt.
> This works, but is ugly. I can not find any documentation of this
> behavior in the 16F628 or mid range manuals.
>
> Working code:
> bsf STATUS,RP0
> bcf PIE1^BANK1,TMR1IE
> bcf STATUS,RP0
> bcf PIR1,TMR1IF
> bsf STATUS,RP0
> bsf PIE1^BANK1,TMR1IE
> bcf STATUS,RP0
> incf t1_overflow,F
>
> Questions: Is this documented anywhere? Is there a better (more
> efficient) way to do this? Do other 16F series PICs behave the same way?
>
> Second problem: There is no interrupt priority, so the overflow count
> may be out of synch with the capture. The only solution I could think
> of is to check if the capture MSB is zero and TMR1IF is set. If these
> conditions are met, the timer has overflowed before the capture event
> but the overflow ISR has yet executed, so the overflow count is
> behind and must be incremented. Testing has been perfect - no failures.
>
> Working code:
> incf t1_overflow,W
> movwf cap_ovr_save
> movf CCPR1H,W
> movwf cap_msb_save
> btfsc STATUS,Z
> btfss PIR1,TMR1IF
> decf cap_ovr_save,F
> movf CCPR1L,W
> movwf cap_lsb_save
>
> Questions: Is this sound logic? Is there a case where this will fail?
> Is there a better method or more efficient code?
>
> Thanks,
> Kevin Timmerman
>
> -