I wrote the following code to measure the frequency of a square wave using the capture module of the PIC16f1788. I wrote the code by following step by step what is required in the datasheet of this PIC. I would like to know if I have missed any important step in doing so and If my code makes sense. This is the first time that I use the capture module so any suggestions are welcome. Thanks
#include <xc.h>
// Config word
#define frequ 2
#define _XTAL_FREQ 32000000
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = ON // Watchdog Timer Enable (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config VCAPEN = OFF // Voltage Regulator Capacitor Enable bit (Vcap functionality is disabled on RA6.)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF // Low Power Brown-Out Reset Enable Bit (Low power brown-out is disabled)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
void main(void)
{
int count=0;
float rise1=0,rise2=0,frequency,period;
OSCCON = 0b11111010;
// clear the interrupts at beginning that way we are sure that our calculations will be exact no previous interrupt present
PIR1.CCP1IF=0;
PIE1.CCP1IE=0;
// output
TRISBbits.TRISB0 = 1; // set it to input
APFCON1bits.CCP1SEL=1;// toggle the CCP port output to RB0 from RC2
// configure CCP1
CCP1CONbits.CCP1M = 0x05; // set it to Capture mode; on every rising edge
While (count=! 2){
count +=1; // increment the value of count
// configure Timer 1
T1CONbits.TMR1CS = 0; //set the timer 1 clock to instruction clock Fosc/4 as mentioned in page300
T1CONbits.TMR1ON = 1; // set Timer 1 on
delay_us(10); //aquisition time
T1GCON.T1GO/nDONE=1; // aquisition is ready wait for a rising edge
while (T1GCON.T1GO/nDONE=1); //wait untill the aquisition is complete
if (count==1) {
rise1=CCPR1; } //capture the first rising edge and store that value in rise1
if count ==2) {
rise2=CCPR1; } // capture the second rising edge and store the value in rise2
}
period = rise2-rise1; // subtracte both values to get the period of the signal
frequency=1/period;
// clear any interrupts that are set
PIR1.CCP1IF=0;
PIE1.CCP1IE=0;
}
Best Answer
From your request I am trying to explain frequency measurement using two timer. A timer can be used in various modes but here we need only two mode to use.
Since you are working with pulses then make Timer0 as a counter. Use Timer1 to measure a duration of 1 second . Suppose Timer0 starts counting the pulses, in the meantime Timer1 measures the time duration. When It measures 1 second, collect the value of counter. If the value of counter is 100 then frequency is 100Hz. Both Timer uses interrupt so your main code is free to assign any other tasks.
This code is written in MikroC. You can convert it as your compiler requirements. You can see this tutorial for further details.
I saw some tutorial where a delay of 1 second is made to measure frequency. But a 1s delay just set the processor idle for 1 second which is wastage of resources. The key idea is to make this delay by interrupt method then I can place another tasks for the controller such as voltage or current measurement. I think this will be helpful for all.