とある科学の備忘録

とある科学の備忘録

CやPythonのプログラミング、Arduino等を使った電子工作をメインに書いています。また、木製CNCやドローンの自作製作記も更新中です。たまに機械学習とかもやってます。

【PIC】周波数カウンタの製作(測定編)

周波数カウンタとは、入力されたパルスの周波数を数える電子機器です。

今回は、周波数カウンタをPIC16F688を使って製作してみました。

周波数測定部

周波数を測定するには、PICの「タイマー0」の機能を使います。タイマー0にはT0CK1ピンから入ってきたパルスを数えることができます。
f:id:pythonjacascript:20181202155856j:plain
(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か同課で判断します。
f:id:pythonjacascript:20181202155419j:plain

こうすることで、0Hz~65535Hz(2の16乗)の周波数を計測することができます。詳細なプログラムは下に載せています。


データ送信部

上の要領で測定した周波数のデータは、独自にプログラムしたシリアル通信アルゴリズムによって送信するアルゴリズムです。

まず、シリアル通信とは、データ(今回の場合は周波数)を1ビット(バイト)ずつ送信する方法のことです。PICにはEUSARTというシリアル通信の機能がついているが、これを使っても一度に9ビット(0~512)までの数字しか送れないので、シリアル通信のプログラムも自作した。

データを送信するピンはTX_PIN(プログラム参照)で行います。
送信順番は、

  1. スタートビット(ON)を1ms
  2. 変数OVERFLGを送信
  3. TMR0レジスタを送信

の3ステップです。
f:id:pythonjacascript:20181202163537j:plain

 
送信された信号をハンディーオシロ(無料のオシロスコープアプリ)を使って可視化してみました。
f:id:pythonjacascript:20181202165006j:plain

ちなみに、ハンディーオシロの使い方は、こちら↓
shizenkarasuzon.hatenablog.com

レジスタの送信方法

レジスタに格納されている8ビットの数値を送信するために、このようなアルゴリズムを組みました。

信号線1本でシリアル通信を行っているので、8ビットのデータを1ビットごとに分裂させて、それらを1つずつ送信する必要があります。
f:id:pythonjacascript:20181202163642j:plain

そのため、上の図のように「右シフト」命令を利用しました。

  1. 右シフトを行うと、レジスタの再開ビットの値がキャリーフラグに保存されます。
  2. キャリーフラグの値を送信します。これでデータを1ビット分送信したことになります。

という操作を8回繰り返すと、一つのレジスタの値を送信することができます。


ハードウェアについて

下のプログラムを動かすための回路について簡単に説明します。
下のプログラムは、T0CK1ピンからの入力パルスの周波数を測定するものなので、測定したい周波数はT0CK1ピンに入力してください。
また、データのシリアル送信はTX_PIN(プログラム参照)で行われます。デフォルトはPORTCの5ピンです。
MCLRリセットを使用しているので、MCLRピンはプルアップしてください。

測定部フローチャート

以上をもとに、このようなフローチャートで動作するプログラムを書きます。
f:id:pythonjacascript:20181202165510j:plain
このように、測定部と、送信部の2つの制御で成り立っていることがわかります。


サンプルプログラム

周波数カウンタの測定部プログラムです。マイコン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

上のプログラムの動作は保証できません。