2015.11.3
前へ
次へ
ホームページトップへ戻る

新製品の紹介(プチ連載です)
周波数カウンタ組立キット

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
たまにはちょいと息抜きで小品も作ってみたいものです。
簡単にチョイチョイと…。
でも、なかなかそうは簡単にはいかなくて、いつものごとく回を重ねてしまうことになるのかも…。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜


[第43回]


●再び117で(12)回路図

およそ10日近くの間117の時報を利用した測定を続けてきましたが、前回書きましたように突然のアクシデントで終了を余儀なくされてしまいました。
残念ではありましたが一応の目的はなんとか果たせたように思います。
228時間におよぶ連続カウントの結果から、私が秋月から購入したVM39S5Gの周波数は12800003〜12800004Hzであると推測できそうです。
これはGPSの1PPS信号を利用した測定結果12800002〜12800003Hz([第28回])とは1Hzほど異なっています。
ほんのわずかの差ではありますがちょっと気になるところではあります。

簡単にプチ連載のつもりだったのですが、やっぱり随分と長い道草になってしまいました。
それもぼちぼち終わりに近づいてきましたので、このあたりで締めくくりをしておきたいと思います。

下は117の時報を使った測定に使った回路図です。
GPSの1PPS信号を使った測定回路は[第26回]でお見せしていますが、実はその回路図は理解し易いように必要部分のみを取り出したもので、本当は下の回路図の回路を使いました。


この回路は[第9回]でも使いました。

●プログラムリスト

下は今回の測定で使ったPIC16F883のプログラムリストです。
最近はPICのプログラムもCコンパイラで作成する方が多いようですが、私はもっぱらアセンブラを使っています。
アセンブラはマシン語に1対1で翻訳されますから、今回のプログラムのように精度を要求されるプログラムには特に適していると考えています。

;;; VM39S5G 12.8MHz count
;;; GPS 1pps test
;;; from fcntr4c.asm
; 15/10/6
;15/10/17 hex disp
;10/20 117test
;
; 16f883
; 20MHz crystal
        #include <p16f883.inc>
        __CONFIG _CONFIG1,_WDT_ON & _HS_OSC & _PWRTE_ON & _MCLRE_OFF & _LVP_OFF
        __CONFIG _CONFIG2
;
cf=0
zf=2
f=1
w=0
;
tcn0 equ 20
tcn1 equ 21
rcntr equ 22
dcntr equ 23
tcntr equ 24
rabf equ 25
wk equ 26
fcntr0 equ 27
fcntr1 equ 28
fcntr2 equ 29
fcntr3 equ 2a
scntr equ 2b
lpcntr equ 2c
wcntr equ 2d
dispcntrL equ 2e
dispcntrH equ 2f
;
digit0 equ 30;high
digit5 equ 35
digit6 equ 36
digit7 equ 37;low
;
swoncntr equ 38
;
savests equ 70
savew equ 71
;
     org 00
st0
     goto start
;
        org 4
        goto int
;
     org 05
; 7segment display data
table
        addwf PCL,f
        retlw 7e;0
        retlw 0c;1
        retlw 0b6;2
        retlw 9e;3
        retlw 0cc;4
        retlw 0da;5
        retlw 0fa;6
        retlw 4e;7
        retlw 0fe;8
        retlw 0de;9
        retlw 0ee;a
        retlw 0f8;b
        retlw 72;c
        retlw 0bc;d
        retlw 0f2;e
        retlw 0e2;f
;
start
        movlw 60;bk3
        movwf STATUS
        clrf ANSEL
        clrf ANSELH
        bcf STATUS,6;bk1
        clrf TRISA
        movlw 1
        movwf TRISB
        movlw 0ff
        movwf TRISC
        movwf TRISE
        movlw 0bf;INTEDG=0
        movwf OPTION_REG
     bcf STATUS,5 ;bank0
;HC590 set
        movlw 20;a5=1:count disenable;a4=0;reset;a3=0:not read cntr to reg
        movwf rabf
        movwf PORTA
;LED clesr
        call clrled
waitstart
        clrwdt
        btfsc PORTC,0
        goto waitstart
recount
;       clrwdt
        clrf fcntr0
        clrf fcntr1
        clrf fcntr2
        clrf fcntr3
        movlw 090
        movwf INTCON
        movlw 30
        movwf rabf
        movwf PORTA
        bcf rabf,5;590 count start
        bcf PORTA,5
;swonmk on
        movlw 3e
        movwf swoncntr
        clrf dispcntrL
        clrf dispcntrH          
;
loop
        clrwdt
;LED DISP, indf to LED
ldisp
        movlw 30
        movwf FSR
        movlw 8
        movwf dcntr
        movlw 0f0
        andwf rabf,f
loop2
        movf INDF,w
        call table
        movwf PORTB
        movf rabf,w
        movwf PORTA
        call t2ms
        incf FSR,f
        incf rabf,f
        decfsz dcntr,f
        goto loop2
;2ms*8=16ms
        movf swoncntr,w
        btfsc STATUS,zf
        goto swoncheck
        decf swoncntr,f
        goto dispcntrup
swoncheck
        btfss PORTC,0
        goto swon
dispcntrup
        incfsz dispcntrL,f
        goto loop
        incf dispcntrH,f
        btfss dispcntrH,4
        goto loop
        goto newdisp;about 1min
swon
        movlw 3e
        movwf swoncntr
;
newdisp
        bsf PORTA,3;read cntr
        nop
        movf PORTC,w
        movwf fcntr0
        bcf fcntr0,0
        btfsc PORTE,3
        bsf fcntr0,0
;6/21 for FF
        movf fcntr0,w
        sublw 0FF
        btfss STATUS,zf
        goto div;fcntr0 not FF
        decf fcntr1,f
        movf fcntr1,w
        sublw 0FF
        btfss STATUS,zf
        goto div;fcntr1 not FF
        decf fcntr2,f
        movf fcntr2,w
        sublw 0FF
        btfss STATUS,zf
        goto div;fcntr2 not FF
        decf fcntr3,f
div
        movlw 37
        movwf FSR
        movf fcntr0,w
        call hexdp
        movf fcntr1,w
        call hexdp
        movf fcntr2,w
        call hexdp
        movf fcntr3,w
        call hexdp
;
        clrf dispcntrL
        clrf dispcntrH
        goto loop
;
; subroutine
;
clrled
        movlw 30
        movwf FSR
        movlw 8
        movwf dcntr
clrled2
        clrf INDF
        incf FSR,f
        decfsz dcntr,f
        goto clrled2
        return
;
hexdp
        movwf wk
        andlw 0f
        movwf INDF
        decf FSR,f
        swapf wk,w
        andlw 0f
        movwf INDF
        decf FSR,f
        return
;
tp2ms
        movlw 0fa;=250
        movwf tcn0
tp2ms2
        clrwdt
        decfsz tcn0,f
        goto tp2ms2
        return
;
t2ms
        movlw 0a;=10
        movwf tcn1
t2ms2
        call tp2ms
        decfsz tcn1,f
        goto t2ms2
        return   
;
int
        movwf savew;1
        swapf STATUS,w;1
        movwf savests;1
;
fint
        incf fcntr1,f;1
        btfss STATUS,zf;1 or 2
        goto fintend;2
        incf fcntr2,f
        btfss STATUS,zf
        goto fintend
        incf fcntr3,f
;
fintend 
        bcf INTCON,1;1
;
intend
        swapf savests,w;1
        movwf STATUS;1
        swapf savew,f;1
        swapf savew,w;1
        retfie;2  14+3.5=17.5
;
     end
;


以前にもどこかに書いたように思いますが、私はフローチャートは書かずにいきなりコーディングに入ってしまいます。プログラムリストだけしかありませんから余り参考にはならないかもしれません。
本当はプログラムの概略について注釈を入れるとよいと思うのですが、ずっと脱線状態が続いていますのでいい加減にしておかないといけません。
ですので簡単なメモ程度にしておきます。

上の回路図の7セグメントLEDはダイナミックドライブによる点灯表示をしています。
ダイナミックドライブによる表示は桁ごとに順次短い時間点灯してそれを繰り返すことで全部の桁が同時に点灯しているように見えるようにするものです。
その表示はプログラムで行なっています。
具体的には1桁を約2msずつ表示して8桁全体の表示は16msで一巡します。
その表示を休むことなく続けながら、入力されるパルスの周波数をカウントするために、割込みプログラムを使っています。
高い周波数のパルスでもカウントできるように前段に74HC590を置いています。
74HC590はレジスタ付きの8ビットカウンタです。
カウントする周波数の下位8ビットは74HC590が受け持ちます。
74HC590に256パルス入力されるごとにPIC16F883に割込みが発生します。

周波数のカウントはRC0に接続されたプッシュスイッチからの入力でスタートし、プッシュスイッチが押されるごとにカウントした値をカウントレジスタfcounter0〜fcounter3からLED表示用のレジスタdigit0〜digit7に7セグメント表示データに変換して格納します。
このデータ表示にはひと工夫がしてあります。
次にスイッチが押されるまでデータを保持してそのまま表示するようにしたほうがプログラムは簡単になりますが、それではまともにカウントを継続しているのかどうかちょっと気になりますので、約65秒経つごとにその時点でのカウントデータを表示するようにしてあります。
そのためのカウンタとしてdispcntrL及びdispcntrHを使います。
7セグメントLED表示が一巡するごと(16ms)にdispcntrLを+1し、カウントオーバーでdispcntrHを+1します。
dispcntrHのbit4が1になったとき(両カウンタを16bitカウンタとして、その値が1000H=4096になったとき)に、カウントデータを表示用レジスタに送ります。
16ms×4096=65536msです。

プッシュスイッチ入力についてはもうひとつの工夫がしてあります。
チャタリング回避のために0.1μFコンデンサとシュミットトリガ回路が組んでありますが、さらに念のため一度スイッチ入力を受け付けたら、そのあと約1秒間はキー入力をチェックしないようにしてあります。
そのためのレジスタがswoncntrです。
スイッチが押されるとswoncntrに初期値3E(62)がセットされます。
swoncntrは7セグメントLED表示が一巡するごと(16ms)に−1されます。
swoncntrが0になるまでの期間(16ms×62=992ms)はスイッチ入力を受け付けません。

プログラム動作を簡単にするためにスイッチ入力のチェックは7セグメントLED表示が一巡するごと(16ms)に行ないます。
スイッチ入力はその程度の間隔でチェックしてもよいはずという判断だったのですが、117時報による長時間測定ではそのために±16msの誤差が余計に加わる結果になってしまいました。
精度を上げるためにはスイッチ入力のチェックは2msタイマールーチンの中で行なうべきだったと反省しています。

説明の途中ですが本日は時間がなくなってしまいました。
続きは次回にいたします。

周波数カウンタ組立キット[第43回]
2015.11.3upload

前へ
次へ
ホームページトップへ戻る