'High resolution pulse width measure (was PICLIST D'
|On Tue, 1 Jul 1997 22:30:13 +0200 Mal Goris <NFRA.NL> writes: mgoris
>If you are willing to use an interrupt, the RTCC, the FSR register and
>a lot more code space than Andy #1's routine above, then you will be
>able to get resolutions down to 1 clock cycle with the
>following. Sorry about the lack of comments. The idea is to let an
>interrupt service routine record the start and stop times as given by
>the RTCC. You can tell when an edge has been detected because FSR is
>incremented by the ISR. After the first edge is detected start
>checking for overflows of RTCC and increment the high byte, stop_hi,
>if it does.
Here's my untested approach to the same. It uses several tricks. The
INT interrupt on B0 is used for input. This is a simple approach with
several major linitations, which can be overcome by using a more
complicated approach. These major limitations are: The RTCC is used for
timing, and it is reset. The pulse-measure routine uses all the PIC's
attention while it is running. Other interrupts are not possible.
; ISR. This ISR differs from standard practice. It will trash the W and
; STATUS registers. It will not clear the flag that caused the
; And it will not reenable interrupts when returning, this allows the GIE
; bit to be used to tell if an interrupt has occurred.
org 04h ;Interrupt routine
movfw TIMER0 ;Get RTCC (TIMER0) value
clrf TIMER0 ;Reset TIMER0.
return ;Return, *don't reenable interrupts*
; Pulse measure. Requires 2 RAM locations, pulse_low and pulse_high.
; This will be the width of the pulse in instruction cycles, minus about
; 3 cycles to account for clearing the RTCC.
; Active high-pulse applied to B0/INT. Pulse must be low upon entering
; the routine.
movlw OPTION_REG ;Point INDF as the option
movwf FSR ;Eliminates the need to set RP
movlw b'11001111' ;Timer, no prescale. WDT max
; Port B0 interrupt rising edge.
movwf INDF ;To OPTION.
movlw b'00010000' ;Enable INT interrupt. Disable
;and clear any flags.
clrf pulse_high ;Clear high pulse width time.
bsf INTCON,GIE ;Enable interrupts.
btfsc INTCON,GIE ;Has interrupt occurred?
; At this point, the interrupt has occurred, due to the rising edge of
; the pulse, and the TIMER0 has just been reset.
bcf INTCON,T0IF ;Clear overflow flag.
bcf INDF,6 ;Set INTEDG to look for falling
bcf INTCON,INTF ;Clear INT flag.
bsf INTCON,GIE ;Enable interrupt on fall of pulse.
btfsc INTCON,T0IF ;Check for low count roll over.
goto waitfall2 ;Timer hasn't rolled over yet.
incf pulse_high,f ;TIMER0 rolled over. Keep track.
btfsc INTCON,GIE ;Did interrupt occur?
goto waitfall ;No, keep waiting.
; Here after pulse ends.
movwf pulse_low ;TIMER0 was copied to W at the
;of the pulse by the ISR.
btfsc INTCON,T0IF ;In case last overflow was
;Pulse width now in pulse_low and pulse_high, subject to (constant)
; correction for latencies.
The problem with the original pulse trigger delay application is that the
PIC needs to output a pulse at the same time it is measuring the input
pulse. With The C84 has only one execution unit, so it can't do both at
once to one-cycle precision (maybe with an external gate to stop an
externally applied TIMER0 clock at the end of the pulse, it could). The
CCP module does pulse timing with dedicated hardware, allowing the PIC to
do several things at once.
More... (looser matching)
- Last day of these posts
- In 1997
, 1998 only
- New search...