Searching \ for '[PIC] 16F628 Timer1 and Capture questions' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: massmind.org/techref/microchip/time.htm?key=time
Search entire site for: '16F628 Timer1 and Capture questions'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] 16F628 Timer1 and Capture questions'
2006\07\31@163217 by Kevin Timmerman

flavicon
face
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


'[PIC] 16F628 Timer1 and Capture questions'
2006\08\01@053338 by Tamas Rudnai
face picon face
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_OUTlistsTakeThisOuTspampcmx.net> wrote:
{Quote hidden}

> -

2006\08\01@093921 by Kevin Timmerman

flavicon
face
Thanks for your comments Tamas. I read the mid-range manual and
checked for errata. The the usual save/restore context code is in
place and the ISR exits with retfie.  I just took the TMR1IE
disable/enable code out of my completed code, and found it works
fine! The first revision had the strange bug, but not any more. I
tried to reproduce what I had seen, but could not. My best guess is
that in the old code the RP0 bit was not reset by preceding code on
the first ISR pass as it should have been.

Kevin Timmerman

At 05:33 AM 8/1/2006, you wrote:
{Quote hidden}

More... (looser matching)
- Last day of these posts
- In 2006 , 2007 only
- Today
- New search...