Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC16F877A Based Frequency Measurement

Status
Not open for further replies.

Sujit Mishra

New Member
Dear sir, I am trying to use CCP module of PIC16F877A uC in capture mode too read input frequency. I have written a small code for it but unfortunately its not working. Can anyone guide me what mistake am I making in it. Below is my code, Thanks.
Code:
#include <htc.h>
#include "LCD.h"

__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_OFF & BOREN_ON
& LVP_OFF & CPD_ON & WRT_OFF & CP_ON); // configuration bits

#define _XTAL_FREQ 4000000 // 4MHZ external crystal

void InitGPIO(void)
{
__delay_ms (10); // Power up delay
TRISCbits.TRISC2 = 1; // CCP1: Configure as input pin
ADCON1 = 0x0F;
}

void CCPInit(void)
{
CCP1IE = 0; //Disables the CCP1 interrupt
CCP1IF = 0; //No TMR1 resister capture occurred
T1CON = 0x01;
CCP1CON = 0x05; //Capture mode, every rising edge
}

void main (void)
{
unsigned int start, end, period;
float result, frequency;

InitGPIO();
InitLCD();
CCPInit();

lcd_gotoxy(0,4);
WriteStringToLCD("FREQUENCY");

while(1)
{
while(!(CCP1IF)); // Wait first rising edge
CCP1IF = 0; // Clear flag not next round
start = CCPR1L; // Save value of first rising edge

while(!(CCP1IF)); // Wait first rising edge
CCP1IF = 0; // Clear flag not next round
//CCP1CON = 0x00; // Disable CCP1 capture module
end = CCPR1H; // Save value of second rising edge

period = (end - start);
period = (float)period;
frequency = (1/period);

lcd_gotoxy(1,4);
disp_num(frequency);
__delay_ms(1);
}
}
 

Attachments

  • LCD.c
    8.9 KB · Views: 252
  • LCD.h
    1.2 KB · Views: 239
Last edited by a moderator:
First... How fast do you need this...

4Mhz crystal.. 1us TOSC.... Therefore TMR1 will time out in approximately 65mS that makes 15Hz your lowest frequency..

When CCP1IF fires you save the lower val in start and the higher val in end???

Lastly this line frequency = (1/period); will not yield the correct result... Period is an integer and the constant 1 will also be an integer..

Here is how I did t..
C:
       period = (end - start);
       frequency = (divisor * period);
       result = (int)(1/frequency);

The reason for the divisor is because I set T1CON to 0x31 to give an 8:1 pre-count so I could have slower frequency
The divisor needs to be set to 0.000008 to allow for the 8:1

Also clear the timer before you measure.. This way the result will never cross the zero.. Capture the whole CCP1 reg not just the lower or the higher one..
C:
TMR1 = 0;
       while(!(CCP1IF)); // Wait first rising edge
       CCP1IF = 0; // Clear flag not next round
       start = CCPR1; // Save value of first rising edge

       while(!(CCP1IF)); // Wait first rising edge
       CCP1IF = 0; // Clear flag not next round
       end = CCPR1; // Save value of second rising edge
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top