728x90

728x90

Friday, May 15, 2020

PIC16F628A 50MHz Frequency Meters Using Timer1 External Counting

CCS PICC have a ready to use example, demonstrating the technique of using timer 1 external pulses counting to make a 50 MHz frequency meter.

The ex_freq.c explained the the process of making frequency meter using timer 1 of PIC16F877 with a one second delay. The output data is presented in serial terminal.

We can use timer 1 of PIC16F628A to count external digital input pulses. With this advantage, we can make a simple frequency meters, measuring the number of pulses per second.

In this example, I switch the CPU to PIC16F628A with the same build-in timer 1. A 16x2 character LCD uses to present the frequency and period.


PIC16F628A Frequency Meters With LCD
PIC16F628A supplied at +5V, clocks at 20 MHz.
Digital Clock pulse feds into pin RB6 Timer 1 Clock In.
SW1 hold the current frequency/period Value,
when shorted to ground

C Source code and simulation file could be download here:

---------------------------------------------------------------------
#include <16F628A.h>
#fuses HS,NOWDT
#use delay(clock=20000000)    
//one instruction=0.2us
#bit t1_overflow=0x0C.0

#define LCD_ENABLE_PIN  PIN_B2                                        
#define LCD_RS_PIN      PIN_B0                                        
#define LCD_RW_PIN      PIN_B1 

#define LCD_DATA4       PIN_B3                                       
#define LCD_DATA5       PIN_B4                                       
#define LCD_DATA6       PIN_B5                                        
#define LCD_DATA7       PIN_B7                                    


#include<LCD.C>

#define holdButton PIN_A0

void main() {
   int cycles8, cycles;
   long freq;
   long freqc_high;
   long freqc_low;
   set_tris_a(0x01);
   lcd_init();
   
   printf(LCD_PUTC,"Sampling!!!!!!");
   while (TRUE) {
      cycles8=0;
      cycles=0;
      freqc_high=0;
      t1_overflow=0;
      set_timer1(0);
      setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
/* ___ wait one second ___  */
      while (cycles!=0xFF) { //true=3, false=4
       cycles8=0; //1 cycle
       //start inner loop
       while (cycles8!=0xFF) { //true=3, false=4
         if (t1_overflow)//true=2,false=3             //----|
            {t1_overflow=0;freqc_high++;}//6 cycles   //    |
         else                                         //    |-- 8 cycles
            {delay_cycles(5);}                        //----|
         delay_cycles(62); //x
         cycles8++; //1
 ///2 cycles to jump to top
 //math: end inner loop
 //math: total inner loop=((3+8+x+1+2)*255 + 4)*255
 //math: if x=62.87781 then inner loops takes 5mil instructions
 //math: if x=62 then inner loop takes 4942920, have to fill 57080 cycles
  }
 delay_cycles(216);      //y
 cycles++;          ///1 cycle
 ///2 cylces to jump to top
 //math: outer=(3+1+y+1+2)*255+4=57080
 //math: y=(57080-4)/255)-(3+1+0+0+1+2)
 //math: if y=216.827450980392156862745098039216 then outer loop cylces is 57080
 //math: if y=216 then outer loop cycles is off by 211 cycles.  z=211
}
      delay_cycles(211);   //z
/* ___ end waiting 1 second ___ */
      setup_timer_1(T1_DISABLED);   
      //turn of counter to prevent corruption while grabbing value
      if (t1_overflow)            
      //check one last time for overflow
          freqc_high++;
      freqc_low=get_timer1();      
      //get timer1 value as the least sign. 16bits of freq counter
      freq=make32(freqc_high,freqc_low);   
      //use new make32 function to join lsb and msb
      //printf("%LU Hz\r\n",freq);      
      //and print frequency
      lcd_gotoxy(1,1);
      printf(LCD_PUTC,"FREQ:");
      lcd_gotoxy(6,1);
      
      float period;
      if(freq==0){
         printf(LCD_PUTC,"Zero Signal");
         printf(LCD_PUTC,"\nT: -------------");
         
      }
      else if(freq<100000)  {
         printf(LCD_PUTC," %LU Hz      ",freq);
         period=1000.0/freq;
         printf(LCD_PUTC,"\nT: %.6f mS  ",period);
      }
      else if(freq<1000000){
         printf(LCD_PUTC," %3.3f kHz       ",(float)freq/1000.0);
         period=1000.0/freq;
         printf(LCD_PUTC,"\nT: %3.6f mS    ",period);
      }
      else{
         printf(LCD_PUTC," %3.3f MHz       ",(float)freq/1000000.0);
         period=1000000.0/freq;
         printf(LCD_PUTC,"\nT: %.6f uS   ",period);
      }
      
      while(input(holdButton)==0);
   }
}

---------------------------------------------------------------------

Simulation Result:

PIC16F628A Frequency Meters Simulation Result
Simulation Result,
signal feed from a virtual signal generator.
The picture show a sampling signal of 8.299 kHz.

If you want a standard PCB for ATMega32 micro-controller, you can order my AVR Microcontroller project from PCBWay with a reasonable price. Click here to get a free $5 credit for new account.

Interfacing ATMega32 to 74HC595 shift register
ATMega16 ATMega32 Experiment Board PCB from PCBWay

No comments:

Post a Comment

320x50

Search This Blog

tyro-728x90