home CNCの構想 CNCの製作 CNCのSOFT CNCの作品 ゲストブック
08/10/1
PIC周波数カウンターを作ってみました。
PIC16F627
を使いました。秋月で160円です。
追加する回路はほんの少しです。
7SEG LED はカソードコモンです。(上記の実験の物を改造しました)
コレクター抵抗は100オーム VRは20Kを使ってコレクター電圧2.4V位に調整しています。
コレクター電流は 2.6V/100=26mA これ位電流流さないと高い周波数でゲインが低下します。
5V 電源にはコンデンサー入れてください(回路図では省略)
;8-Digit 8-Pin Kカソードコモン LED FCOUNT 08/10/16 JA0BAS
VerUP
LIST
P=PIC16F627A ;
INCLUDE "P16f627A.inc"
__config _BODEN_OFF & _CP_OFF & _DATA_CP_OFF
& _PWRTE_ON & _WDT_OFF & _LVP_OFF & _MCLRE_OFF &
_EXTCLK_OSC
errorlevel -302
; suppress message 302 from list file
; -------------- adress 20&H
dec0 equ 20h
;100MHz 10進格納場所(10バイト)
dec1 equ 21h
;10MHz dec0が最上位桁でdec[9]が最下位桁です。
dec2 equ 22h ;1MHz
dec3 equ 23h
;100KHz
dec4 equ 24h
;10KHz
dec5 equ 25h ;1KHz
dec6 equ 26h
;100Hz
dec7 equ 27h ;10Hz
dec8 equ 28h ;1Hz
dec9 equ 29h ;
overf equ 2ah
vfo_m equ 2eh ;
一時余り格納場所(サブルーチンで使用)
WT EQU 2FH
vfo0 equ 31h
;PSAの値Lo(VFO)。
vfo1 equ 32h
;TMR0の値
vfo2 equ 33h
;TOIFによりインクリメントした値
Vfo3 equ 34h
;VFO(2)のオーバフローによりincした値
wait_cn equ 36h
cn equ 37h
S_DAT EQU 38H
K_POS EQU 39H ;桁位置
K_BP EQU 3AH
O_DAT EQU 3BH
TC EQU 3CH
TW EQU 3DH
W_TEMP EQU 3EH
ST_TEMP EQU 3FH
MOVFF MACRO
DST,SRC ;←MOVFF というマクロを登録、引数は SRC DST
MOVF DST,W
MOVWF SRC
ENDM
org 0
goto init
org 4
goto init
;----------------------------------------------------------------------------
init bsf
STATUS,RP0 ;BANK1
movlw
b'00000111' ;コンパレーターoff FOR 16F617
movwf CMCON
MOVLW B'00000000'
MOVWF TRISB
; portbをOUTに
movlw
B'01100111' ;prescaler 1/256 set ;portbプルアップ;立上カウント
movwf OPTION_REG
BCF STATUS,RP0
;BANK0
MOVLW
b'00000001' ;0桁目の位置
MOVWF K_BP
CLRF K_POS
clrwdt
;prescalerをクリア
clrf tmr0
;TMR0をクリア
main
call
c_main ;counter mein
call x4
;4倍する
call dcmain
;16進->10進変換
clrf vfo0
;変数クリヤ
clrf vfo1
clrf vfo2
clrf vfo3
goto main
; -------------------------------------------------------------------
c_main
clrf portb
clrf porta
bsf STATUS,RP0
;BANK1
MOVLW B'00011000'
MOVWF TRISA
; porta.3 をinput mode=high impedance/TMR0の開始
BCF STATUS,RP0
;BANK0
CLRWDT
;;temp 250 msec カウントの始点
clrf tmr0
;カウンタTMR0をクリア
movlw D'96'
;時間調整
movwf wait_cn
;
decfsz wait_cn,F
goto $-1
NOP
movlw D'152'
;時間調整
movwf cn
cmain0 call
display
decfsz cn,F
goto cmain0
cmain1 ; sleep
;
bsf STATUS,RP0
;BANK1
MOVLW B'00010000'
MOVWF TRISA
;porta.3 をOUT TMR0の停止
250msecカウントの終点
BCF STATUS,RP0
;BANK0
bcf portA,3
movff tmr0,vfo1
;TMR0のdataをvfo1に
toggle bSf
portA,3 ;port porta4のトグル
bCf portA,3
decf vfo0,F
movf tmr0,W
subwf vfo1,w
;vfo1-TMR0=0であれば Z=1
btfsc STATUS,z
goto toggle
RETURN
;vfo0への prescaler値の取込完
;----------------------------------
delay250
;--------------;389steps=389usのルーチン------------
;TMR0のオーバフロー(TMR0IF)のCHK
movlw D'255'
;
movwf wait_cn
;
decfsz wait_cn,F
goto $-1
movff
intcon,overf ;チェックした瞬間を保存
bcf status,c
btfsc overf,2
;
incf vfo2,F
;
btfsc STATUS,c ;
incf vfo3,F
;
btfsc overf,2
;
bcf intcon,t0if
; フラグクリヤ
NOP
RETURN
;
;-------------------------------------------------------------
TABLE ;K_POS値をPCLに+しでJMP,データを持ってretする
ANDLW
B'00001111' ;下位4ビット
ADDWF PCL,F
RETLW b'00111111'
;0 3F C0
RETLW
b'00000110' ;1 06
RETLW
b'01011011' ;2 5A
RETLW
b'01001111' ;3 4F
A
RETLW
b'01100110' ;4 66
____
RETLW
b'01101101' ;5 6D
F | | B
RETLW
b'01111101' ;6 7D
|_G__|
RETLW
b'00000111' ;7 07
E | | C
RETLW
b'01111111' ;8
7F
|____|
RETLW
b'01101111' ;9 6F
D
RETLW
B'01110111' ;A
RETLW
B'01111100' ;b
RETLW
B'01011000' ;C
RETLW
B'01011110' ;d
RETLW
B'01111001' ;E
RETLW
B'01110001' ;F
x4 BCF STATUS,c
;*2 250ms 計測値を4倍する
RLF vfo0,F
RLF vfo1,F
RLF vfo2,F
RLF vfo3,F
BCF STATUS,c ;*2
RLF vfo0,F
RLF vfo1,F
RLF vfo2,F
RLF vfo3,F
return
;---------------------------------------------------------
;32bitバイナリ→10進変換 変換後vfoは破壊
;vfoに32bitデータを置く。(vfo3:vfo2:vfo1:vfo0)
;decに答えが格納(dec0:dec1:...:dec8:dec[9])
dcmain MOVLW H'29'
MOVWF fsr
; 格納場所初期値
call devide
; 最下位変換
call devide
;10回繰り返し
call devide
call devide
call devide
call devide
call devide
call devide
call devide
call devide
; 最上位変換
RETURN
devide MOVLW
D'32' ;÷10サブルーチン
MOVWF cn
; 32ビットくり返し
clrf vfo_m
devide0 BCF status,c
RLF vfo0,F
RLF vfo1,F
RLF vfo2,F
RLF vfo3,F
RLF vfo_m,F
movlw B'11110110'
addwf vfo_m,0
btfsc STATUS,c
movWF vfo_m
btfsc STATUS,c
incF vfo0,F
DECFSZ CN,F
GOTO devide0
decF fsr,F
MOVFF vfo_m,INDF
; 余り
RETURN
;******************************************************************************
display
LEDofF
;規定値 全IN 全消灯
bsf STATUS,RP0
;BANK1
movlw
b'11111111' ;1=inMODE LEDoff
movwf TRISB
BCF STATUS,RP0
;BANK0
CLRF PORTB
CLRF O_DAT
MOVF K_POS,W
SUBLW D'7'
;7桁目か
BTFSC STATUS,Z
GOTO K_7
;7桁目のみfloat lineを使わない別処理
K_ETC
MOVF K_POS,W
;K_POS分だけポインタを進める
SUBLW 27H
;DATAの先頭アドレス
movwf FSR
;アドレスをセット
movf INDF,W
;FSR番地から表示DATA取得
CALL
TABLE ;7SEG DATA に変換
MOVWF S_DAT
;7SEG DATA 保管
MOVF K_BP,W
;float lineの位置
IORWF O_DAT,F
;発光桁を強制的に1にするon K側をLに
COMF O_DAT,F
ANDWF S_DAT,W
;1の部分素通りマスク
BTFSS STATUS,Z
;必要ならfloat lineをHにする
BSF S_DAT,7
;RB7 0=OUT 発光
MOVF K_BP,W
;float lineの位置
IORWF S_DAT,F
COMF S_DAT,F
;反転させ
MOVF O_DAT,W
MOVWF PORTB
MOVF S_DAT,W
bsf STATUS,RP0
;BANK1
MOVWF TRISB
;SEG DATA SET
BCF STATUS,RP0
;BANK0
INCF K_POS,F
;桁+1
BCF STATUS,C
RLF K_BP,F
;桁位置+1
CALL delay250
GOTO LEDOFF
K_7
movf 20h,W
;20h番地から7桁目の表示DATA取得
CALL
TABLE ;7SEG DATA に変換
MOVWF S_DAT
;7SEG DATA 保管
BSF O_DAT,7
;発光桁を強制的に1にするon K側をLに
COMF O_DAT,F
BSF S_DAT,7
;RB7 0=OUT 発光
COMF S_DAT,F
;反転させ
MOVF O_DAT,W
MOVWF PORTB
MOVF S_DAT,W
bsf STATUS,RP0
;BANK1
MOVWF TRISB
;SET
BCF STATUS,RP0
;BANK0
CLRF K_POS
;NEXT 0桁
MOVLW
b'00000001' ;0桁目の位置
MOVWF K_BP
CALL delay250
NOP
NOP
NOP
RETURN
end
プログラムのバグありましたら訂正しますのでご連絡ください。
250mS測定し4倍して周波数にしています。毎秒4回計測します。
2倍、4倍 と言った計算はシフトするだけで計算終わりですのでソフトが簡単高速になります。
8ビットの1/256内蔵プリスケーラーを前置して8ビットのタイマー0を使い測定しています。
このプリスケーラーの性能で最高測定周波数が決まります。
PORTA4がこのプリスケーラーの入力端子です。
PORTA3で250mSのゲートを行っています。
このアセンブラーソースはクロック16MHzで作ってあります。他のクロックの場合は時間調整してください。
100MHzの桁まで表示していますが、この PIC ではプリスケーラーを外付けしないと測定できません。
表示最小桁は10Hzです。
周波数調整可能なクロックを使わないと10Hzの桁は無効(無意味)です。
プログラムの変更必要ですが、超
高精度クリスタルモジュール(12.8MHz±1ppm)が良いと思います。
測定可能最高周波数 41.51766MHz を測定中 色々なPICで試してみますが、40MHz位が測定可能最高周波数です。
18P の PIC で8桁余裕を持って表示しています。
プログラムの工夫で使用ピン数が激減し回路も簡単になりました。
写真のとおり表面に部品がほとんどありません。
9桁表示も可能です。
アマチュア無線などでは430MHz位までは測定したくなります。最近は分周ICの需要がなく入手が難しくなりました。
大昔のTVチューナーか何かをばらして部品を取る!!!
PLLのICで何かで良い物が入手できればいいんですが、知っている方 教えてください。
08/10/16
周波数カウンター ソフトVerUPしました。(バグ取)