Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

16f882 TMR1 as frequency counter problem

Status
Not open for further replies.

dope40

Member level 4
Joined
Oct 3, 2011
Messages
76
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
Bulgaria
Activity points
1,777
Hi,

I am trying to make a frequency counter using a pic 16f882 .
The idea is using TMR1 to measure the pulse period and use it to get the frequency.

I am using a 16 MHz crystal so that TMR1 increases every 250ns ( FOSC/4 and 1:1 Prescale Value )

Here is the code :

Code:
#include <xc.h>
// CONFIG1
#pragma config FOSC = EXTRC_CLKOUT// Oscillator Selection bits (RC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, RC on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Reset Selection bits (BOR enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)

// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)					

#define _XTAL_FREQ 16000000
#include <stdio.h>
#include <stdlib.h>
int aa, bb, state ;
unsigned long overflow, total ;


void interrupt tc_int()
{
  if (T1CONbits.TMR1ON == 0) {
    T1CONbits.TMR1ON = 1 ;  // start timer
    INTCONbits.INTF = 0 ; // clear flag
  }   
  
  else if (T1CONbits.TMR1ON == 1) {
      T1CONbits.TMR1ON = 0 ; // disable TMR1
      total =(TMR1H<<8)|(TMR1L);
      INTCONbits.INTE = 0 ; // disable interupt
      TMR1H=0;
      TMR1L=0;
      // total =(4000000/total);
      INTCONbits.INTE = 1; //Enable RB0/INT external Interrupt
      INTCONbits.INTF = 0; // clear the interrupt flag
  }

}   
void Init(void){
    TRISA = 0xFF;   //set all digital I/O to inputs
    TRISB = 0xFF;
    TRISC = 0xFF;
    ANSEL = 0x00;   //disable all analog ports
    ANSELH = 0x00;
    
    T1CON=0X00;
    TMR1H=0;
    TMR1L=0; // intialization of timer one prescalar and internal clock
    INTCONbits.GIE = 1; //Enable Global Interrupt
    INTCONbits.INTE = 1; //Enable RB0/INT external Interrupt
    OPTION_REGbits.INTEDG = 0; //Interrupt on rising edge
}
void main(void)
{
    Init() ;

    while(1)
    {
     
    }

}

I am feeding 100 Hz in RB0 pin. Based on that i am expecting the value of Total to be 40000 , but i get around 19000 ( using PICKit 3 as debugger , also my freq. gen is not ideal so i am expecting some fluctuation . Still i get half of what i am expecting ).

The interrupt is on the rising edge.

Does anyone know what i am doing wrong ?

P.S .... Also i failed to mention , for the purposes i need it the duty cycle is high ( ~ 90 % ) , but still i think that shouldn't be a problem , right ?
 

Hi,

The precise way is to use "capture" mode to get exact timestamps.

On one rising edge you get a timestamp (start)
On the next rising edge you get the next timestamp (stop)

The frequency is calculated by: f = 4000000 / (timestamp(stop) - timestamp(start))

Don't reset the counter value.
The result is correct as long as the input frequency is higher than: 4000000/65536

Klaus
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top