Frequency counter with PIC16F877A

Thread Starter

Bernhard

Joined Apr 28, 2011
2
Hi. I'm working on a project to count the number of interruptions per second. I found this frequency counter schematic and modified the PIC program. Mainly the code counts the number of "1s" on RB0, convert it into decimal, then shows it on the common cathode ssd. The problem I have is showing the number of interruptions in digits because it is supposed to show 1s in 150us, then 10s in 150us, then 100s 150us after, etc... but it only refreshes all seven segment display at the same time. So I can see digit, only the display turned on.
Here is my code and schematic.

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// Project : Simple frequency counter using PIC16F877A, crystal frequency 4Mhz
// compiler : HITEC PICC
///////////////////////////////////////////////////////////////////////////////////////////////////////////


#define PIC_CLK 4000000
#include <pic.h>

///////////////////////////////////////////////////////////////////

__CONFIG(XT & WDTDIS & PWRTDIS & BORDIS & LVPDIS );

///////////////////////////////////////////////////////////////////

unsigned long cntr ; // number of RB0 transition
unsigned int ovrflw ; // number of timer0 overflows
unsigned long x ;
unsigned int y ;

///////////////////////////////////////////////////////////////////

unsigned char digit0, digit1, digit2, digit3;
const char ssd[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//SSD mask for common cathode type

///////////////////////////////////////////////////////////////////


unsigned char delayus_variable;

#if (PIC_CLK == 4000000)
#define dly1u asm("nop")
#define dly2u dly1u;dly1u
#endif

//*****
//delay routine


#if PIC_CLK == 4000000
#define DelayDivisor 4
#define WaitFor1Us asm("nop")
#define Jumpback asm("goto $ - 2")
#endif


void decode(unsigned int value){

digit3=value/1000;
digit2=(value%1000)/100;
digit1=(value%100)/10;
digit0=(value%10);
}


void DelayUs(unsigned char x) {
delayus_variable=(unsigned char)(x/DelayDivisor);
WaitFor1Us;
}


unsigned char delayus_variable;

void DelayBigUs(unsigned int cnt)
{
unsigned char i;

i = (unsigned char)(cnt>>8);
while(i>=1)
{
i--;
DelayUs(253);
CLRWDT();
}
DelayUs((unsigned char)(cnt & 0xFF));
}

void DelayMs(unsigned char cnt)
{
unsigned char i;
do {
i = 4;
do {
DelayUs(250);
CLRWDT();
} while(--i);
} while(--cnt);
}

//this copy is for the interrupt function
void DelayMs_interrupt(unsigned char cnt)
{
unsigned char i;
do {
i = 4;
do {
DelayUs(250);
} while(--i);
} while(--cnt);
}

void DelayBigMs(unsigned int cnt)
{
unsigned char i;
do {
i = 4;
do {
DelayUs(250);
CLRWDT();
} while(--i);
} while(--cnt);
}

void DelayS(unsigned char cnt)
{
unsigned char i;
do {
i = 4;
do {
DelayMs(250);
CLRWDT();
} while(--i);
} while(--cnt);
}
///////////////////////////////////////////////////////////////////

void display(){
unsigned char i;
for(i=0;i<5;i++){
PORTD=0b00000001;
PORTC=ssd[digit0];
DelayUs(150);
PORTD=0b00000010;
PORTC=ssd[digit1];
DelayUs(150);
PORTD=0b00000100;
PORTC=ssd[digit2];
DelayUs(150);
PORTD=0b00001000;
PORTC=ssd[digit3];
DelayUs(150);
}
}

///////////////////////////////////////////////////////////////////

main(){
TRISD=0b11110000;
TRISC=0; //
TRISB = 3 ; //input
///////////////////////

OPTION = 0b11011000 ; //no prescaler
INTCON = 0b10110000 ; //T0IF, INTF and GIE enabled

while(1){
if (RB1 == 1) y=(x/1000); //for scaling Display to KHz

else y=x;

decode(y); //Display frequency on Seven Segment Display
display();

}
}
///////////////////////////////////////////////////////////////////

/* * interrupt routine called 4000000/256 times by seconds :
* the timer TMR0 is increased each 4 clock cycles (quartz frequency is 16 Mhz),
* and overflows when reseting from 255 to 0,
* calling the interrupt procedure with bit T0IF set
* * also called on each RBO transition, with bit INTF set */

void interrupt isr(void){

if ((INTF)){
cntr++ ; // inc. transition counter
INTF = 0 ; // clear interrupt flag to enable next call
}
else if(T0IF==1){
ovrflw++ ; // inc. overflow counter
T0IF = 0 ; // clear interrupt flag to enable next call on overflow
}
if (ovrflw > 3906) { // 4000000/ 4/ 256 = 3906.25
GIE = 0;
x=cntr;
cntr = 0 ; // clear counters
ovrflw = 0 ;
INTCON = 0b10110000 ; // T0IF, INTF and GIE enabled
}
}


I added 330ohm resistors on every segment. Thanks for any help!
 

Attachments

Top