This will save you a little time deciphering it;
' 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 = 000101 ' 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
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.
' 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 = 000101 ' 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 = 000101 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 = 000100 ; 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 = 000100 THEN ; If falling edge capture then T1CON.0 = 0 ; Stop Timer1 CCP1CON = 000101 ; 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
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.
Re: How can I reduce ADC drift
Yes, it is.
Demon Today, 00:02