Using PIC Capture Compare Module For Frequency Measurement

Thread Starter


Joined Jul 2, 2018
Mod edit: changed thread title to fit subject of thread - JohnInTX

Hello guys i am a beginner in pic microcontroller programming. i have a code for frequency measurement using pic 18f4550 microcontroller.but the problem is although the code sometimes works in real hardware but it did not simuate i proteus simulation software. This code is very important for me since I want to understand how capture module works in pic.Can any guys fix this code as well as post the simulation file in this forum so that i can download them and simulate it.Or provide some alternative code for Testing capture module functionality of pic 18f4550.

// some random garbage uncommented code found on forum
// 20MHz external crystal with no PLL to give 20MHz system clock
// a 5 kHz test square wave is provided on RC1 - link RC1 to RC2 to test operation

#define f_timer 5000000                                    // T1 clock is Fosc/4
sbit LCD_RS at LATB4_bit;
sbit LCD_EN at LATB5_bit;
sbit LCD_D4 at LATB0_bit;
sbit LCD_D5 at LATB1_bit;
sbit LCD_D6 at LATB2_bit;
sbit LCD_D7 at LATB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;

void main ( void ){
unsigned long signal_period,data1,data2;
char frequency_Hz[20];
float Frequency;

    TRISC.TRISC1 = 1;
    OSCCON = 0b1110000;
    PIE1.CCP1IE = 1;
    PIR1.CCP1IF = 0;
    CCP1CON = 0x05;
    CCPR1 = 0x00;
    PIR1.TMR1IF = 0;
    T1CON = 0x80;
    T1CON.TMR1ON = 1;
    TRISB = 0;
    TRISA = 0;                                                  // all outputs
    LATA = 0;                                                   // all low to start with
    TMR1H = 0;
    TMR1L = 0;

    PWM2_Init(5000);                                            // provide test frequency  output on RC1
    PWM2_Set_Duty(127);                                         // square wave
    while( 1 ){
        data1 = CCPR1;
        PIR1.CCP1IF = 0;
        data2 = CCPR1;

        if(data1 < data2){
            Lcd_Cmd(_LCD_CLEAR);                                        // clear out old information
            signal_period = data2 - data1;
            Frequency = ((float)f_timer / (float)signal_period);
            FloatToStr( Frequency,frequency_Hz );
            ///LongWordToStrWithZeros(Frequency, frequency_Hz);
            Lcd_Out(1, 1, frequency_Hz);                                // display new frequency value
            TMR1H = 0;
            TMR1L = 0;
        Delay_ms(500);                                                  // Limit display rate to reduce flicker
Last edited by a moderator:


Joined Jun 26, 2012
// some random garbage uncommented code found on forum
There's problem #1. What makes you think that code from the internet is any good?

But since you asked:
All CAPTURE does is copy the value of TIMER 1 into the capture registers CCPR1H/L and raises CCP1IF when the capture condition is satisfied. That's all it does . Everything else is application dependent.

In this case, the capture is set to occur on every rising edge of the input. It reads the value of the capture register each time then subtracts to find how many TIMER 1 counts elapsed between two successive rising edges. That measures the period of one cycle of the input. It does some math to convert the raw count to a frequency then displays it and repeats. That's how it is supposed to work.

It enables CCP1IE but not the rest of the interrupt enables and that's a good thing since there is no interrupt service routine.

A good thing to do would be to run through this code step by step and write meaningful comments for each step. Look carefully at the flow. Do you think it's a good idea to clear the timer after starting it? At the end, what is the use of clearing the timer then delaying 500ms? The timer runs and runs during that delay making clearing it there ineffective. It will probably capture several edges during that delay. Does that matter? You can't know until you understand how it is supposed to work.

Good luck!


Joined Jan 8, 2017
A few years ago I made a tachometer using the capture compare module on a PIC16F628A. Here is a link to the design on my website. There is a description of how it works and a .zip file that contains the source code. It is written in assembler as I find "C" too difficult to use.