Im trying to build a frequency counter using a pic 16F628 and the Capture pin from the CCP module on port RB3 and 2 multiplexed 7 segment displays. Did most of the coding, but I dont have any idea what values I can expect from CCPR1H and CCPR1 registers, so donno what to do with them. I think it should be 0-255 After checking a couple of existing projects using capture pin, I made it up to add together and get divided by 100.. Still It doesnt show anything on my display. I need a 30-200Hz counter, so totally confused if my routine is not initialized properly or if I mixed something up. The displays are working fine and expect to show values on 2 digits as 03-20 for 30-200hz range. Where could I have gone wrong? Please Help. Coded in Hi Tech C, no errors.
Chip is a 16F628, RB0-RB2,RB4-RB7 segment drivers... RA0-RA1- digit drivers, RB3 as capture pin, int osc, RB3 driven by optocoupler.. Timer0 for display mux refresh, Timer1 for capture interrupt. 2 led 7 segment displays muxed..
Input fed through this ckt
Sources are a 9-0-9 ac transformer, pc soundcard output using function generator and a 50Khz multimeter square wave output.. none of these could be detected..
Rich (BB code):
#include <HTC.H>
#define _XTAL_FREQ 4000000 //Internal OSC Freq
#define SEGMENT_TRIS TRISB //Display Segments Connected Ports
#define SEGMENT_PORT PORTB
#define DIGIT_TRIS TRISA //Display Digit select data ports
#define DIGIT_PORT PORTA
__CONFIG(INTIO & WDTDIS & PWRTDIS & BORDIS & LVPDIS ); //Config Bits
unsigned char digits[2]={0,0}; //Defining the Digit Array
//unsigned char kontrol, control;
float counter;
void Wait(unsigned char delay) //Delay Loops
{
for(;delay;delay--)
__delay_us(100);
}
void SevenSegment(unsigned char num) //Defining the segment pattern for each digit 0-9
{
switch(num)
{
case 0:
SEGMENT_PORT= 0B01000000; // Defined in the order xGFEDCBA segments
break;
case 1:
SEGMENT_PORT= 0b11111001;
break;
case 2:
SEGMENT_PORT= 0B00100100;
break;
case 3:
SEGMENT_PORT= 0B00110000;
break;
case 4:
SEGMENT_PORT= 0B10011001;
break;
case 5:
SEGMENT_PORT= 0B00010010;
break;
case 6:
SEGMENT_PORT= 0B00000010;
break;
case 7:
SEGMENT_PORT= 0B11111000;
break;
case 8:
SEGMENT_PORT= 0B00000000;
break;
case 9:
SEGMENT_PORT= 0B00010000;
break;
}
}
void DisplayInit()
{
SEGMENT_TRIS=0b00001000; //Config segment ports as outputs
DIGIT_TRIS=0b00100000; //Config Digit Ports as Outputs
DIGIT_PORT=0B00000011; //Digit select port state
//Setup Timer0 for the Digit Scanning Operation
PS0=1; //Prescaler is divide by 64
PS1=0;
PS2=1;
PSA=0; //Timer Clock Source is from Prescaler
T0CS=0; //Prescaler gets clock from Internal OSC
T0IE=1; //Enable TIMER0 Interrupt
PEIE=1; //Enable Peripheral Interrupt
GIE=1; //Enable INTs globally
TMR0=1; //Staring timer0
}
void Print(unsigned short num) // This function splits a number to Ones and Tens for display on each digit
{
unsigned char i=0;
unsigned char j;
if(num>99) return;
while(num)
{
digits=num%10; //Splitting Numbers and Storing in Arrays
i++;
num=num/10;
}
for(j=i;j<2;j++) digits[j]=0;
}
void SevenSegISR() // Display Scanner which update the multiplexed Displays
{
TMR0=150;
static unsigned char i;
if(i==1)
i=0; //Checking end of Display Scan
else
i++; //Incrementing to next digit for refresh
DIGIT_PORT=((DIGIT_PORT & 0b00111111)|(1<<i)); //Display Output on the Digits
SevenSegment(digits); //Write the digit in the ith display.
}
void interrupt ISR() //Interrupt Service Routine for Display
{
if(T0IE && T0IF) //Check if TMR0 has Overflowed
{
SevenSegISR(); //Call the SevenSegISR
T0IF=0; //Clear Flag for Timer0
}
}
void main()
{
CMCON=0x07;
//unsigned int value;
float frequency;
TMR1CS = 0; //Timer1 uses int clk as osc source
TMR1IF = 0; //Reset Timer1 Flag Bit
TMR1H = 0x00; TMR1L = 0x00; //Reset Timer1 Registers
T1CKPS1 = 0; T1CKPS0 = 0; //1:1 Timer1 Prescalar
T1SYNC = 0; //External Clock Input sync off
TMR1IE = 1; //Timer1 Interrupt enabled
TMR1ON = 1; //Timer1 Enabled and started
CCP1M3 = 0; CCP1M2 = 1; CCP1M1 = 0; CCP1M0 = 1; //Capture Mode enabled on rising edge
CCP1IE = 1; //Prevent False Interrupts
GIE = 1; //Interrupt Enable
PEIE = 1; //Global Interrupts Enable
DisplayInit(); //Initialize the Seven Segment Displays
while(1)
{
// if capture interrupt changed, update 'value' from CCP value
if ( CCP1IF )
{
counter=(CCPR1H+CCPR1L)/100;
CCP1IF = 0;
}
// if timer interrupt: reset timer and toggle Port B.2
if ( TMR1IF )
{
TMR1H = 0x00; TMR1L = 0x00;
TMR1IF = 0;
}
Print(counter);
__delay_ms(100);
}
}
Input fed through this ckt
Sources are a 9-0-9 ac transformer, pc soundcard output using function generator and a 50Khz multimeter square wave output.. none of these could be detected..
Attachments
-
44.6 KB Views: 311
Last edited: