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;
}
``
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.