cmicrocontrollerinterruptpicpulse

pulse width using interruption flag


I would like to measure a pulse width using pic 18f4550 CCP in capture mode. The idea is: when the CCP model receives a rising edge, the timer1 starts, and after each interruption of the Timer 1, x which is a constant with an initial value of 0 increases by 1, when the CCP model receives a falling edge timer1 stops and the increase of x must also stop so that its value can be used in the calculation of the pulse. the problem i found is that the increasing of x doesn't stop and the code works like a counter and as i am a newbie in pic programming I couldn't find the error. if anyone can help i will be grateful. the code I am using is bellow. thanks!

#include <stdio.h>
#include <stdlib.h>

#include "osc_config.h"
#include "LCD_8bit_file.h"
#include <string.h>

int x=0;

void main()
{
    unsigned long comtage;
    unsigned long DEPHASAGE[20];
    float Deph_tempo;
    
    TRISCbits.TRISC2=1;
    
    IRCF0=1;     
    IRCF1=1;
    IRCF2=1;  
    
    LCD_Init();
    
    LCD_String_xy(0,0,"pulse"); 
 
    PIE1bits.CCP1IE=1;
    PIR1bits.CCP1IF=0; 
    
    CCP1CON=0b00000101; 
    CCPR1=0;        
    
    T1CONbits.RD16=0;
    T1CKPS0=0;
    T1CKPS1=0;
    TMR1CS=0;
    
    while(1)        
    {    
        CCP1CON         = 0b00000101;
        PIR1bits.CCP1IF = 0;
        TMR1ON          = 0; 
        TMR1            = 0;

        while (!PIR1bits.CCP1IF)
            ;

        TMR1ON          = 1; 
        CCP1CON         = 0b00000100;
        PIR1bits.CCP1IF = 0;
    
        if (TMR1IF==1)
        {
            x++;
            TMR1IF=0;
        }
    
        while (!PIR1bits.CCP1IF)
            ; 

        comtage = x; 
    
        Deph_tempo = ((float)comtage /7843.13 ); 
        sprintf(DEPHASAGE,"%.5f  ",Deph_tempo); 

        LCD_String_xy(2,0,DEPHASAGE);
    }
    x = 0;
}                              

``

Solution

  • There is one way you can achieve what you want to do... It's a bit tricky, since you need a timer that's more than 16 bits wide. It is possible to use both TMR1 and TMR3 to work with CCPCON, and get a 19-bit wide timer, at Fosc = 8MHz, your clock input to the timers is 2MHz, which means this 19 bit timer will rollover after 2^19 * .5 us = 264 us seconds or so... We could use TMR3IF to detect a rollover and make it 20 bits, but that's still a bit short.

    There is also the possibility of using TMR0, which has an 1:256 prescaler, but you'd need to feed TMR0 with an external clock. You can use TMR3 and the PWM generator to generate a 500kHz clock signal on CCP2/RC1, and route that to TK0CKI/RA4. This would effectively create a 26-bit counter, with a resolution of 4/Fosc = .5 us, and a range of 33.55 seconds. You could increase resolution by using the PLL to increase oscillator frequency. This also has the advantage that it would be quite precise. Repeatability depends on the loops. Using an ISR to catch the interrupts would improve repeatability quite a bit.

    #include <stdio.h>
    #include <stdlib.h>
    
    #include "osc_config.h"
    #include "LCD_8bit_file.h"
    #include <string.h>
    
    void main()
    {
        unsigned long count = 0;
    
        // Setting up TMR0 for extarnal clock on T0CKI/RA4
    
        LATAbits.LATA4    = 0;
        TRISAbits.TRISA0  = 1;     // RC0 as input
        T0CON             = 0x27   // Prescaler 1:256, 0->1 transition, T0CKI input 
        TMR0IE            = 0;     // mask interrupts.
    
        // Setting up TMR1/CCP1CON for capture on RC2/CCP1
    
        TRISCbits.TRISC2  = 1;     // CCP2/RC2 as input
        LATCbits.LATC2    = 0;
        T1CON             = 0x80   // internal clock oscillator off, 1:1 pre, 16 bits reads
        TMR1              = 0;
        CCP1CON           = 0x05   // set capture mode on rising edge
        CCP2IE            = 0;     // mask interrupts
        TMR1IE            = 0;
    
        // Setting up TMR2/CCP2CON for generating the clock on CCP2/RC1
    
        LATCbits.LATC1    = 0;     // clear RC1 latch
        TRISCbits.TRICSC1 = 0;     // RC1 as output
        T2CON             = 0;     // timer2 off, prescaler 1:1, post scaler 1:1
        PR2               = 3;     // PWM frequency = (Fosc / 4) / 4
        TMR2              = 0;
        CCPR2             = 0;
        CCP2CON           = 0x1C;  // CCP2M = PWM mode, DCB2<0> = 1 (LSB for duty cycle compare) 
        CCP2IE            = 0;     // mask interrupts
        TMR2IE            = 0;
    
        while (1)
        {
            // get ready to capture.
            TMR2ON          = 0;      // stop our timing clock.
            TMR0ON          = 0;      // this reset TMR0 prescaler
            TMR0            = 0;      // clear timers.
            TMR1            = 0;
            TMR2            = 0;
            TMR0ON          = 1;      // Timer 0 is ready to count.
            CCP1CON         = 0x05;   // set capture mode on rising edge
            PIR1bits.CCP1IF = 0;
    
            while (!PIR1bits.CCP1IF)  // wait for event
                ;
    
            PIR1bits.CCP1IF = 0;
            CCP1CON         = 0x04;   // set capture mode on falling edge
    
            TMR1ON          = 1;
            TMR2ON          = 1;
    
            while (!PIR1bits.CCP1IF)  // wait for event
                ;
            
            // here we have to make sure to keep the same latency as after 
            // rising edge, so we are precise. 
            PIR1bits.CCP1IF = 0;
            CCP1CON         = 0x04;   // set capture mode on rising edge
    
            TMR1ON          = 0;
            TMR2ON          = 0;      // also stops TMR0 
    
            // TMR0's clock is is divided by 2²2 * 2^8 = 2^10
            // its lower 6 bits should be equal to the upper 6 bits
            // of TMR1.   
            count = ((TMR0 & 0xFFC0 << 10) + TMR1;
    
            // convert to us
            count >>= 1;
    
            // display...
        }
    }
    

    That's as close as I can get without an actual device and a scope in front of me. Let me know if you have any question or encounter any issues.