Grab that app note Steve linked to. It's got some pretty cool stuff in it.
This will save you a little time deciphering it;
Code:
' Measuring signal pulse widths with capture module
' Procedure for high-going pulse:
' 1. Configure CCP to capture on rising edge
' 2. Setup Timer1 so it will not overflow during max pulse width time
' 3. Enable ccp capture
' 4. Once capture flag bit is set, save captured value as T1
' 5. Reconfigure CCP to capture on falling edge
' 6. On 2nd capture, save 2nd value as PW
' 7. Subtract T1 from PW for the pulse width value
' Test signal:
' 12.04kHz pulse with 41uS high / 42uS low
' Input signal connected to RC2/CCP1 pin
' PIC18F242 @20MHz
DEFINE OSC 20
DEFINE DEBUG_REG PORTC
DEFINE DEBUG_BIT 6
DEFINE DEBUG_BAUD 115200
DEFINE DEBUG_MODE 0 ' 1 = inverted, 0 = true
Symbol Capture = PIR1.2 ' CCP1 capture flag
T1 VAR WORD ' 1st capture value
PW VAR WORD ' 2nd capture value & ultimately final pulse width
TRISC.2 = 1 ' CCP1 input pin (Capture input)
INTCON = 0 ' Interrupts off
ReLoad:
CCP1CON = %00000101 ' Capture mode, capture on rising edge
T1CON = 0 ' TMR1 prescale=1, clock=Fosc/4, TMR1=off (200nS per count @20MHz)
TMR1H = 0 ' Clear high byte of TMR1 counter
TMR1L = 0 ' Clear low byte
T1CON.0 = 1 ' Turn TMR1 on here
Capture = 0 ' Clear capture int flag bit
While !Capture ' Wait here until capture on rising edge
Wend
' Rising edge detected / stuff Timer1 value in T1
T1.HighByte = CCPR1H
T1.LowByte = CCPR1L
CCP1CON.0 = 0 ' Configure capture for falling edge now
Capture = 0 ' Clear capture interrupt flag bit
While !Capture ' While here until capture on falling edge
Wend
' Falling edge detected / stuff Timer1 value in PW
PW.HighByte = CCPR1H
PW.LowByte = CCPR1L
PW = PW-T1 ' High pulse width = PW-T1
' Convert to uS for 20MHz osc with 200nS Timer1 ticks
PW = (PW * 2)/10
DEBUG dec PW,"uS High",13,10 ' Output to RS232 display
GOTO ReLoad
END
I ran it with a 2nd PIC delivering a 12.04kHz signal: HPWM 1,127,12000 to the
18F242 CCP1 pin. 41uS high, 42uS low.
It's spot-on. Returns 41uS High on MCS serial terminal. Fluke ScopeMeter 123
shows precisely the same timing.
Much nicer than pulsin, count, etc..
Darrel Taylors' instant interupts works perfect for this.
Code:
' PIC18F242 @20MHz
DEFINE OSC 20
DEFINE DEBUG_REG PORTC
DEFINE DEBUG_BIT 6
DEFINE DEBUG_BAUD 115200
DEFINE DEBUG_MODE 0 ' 1 = inverted, 0 = true
OverFlows VAR BYTE ' Timer1 overflow total
Remainder VAR WORD ' Remaining Timer1 ticks after falling edge capture
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts
;----[High Priority Interrupts]----------------------------------------
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler CCP1_INT, _Capture, PBP, yes
INT_Handler TMR1_INT, _Timer1, PBP, yes
endm
INT_CREATE ; Creates the High Priority interrupt processor
ENDASM
CCP1CON = %00000101 ' Capture mode, capture on rising edge
T1CON = 0 ' TMR1 prescale=1, clock=Fosc/4, TMR1=off (200nS per count @20MHz)
@ INT_ENABLE CCP1_INT ; enable Capture interrupts
Main:
IF T1CON.0 = 0 THEN ' If done, show result
DEBUG "Timer Overflows = ",DEC OverFlows
DEBUG " Remaining ticks = ",dec Remainder,13,10
ENDIF
PAUSE 2000
@ INT_ENABLE CCP1_INT ; Start new capture
GOTO Main
'---[CCP1 - interrupt handler]------------------------------------------
Capture:
IF CCP1CON = %00000101 THEN ' If rising edge capture then
TMR1L = 0 ' Clear Timer1 counts
TMR1H = 0
T1CON.0 = 1 ' Turn Timer1 on at rising edge capture
OverFlows = 0 ' Clear over flow counts
Remainder = 0 ' Clear remainder
CCP1CON = %00000100 ; Switch to falling edge capture
PIR1.0 = 0 ; Clear Timer1 overflow flag before enable
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
GOTO OVER_CCP ; Done, exit
ENDIF
IF CCP1CON = %00000100 THEN ; If falling edge capture then
T1CON.0 = 0 ; Stop Timer1
CCP1CON = %00000101 ; Switch back to rising edge capture
@ INT_DISABLE TMR1_INT ; Disable Timer 1 Interrupts
@ INT_DISABLE CCP1_INT ; Disable CCP1 Interrupts
Remainder.LowByte = TMR1L ; Get remaining Timer1 counts on falling edge
Remainder.HighByte = TMR1H
ENDIF
OVER_CCP:
@ INT_RETURN
'---[TMR1 - interrupt handler]---------------------------------------------
Timer1:
OverFlows = OverFlows + 1
@ INT_RETURN
END
Input for testing was a 2nd PIC providing a 30mS pulse followed by a 1000mS
pulse with a 5 second delay between each.
For the 30mS pulse it displays: Timer Overflows = 2 Remaining ticks = 19048
The total pulse width: (2 * 65536 * 200nS) + (19048 * 200nS) = 30.0242mS
For the 1000mS pulse: Timer Overflows = 76 Remaining ticks = 19480
So: (76 * 65536 * 200nS) + (19480 * 200nS) = 1.0000432 S
Darrels interrupt routines are pretty handy.
Bookmarks