ソースリスト
#include <16f88.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(CLOCK=20000000)

//LCD_Lib設定
#define mode 0
#define input_x input_B
#define output_x output_B
#define set_tris_x set_tris_B
#define stb PIN_B0
#define rs PIN_B1
#include <lcd_lib.c>
#bit T1_kaisi=0x10.0
#bit T0_IF=0x0b.2

Int End;
Int Sec;
long Count;
Int32 Freq;

#INT_ccp1
void isr(void){
  Sec--;
  if(Sec==0){
  output_low(PIN_A4);
  T1_kaisi=0;
  End=1;
  }
 }

void main()
{
  setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_8);
  set_timer0(0);
  setup_timer_1(T1_INTERNAL | T1_Div_BY_8);
  T1_kaisi=0;
  set_timer1(0);
  setup_ccp1(CCP_COMPARE_RESET_TIMER);
  CCP_1=62500;
  enable_interrupts(INT_ccp1);
  enable_interrupts(GLOBAL);

 while(1)
  {
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_8);
   End=0;
   Count=0;
   set_timer0(0);
   T0_IF=0;
   Sec=10;
   Set_timer1(0);
   T1_kaisi=1;
   delay_cycles(66);
   Input(PIN_A4);

   while(!End){
    if(T0_IF) {
    Count++;
    T0_IF=0;
    }
   }

   Freq=(int32)Count*2048+(int32)get_timer0()*8;

   lcd_init();
   lcd_clear();
   lcd_cmd(0xC0);
   printf(lcd_data,"freq=%Lu",Freq);
   delay_ms(100);
   }
 }

周波数カウンタ

 周波数は単位時間内における周期の数のことです。単位時間は1秒ですので1秒間に何サイクルあるかを数えることになります。ここではPIC16F88を20MHzのクリスタルで動作させて使用しますが、最大周波数は次のように求められるということだそうです。
  最小パルス幅=((クロックサイクル)+40nsec)/プリスケーラ―値
システムクロックは5MHzですので、クロックサイクルは200nsecになり上式に入れると最小パルス幅はプリスケ―ラー値を8で使用しますので30nsecになり周波数は33MHzということになります。オーディオからHFまで測定できるということになります。問題はこの単位時間をいかに作り出すかということになります。一番簡単な方法は delay(1000ms) を使用すればよさそうですが、精度が全く期待できないと言われています。この関数を使用して試したところ5MHz位までは概略値としてカウントはできました。ここではタイマ1とコンパレータを使用しています。条件は以下のようになります。
 タイマ1のクロック=20MHz/4/8=625KHz
 コンペア値=62500
 割込み周期=100msec(62500/625000)
 割込み回数=10
 信号カウント タイマ0を使用
 ゲート停止 信号入力端子を出力モードにする。
 ゲート開始 信号入力端子を入力モードにする。

トップページに戻る

 SGが20000270HzのときPICでは19997624Hzで2646Hzの差で0.13%、132ppmと高精度です。下の写真はSGが30000270HzのときPICでは30000144で126Hzの差で0.004%、4.2ppmです。
 SGは無変調で出力しています。周波数が高いほどSGの出力レベルを上げる必要がありましたが原因調査中です。