新製品の紹介(プチ連載です)
周波数カウンタ組立キット
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
たまにはちょいと息抜きで小品も作ってみたいものです。
簡単にチョイチョイと…。
でも、なかなかそうは簡単にはいかなくて、いつものごとく回を重ねてしまうことになるのかも…。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第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
前へ
次へ
ホームページトップへ戻る