Hej Thomas,
en PIC16F628 har en Input Capture Module. Det er perfekt til det.
- Konfigurer Timer 1 med f. eks. 10µs tælle frekvens.
- Konfigurer Input Capture så at du har en capture event med interrupt ved næste positive kant.
- I interrupt gemme capture værdien A og skifte til negative kant.
- I næste interrupt gemme capture værdien B og B-A er impulsvarigheden
void init()
{
initTimer1For10usClock();
initInputCaptureForRisingEdge();
initInputCaptureInterrupt();
}
void IRQ (void)
{
//It was an input capture interrupt
if (PIR1bits.CCP1IF == 1)
{
// Reset the input capture flag
PIR1bits.CCP1IF=0;
if (CCP1M0 == 1) //was it a rising edge ?
{
posEdgeTimestamp = CCPR1L; // use only the low byte.
CCP1M0 = 0; // switch to falling edge
}
else
{
negEdgeTimestamp = CCPR1L; // use only the low byte.
CCP1M0 = 1; // switch to rising edge
pulseDuration = negEdgeTimestamp - posEdgeTimestamp; // Calculate the pulse duration
}
}
gerd
3 variabler:
TIMESTAMP_A equ 0x20
TIMESTAMP_B equ 0x21
TIME_BETWEEN_AB equ 0x22
Reset og interrupt vector:
;***********************************************
; Reset vector
;***********************************************
org 0x0000
goto RESET
;***********************************************
; IRQ vector
;***********************************************
org 0x0004
goto IRQ
Initialisering:
;***********************************************
; Reset and initialization
;***********************************************
org 0x0005
RESET
bsf STATUS,RP0 ; change to bank 1
bsf TRISB,3 ; Input capture is PORT RB3, so set RB3 as input
bcf STATUS,RP0 ; change to bank 0
movlw B'00000001' ; Enable Timer1 with 1:1 prescaler
movwf T1CON ; so it counts every 400ns, at fosc = 10MHz
movlw B'00000101' ; input capture every every rising edge
movwf CCP1CON
movlw B'11000000' ; Enable all un-masked (Peripheral)-interupts
movwf INTCON
bsf STATUS,RP0
movlw B'00000100' ; Enable CCP1-Interupt
movwf PIE1
bcf STATUS,RP0
clrf TIME_BETWEEN_AB ;
Din main loop:
;***********************************************
; Main loop
;***********************************************
MAIN
; The result (pulse duration) is in TIME_BETWEEN_AB.
; TIME_BETWEEN_AB is the difference between the HIGH bytes of the timer.
; So if it counts with 2.5MHz or 400ns (10MHz system clock) the count value after
; 1.5ms is 3750. And the high byte of 3750 is round about 15.
;
; 1.0ms: TIME_BETWEEN_AB is 10
; 1.5ms: TIME_BETWEEN_AB is 15
; 2.0ms: TIME_BETWEEN_AB is 20
goto MAIN
Interrupt:
;***********************************************
; Input capture interrupt to detect RC signals
;***********************************************
IRQ
movwf W_TEMP ;copy W to temp register, could be in either bank
swapf STATUS,W ;swap status to be saved into W
bcf STATUS,RP0 ;change to bank 0 regardless of current bank
movwf STATUS_TEMP ;save status to bank 0 register
btfsc CCP1CON,0 ; was it a positive or negative edge ?
goto INCAP_RISING ; CCP1CON.0 = 1 <==> rising edge
goto INCAP_FALLING ; CCP1CON.0 = 0 <==> falling edge
INCAP_RISING
movf CCPR1H,W ; save the CCPR1H register
movwf TIMESTAMP_A ; into the variable TIMESTAMP_A
bcf CCP1CON,0 ; switch to falling edge
goto IRQ_END
INCAP_FALLING
movf CCPR1H,W ; save the CCPR1H register
movwf TIMESTAMP_B ; into the variable TIMESTAMP_B
movf TIMESTAMP_A,W ; subtract B-A
subwf TIMESTAMP_B,W ; subtract B-A
movwf TIME_BETWEEN_AB ; TIME_BETWEEN_AB = TIMESTAMP_B-TIMESTAMP_A
bsf CCP1CON,0 ; switch to rising edge
goto IRQ_END
IRQ_END
movwf W_TEMP ;copy W to temp register, could be in either bank
swapf STATUS,W ;swap status to be saved into W
bcf STATUS,RP0 ;change to bank 0 regardless of current bank
movwf STATUS_TEMP ;save status to bank 0 register
retfie