fcounter.c

Frequency counter with output on 7-segment display (by Kees van Nieuwburg).



//----------------------------------------------------------------------------------------------------------------------
//
// Author: Kees van Nieuwburg
// Version 1.0
//
//-----------------------------------------------------------------------------------------------------------------------
asm __CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON

char Frequency[8] = {128,128,128,128,128,128,128,128};
char Frequency_old[8] = {128,128,128,128,128,128,128,128};
char Counter[4] = { 0,0,0,0 };
char Digit;

void Display();
void Correct();
char Count_Prescaler();
char Count_12bit();
void Count_delay();


void main(void)
{
  char x,y;

  disable_interrupt( GIE );

  set_bit( STATUS, RP0 );
  OPTION_REG = 52;            // Set pescaler to 1:32 and enable the free-run timer 
               // to increment its value via external impulses on RA4/T0CKI pin.

  set_tris_a( 240 );    // Set RA3 and lower to output 
  set_tris_b( 0 );
  clear_bit (STATUS, RP0 );

  delay_ms(250);
  Count_12bit();     // Reset the 12-bit counter ( The counter wil stop at the point it has to begin its next cycle ). 


  while (1==1)
  {
   TMR0 = 0;         // Reset timer 0
   clear_wdt();      // clear prescaler
   output_port_a( 15 ); // enable counting

   Count_delay();    // count for 1 second

   output_port_a( 12 ); // disable counting

      if( Count_12bit() == 1 )   // The function Count_12bit() wil set the variable Counter. The counter value
      {              // is the amount of pulses that were needed to complete the counters cycle.
                     // If counting isn't succesful Count_12bit() wil return 0.  

         Frequency[0] = Frequency[0] - Counter[0] + 5;
         Frequency[1] = Frequency[1] - Counter[1] + 9;
         Frequency[2] = Frequency[2] - Counter[2];
         Frequency[3] = Frequency[3] - Counter[3] + 4;
         Correct();

         for( x = 0; x < TMR0; x++ )
         {
            Frequency[0] = Frequency[0] + 2;
            Frequency[1] = Frequency[1] + 7;
            Frequency[2] = Frequency[2] + 0;
            Frequency[3] = Frequency[3] + 1;
            Frequency[4] = Frequency[4] + 3;
            Frequency[5] = Frequency[5] + 1;
            Correct();
         }

         y = Count_Prescaler();

         for( x = 0; x < y; x++)
         {
            Frequency[0] = Frequency[0] + 6;
            Frequency[1] = Frequency[1] + 9;
            Frequency[2] = Frequency[2] + 0;
            Frequency[3] = Frequency[3] + 4;
            Correct();
         }


         for(x = 0; x <= 7; x++)
         {
            Frequency_old[x] = Frequency[x] & 15;
            Frequency[x] = 128;
         }

      }else
      {
         for(x = 0; x <= 7; x++)
         {
            Frequency_old[x] = 1;
            Frequency[x] = 128;
         }
      }
   }
}


char Count_Prescaler()
{

   char i, TMR0_old;
   TMR0_old = TMR0;        // Save the value of timer 0

   for(i = 1; i <= 32; i++)
   {
      output_port_a( 0 );  // give a puls
      output_port_a( 8 );

      if(TMR0 != TMR0_old) // check if timer value has changed
      {
         return 32 - i; // return the number of pulses the prescaler counted. 
      }
   }
   return 0;
}


char Count_12bit()
{
   char y, x = 0;

   for(Counter[3] = 0; Counter[3] <= 9; Counter[3] = Counter[3] + 1)
   {
      for(Counter[2] = 0; Counter[2] <= 9; Counter[2] = Counter[2] + 1)
      {

         for(Counter[1] = 0; Counter[1] <= 9; Counter[1] = Counter[1] + 1)
         {
            Display();        // Display a digit

            for(Counter[0] = 0; Counter[0] <= 9; Counter[0] = Counter[0] + 1)
            {
               output_port_a( 12 ); // give a pulse
               output_port_a( 14 );

               y = ( input_port_a() & 16 );
               if( y  == 16 )    // test if RA4 is high  
               {
                  x = 1;
               }
               else if( x == 1 )    // If RA4 has been high before
               {
                  Counter[0] = Counter[0] + 1;  // correct the the counter ( from 0 to ... / 1 to ... )
                  return 1;            // return that the count has been succesful
               }
            }
         }
      }
   }
   return 0;
}




void Correct()
{
   /*    The function correct works like the primary school method of counting
      i believe it's callt "Ten pace ring" in englisch. If a number higher than
      9(137) or lower than zero(128) the function wil correct the nurber. */
   char i;

   for (i = 0; i <= 6; i++)
   {
      if( Frequency[i] < 128 )
      {
         Frequency[i] = Frequency[i] + 10;
         Frequency[i + 1] = Frequency[i + 1] - 1;
      }
      if(Frequency[i] > 137)
      {
         Frequency[i] = Frequency[i] - 10;
         Frequency[i + 1] = Frequency[i + 1] + 1;
      }
   }
}



void Count_delay()
{
   /*    The function Count_delay() should take exactly one second during this   
      time pulses are counted and the frequency is displayed
      I callibrated mij counter with a fuction generator and the following 
      delay worked best for me.                       */

   char i;
   int x;

      for(i = 0; i < 250 ; i++)
      {
         Display();
         delay_ms(1);
         Display();
         delay_ms(1);
         Display();
         delay_ms(1);
         Display();
         delay_us(250);
         delay_us(250);
         delay_us(250);
         delay_us(139);
         nop();
      }
      delay_us(113);
}


void Display()
{
/*    Every time the display function is called the next karakter wil be displayed. */

  Digit = Digit & 7;
  output_port_b( Frequency_old[Digit] | ( Digit << 4 ) );
  Digit++;

}



http://www.sourceboost.com/home.html

Copyright © 2002-2006 SourceBoost Technologies