【PIC】周波数カウンタの製作(測定編)
周波数カウンタとは、入力されたパルスの周波数を数える電子機器です。
今回は、周波数カウンタをPIC16F688を使って製作してみました。
周波数測定部
周波数を測定するには、PICの「タイマー0」の機能を使います。タイマー0にはT0CK1ピンから入ってきたパルスを数えることができます。
(PIC16F688のデータシートより)
測定されるパルスは、上図の赤線の経路をたどってTMR0レジスタに蓄積されます。
このようにして、タイマー0をT0CK1ピンを使って使用する場合、次のような設定が必要です。
設定 | 理由 |
---|---|
T0SEビット=1 | パルスが立ち上がった(「0」から「1」になった)時にTMR0レジスタをインクリメントするため |
PSAビット=1 | プリスケーラを使わない設定にする。測定したい周波数地によってプリスケーラを設定するべき |
T0CSビットを1 | タイマー0の入力クロックはT0CK1ピンから入力するため |
以上の3つの設定を行うことで、タイマー0のパルスの回数を測定することができます。このようにして、一秒間TMR0でパルスをカウントし、その値を測定した周波数とします。
しかし、それでは0~254Hz(2の8乗)までしか計測できません。TMR0レジスタは8ビットのレジスタで、255個目のパルスが入力されえるとレジスタがオーバーフローするからです。
そこで、OVERFLGという変数を新しく作り、TMR0レジストがオーバーフローしたら、その時は、変数のOVERFLGをインクリメントします。TMR0レジスタがオーバーフローしたかどうかはT0IFビットが1か同課で判断します。
こうすることで、0Hz~65535Hz(2の16乗)の周波数を計測することができます。詳細なプログラムは下に載せています。
データ送信部
上の要領で測定した周波数のデータは、独自にプログラムしたシリアル通信アルゴリズムによって送信するアルゴリズムです。
まず、シリアル通信とは、データ(今回の場合は周波数)を1ビット(バイト)ずつ送信する方法のことです。PICにはEUSARTというシリアル通信の機能がついているが、これを使っても一度に9ビット(0~512)までの数字しか送れないので、シリアル通信のプログラムも自作した。
データを送信するピンはTX_PIN(プログラム参照)で行います。
送信順番は、
- スタートビット(ON)を1ms
- 変数OVERFLGを送信
- TMR0レジスタを送信
の3ステップです。
送信された信号をハンディーオシロ(無料のオシロスコープアプリ)を使って可視化してみました。
ちなみに、ハンディーオシロの使い方は、こちら↓
shizenkarasuzon.hatenablog.com
ハードウェアについて
下のプログラムを動かすための回路について簡単に説明します。
下のプログラムは、T0CK1ピンからの入力パルスの周波数を測定するものなので、測定したい周波数はT0CK1ピンに入力してください。
また、データのシリアル送信はTX_PIN(プログラム参照)で行われます。デフォルトはPORTCの5ピンです。
MCLRリセットを使用しているので、MCLRピンはプルアップしてください。
サンプルプログラム
周波数カウンタの測定部プログラムです。マイコンはPIC16F688を使用します。
周波数カウンタというだけに、時間にシビアな動作が要求されるため、プログラムはアセンブリです。
;/****************************************** ; Frequency Counter (PIC16F688) ;******************************************* LIST P=PIC16F688 INCLUDE "P16F688.INC" __CONFIG _FCMEN_ON & _IESO_OFF & _BOR_ON & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSCIO ;/****************************************** ; 変数 ;******************************************/ GATEDATA EQU 20H ;周波数を格納する最下位バイト OVERFLG EQU 21H ;周波数を格納する最上位バイト CNT1 EQU 23H CNT2 EQU 24H CNT3 EQU 25H CNT4 EQU 28H TX_CNT EQU 26H TEMP EQU 27H ;TX_BITEで送信するデータを入れるバイト #DEFINE TX_PIN PORTC,5 ;データ送信ピン ORG 0 MAIN CALL IOPORT CLRF OVERFLG CLRF GATEDATA MAINLOOP GOTO GET_DATA_L IOPORT CLRF PORTA CLRF PORTC MOVLW 07H MOVWF CMCON0 BSF STATUS,5 MOVLW 75H MOVWF OSCCON CLRF ANSEL MOVLW 0CH MOVWF TRISA CLRF TRISC BCF STATUS,RP0 CLRF TMR0 BCF INTCON,T0IF RETURN ;----------------------------------------- ;GET_DATA_L関数…周波数測定 GET_DATA_L CLRF TMR0 CLRF OVERFLG BSF PORTC,RC2 BCF INTCON,T0IF CLRF TMR0 ;GATE open MOVLW 020H CALL WAIT MOVLW 05H CALL TIMER2 NOP MOVF TMR0,0 ;Gate Close MOVWF GATEDATA BCF PORTC ,RC2 GOTO SEND_DATA DUMYNOP DECFSZ CNT4,1 GOTO DUMYNOP RETURN WAIT MOVWF CNT1 LPCNT1 MOVLW 1AH MOVWF CNT2 LPCNT0 MOVLW 0C7H MOVWF CNT3 LPCNT4 NOP NOP CHECK BTFSS INTCON,T0IF ;TIMER0 GOTO LPCNT2 INCF OVERFLG,1 BCF INTCON,T0IF GOTO LPCNT3 LPCNT2 NOP NOP NOP LPCNT3 NOP DECFSZ CNT3,1 GOTO LPCNT4 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP DECFSZ CNT2,1 GOTO LPCNT0 MOVLW 03H CALL TIMER2 DECFSZ CNT1,1 GOTO LPCNT1 RETURN TIMER2 MOVWF CNT4 LPCNT01 NOP DECFSZ CNT4,1 GOTO LPCNT01 RETURN ;------------------------------------------- ;SEND_DATA関数…データ転送 SEND_DATA BSF TX_PIN MOVLW 0F8H CALL TIMER NOP ;1ms NOP BCF TX_PIN MOVF OVERFLG,W CALL TX_BITE MOVF GATEDATA,W CALL TX_BITE BCF TX_PIN GOTO MAINLOOP ;------------------------------ ;TX_BITE関数…1バイト送信 TX_BITE MOVWF TEMP MOVLW 8H MOVWF TX_CNT TXLPSTART RLF TEMP,F BTFSS STATUS,C GOTO TX0 GOTO TX1 TX0 BCF TX_PIN ;0を送信 GOTO TXLPEND TX1 BSF TX_PIN ;1を送信 NOP TXLPEND MOVLW 0F8H CALL TIMER NOP DECFSZ TX_CNT,F GOTO TXLPSTART RETURN TIMER MOVWF CNT3 LPCNT6 NOP NOP NOP NOP NOP DECFSZ CNT3,1 GOTO LPCNT6 RETURN END
上のプログラムの動作は保証できません。