;ソースファイル そのまま掲載
秋月のPICライタ添付の参考プログラムを多用してあります
注釈がいっぱい入っていますが、私はこれでも難解?でした
きれにコーデングしてと思いましたがめんどうなのでそのまま掲載します
FILE : PLL50A .ASM ------copy right(c) JA0ESA 1999
; PLL49C の不要個所カットバージョン バグck ok
; 50k 12.8tcxo STEP band sw 対応
; 秋月テレビチユーナのPLL用に作った 液晶表示回路 start 1999/08/03
; 使用環境 PIC16F84-10/P クロック10 aki TV TUNER +XTO 12.8MHz+74HC393
; 16C84はレジスタ不足で動作不可
; 拡張アセンブラPA.EXE・秋月ライタ
; 液晶 M1632
; ピンアサイン
; PIC16F84 液晶モジュール
; ()内はピン番号
; RA0(17) ---------- E(ENABLE)
; RA1(18) ---------- RS
; RA2(1)------------ ENCOD A PULL UP
; RA3(2)------------ ENCOD B PULL UP
; RA4(3)------------ MHz bottom
; GND(0V) = R/~W
; RB4(10) = DB7
; RB5(11) = DB6
; RB6(12) = DB5
; RB7(13) = DB4
; GND(0V) = DB3
; GND(0V) = DB2
; GND(0V) = DB1
; GND(0V) = DB0
; RB0 TD63PLL ENA
; RB1 TD63PLL DATA
; RB2 TD63PLL CLOCK
; RB3 -----free
;
; ****ソフトのおしながき********************
; 購入した物は4Mの水晶が入っており基本ステップは31.25Kです
; こうするとPLLのメインカウンタが1メガづつの上下になり非常に便利
; ですが、いかんせPLLの悪さ!!には手を焼いてしまいました、12.8メガの
; XTOに交換し、74HC393で1段分周し基準クロックは6.4メガとしました
; 基準クロックの製造でさらに回路の複雑化が予想されましたが、これにより
; 周波数の精度は格段に向上し、合わせてVCOのロック時のビート(ふらつき)
; がかなり改善されました、使っていた水晶(4MHz)の安定度や品物がかなり
; 悪かったものと思われます、
; 50Kステップの設定なので表示のアルゴを以前から大幅に手直改善しました
; 前はレジスタシフトを0を見て判定していましたが、単純にレジスタを並べて
; 右ローテートを行っています、LSBの最初のビットはキャリーにいきますが
; 次のローテートでキャリーをUSBの最上位に入れますので問題はありません
; この操作で表示の原始データをPLLレジスタから抽出しています
; 初期設定では433.00に周波数が出ます、ロータリーエンコーダの1ステップ
; が50KHzづつ可変します、HIボタンを押すと4.8メガづつの可変に
; なります、秋月のユニットは3バンドのVCOが入っていますがどの
; VCOも無限に可変は出来ません!(あたりまえ)VCOの切り替えはICに送る
; データの最初の4ビットが対応します
; 発振周波数
; VHF LOW VCO: 90.00 - 179.15 Aと表示
; VHF HIGH : VCO: 179.20 - 379.15 B
; UHF: VCO: 379.20 - 819.15 D
; SHF : VCO 900-980 C
; 一応周波数の切れ目は無いようになりましたが各VCOの切り替え周波数
; は動作設計規格的に無理を承知での動作です!!
; 出力はPLLICのVCO検出からコンデサカップリングで取り出してあります
; そうでないと各VCOから取り出さないとなりません、オーバー500メガ
; の高周波回路の切り替えはストリップライン上であっても平坦な切り替え特性を
; 維持するにはかなりの熟練?とテクが必要です切り替えダイオードのアイソレーション
; を考えると自信が無いのでもっとも簡単な方法としました
; SGであれば0dbmくらいの出力は不可欠ですがいくらがんばっても−30
; が限界のようですのでミニサーキットのアンプを2段かましてありますがそれにしても
; −10が眼界です、それも各周波数の出力平坦度はお世辞にも良いとはいえません
; しかし小型で当てになる周波数は貴重ですし¥も5K以内ですしこれで満足
; 90から800までの50KセパのSGとしました
.include 16f84.h ; 16F84を選択
.osc xt ; オシレータXT
.wdt off ; ウォッチドッグOFF
.pwrt on ; パワーアップタイマON
.protect off ; プロテクトOFF
E equ ra.0
RS equ ra.1
td63_ena equ 6.0
td63_dat equ 6.1
td63_clk equ 6.2
org 0ch
key ds 1 ;エンコーダの直値が入るポジクロック
temp ds 1;チャタ比較の前データ
udgap ds 1 ;ユーデーギャップと発音
;これの0ビットがアップクロックがきた時(エンコーダの)
;1になる、このときエンコーダのB入力の論理でアップダウン
;が決まる、アップダウンの情報はこの1ビット目に入る
;この値は保持されて、この状態から待って クロックダウン
;が着たら初めて 1パルスのカウントになる
;当然この時点でこの情報はクリアされて また待つのダ
;PLLのデータはPLL_B DAT_HIGH DAT_MID DAT_LOWの4ツの
;レジスタに保存される、実際の送り出しはテンポラリ
;に一時入りこいつが左シフトするたびにターゲットビット
;の状態チェックが入りデータクロックが作られる
;PLLデータは4-10-5の19ビットであるから
;データレジスタは当然無効ビットが存在する
pll_tmp ds 1 ;PLL操作のテンポラリ
pll_cnt ds 1 ;pLL計算回数カウンタ
pll_b ds 1 ;pll fast int data for BAND(low 4bit)
cnt1 ds 1 ;
cnt2 ds 1 ;
wait_cn ds 1
wait_cn2 ds 1
wait_s ds 1 ;sec
d4 ds 1 ;液晶表示サブ 内部で使用
d8 ds 1
cn ds 1
poi ds 1
chr ds 1
yy ds 2 ; 乗数(2bytes)
xx ds 2 ; 被乗数(2bytes)
zz ds 4 ; 演算結果(4bytes)
cn1 ds 1 ; サブルーチンmul_xyで使用
mup ds 1 ; MHz bottom flg
val ds 4 ;変換ルーチンで使用するレジスタ
dec ds 10 ;デシマル変換後のデータが入る
dec_top ;配列変数のトップ ポインタ
cnd ds 1 ;10進変換サブで使用
val_m ds 1 ;10進変換サブで使用 一時余り格納
dat_high ds 1 ;;PLL Higher Byte LSB 2bit
dat_mid ds 1 ;PLL Middle Byte ALL 8bit
dat_low ds 1 ;PLL Swalow Byte USB 5bit(&H8づつの増減)
abc ds 1
nowcnt equ udgap.0 ;カウント中ですよ のフラグ
ud_ck equ udgap.1 ;回転方向フラグ
enc_a equ temp.2 ;エンコーダAのビット定義
enc_b equ temp.3 ;同じくB
hi_key equ temp.4 ;HIキーのビット定義
org 0
goto start
org 4
goto start
start
mov !ra,#00011100b ; E,RSピンをOUTに
mov !rb,#00001111b ; DB7-DB4ピンをOUTに
clr ra
clr rb
call init_lcd ; LCD初期化
call title ; サンプル文字列表示
clr poi
endless call scroll ; 文字をスクロールして
mov wait_s,#5
call wait_sec
goto st ;----jmp fucker ->
title_tbl jmp pc+w ; テーブル参照
title_mes retw ' PLL SG 800MHz '
retw ' Ver50A JAOESA ' ;最初に液晶に表示される
scroll
call scr
mov wait_cn,#0 ; しばらくウェイト
call wait_ms
mov wait_cn,#0
call wait_ms
inc poi
ret
scr
clrb RS
mov d4,#11000000b
call write_lcd4 ; カーソルを1行目に移動
mov cn,#16 ; 16文字
setb RS ; 以後のコマンドは文字表示
scr0
and poi,#15
or poi,#16
mov w,poi
call title_tbl
mov d4,w
call write_lcd4
inc poi
djnz cn,scr0
ret
title
clrb RS
mov d4,#10000000b
call write_lcd4 ; カーソルを1行目に移動
clr poi
call putchar
clrb RS
mov d4,#10000000b+64
call write_lcd4 ; カーソルを2行目に移動
call putchar
ret
putchar
mov cn,#16 ; 16文字
setb RS ; 以後のコマンドは文字表示
putchar0 mov w,poi
call title_tbl
mov d4,w
call write_lcd4 ; 文字表示(RS='H'にしてください)
inc poi
djnz cn,putchar0 ; 16文字分くり返し
ret
;*********** MAIN PROGRAM *************************************
st
mov !ra,#00011100b ; E,RSピンをOUTに
mov !rb,#00000000b ; port B をOUTに
clr ra
clr rb
mov udgap,#0 ;Initial set of Up/down skew
mov pll_b,#08h ;select BAND UHF 1000b
mov dat_high,#01h
mov dat_mid,#0Eh ;set int PLL /// f=433MHz//
mov dat_low,#10100000b ;swakow =20d+ Low 3bit =
mov wait_s,#1
call wait_sec
call send_pll ;int data out TD63
call init_lcd ; LCD初期化
call dsp_f
mov wait_s,#1
call wait_sec
clr udgap
;%%% START OF MAIN LOOP %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
rsw ;--------ROTARY ENCODER INPUT ---------------
bcf td63_ena ;ここは不用かも どこの
bcf td63_dat ;サブに飛んでPLLのデータポート
bcf td63_clk ;攪乱されると怖いのでおまじない程度
call rsw_wait
movf ra,w
movwf key
comf key,0
andlw 00011100b ;入力以外のビット排除
movwf key
xorwf temp,0
jz clk_ck
mov temp,key
jmp rsw
clk_ck ;-----チャタなしでここへ----------------------
btfsc nowcnt ;カウント中フラグを見る
jmp clkdown ;カウント中だ ダウンクロック待へ
nop ;カウント中でない
btfss enc_a ;a相の状態は1か
jmp rsw ;0 だから再入力へ
mov udgap,temp ;1 だ upgapのB相の状態をセット
rr udgap
rr udgap
and udgap,#00000011b ;上位をマスク
jmp rsw
;---------------------------------------------------------------------
clkdown
btfsc enc_a
jmp rsw
nop
btfsc ud_ck ;上下方向をチェック
jmp up_1 ;"1" up
jmp down_1 ;"0" down
nop
up_1
call pll_up ;周波数レジ計算
call send_pll ;PLLの送信
call dsp_f ;表示LCD処理
nop ;アッププロセス
jmp exit1
down_1
call pll_dwn
call send_pll
call dsp_f
nop ;ダウンプロセス
exit1
clr udgap
clr temp ;
jmp rsw
;%%%%%%%%%%%%%% END OF MAIN LOOP %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;%%%% PLL COUNT%%%%%%%%%%
;------- Count UP 50K ------
pll_up
BTFSC HI_KEY ;check SFT switch
GOTO pll_mup ;count up by 1MHz
;/// count up by 50 KHz ///---
bcf c ;reset carry
add dat_low,#8h ;pll_low+8h swalow counte LSB 5bit
btfss c ;overflow?
ret ;not overflow
add dat_mid,#1 ;dat_mid +1
btfss c ;overflow
ret ;not overflow
add dat_high,#1 ;dat_high +1
ret
;-------/ Count up by 4.8 MHz/-------
pll_mup
bcf c ;reset carry
add dat_mid,#3 ;dat_mid +1 1
btfss c ;chick overflow
ret ;not overflow
add dat_high,#01 ;overflow data hi reg inc
ret
;%%%%%%%(Count down PLL data)%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pll_dwn
BTFSC HI_KEY ;check SHT switch
GOTO pll_mdwn ;count DOWN by 1MHz
;---(Count down PLL 50KHz --------------------------
bcf c
sub dat_low,#8h ;dat_low-08h
btfsc c ;under flow?
ret ;not under flow-> return
sub dat_mid,#1 ;underflow (next sub) mid-1
btfsc c ;chck dat_mid under flow?
ret ;not under flow then return
sub dat_high,#1 ;dat_mid under flow ->dat_high-1
ret
;----- Count down PLL (4.8 MHz step)------------------------
pll_mdwn
bcf c ;Mhz is dat_mid and dat_high
sub dat_mid,#3 ;sub dat_mid
btfsc c ;ck under flow
ret ;ボローなし
sub dat_high,#1 ;ボローあり次の桁から引く
ret
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;[[ SEND TD6382 PLL IC ]]----------------------------
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
send_pll ;send data = 上位ビットから順に送り出す事
;-(1)band data send------
;バンドの定数の計算
and dat_high,#00000011b
cje dat_high,#1,uhf_band
cje dat_high,#2,shf_band
cje dat_high,#3,shf_band
nop
cja dat_mid,#236,uhf_band
nop
cja dat_mid,#111,vhh_band ;
nop
mov pll_b,#01h ;0000 0001 vhf low
jmp skip_b
shf_band mov pll_b,#04h ;0000 0100
jmp skip_b
uhf_band mov pll_b,#08h ;uhf band sel
jmp skip_b ;0000 1000
vhh_band mov pll_b,#02h ;0000 0010
skip_b
;--------------50k---UHF ONLY SELECT TRAP ---990927
;mov pll_b,#08h
bcf td63_ena
bcf td63_dat
bcf td63_clk
mov wait_cn,#01
call wait_ms
bsf td63_ena ;ICデータイナーブル アクテイブ
mov wait_cn,#01
call wait_ms
;------ SEND BAND DATA --------
mov pll_tmp,pll_b ;一時メモリにバンドデータを
mov pll_cnt,#04h ;カウンタに有効ビット数を
sb1
btfsc pll_tmp,3 ;if bit3 "0" next skip
bsf td63_dat ; bit3 "1" --> data port "1"
btfss pll_tmp,3 ;if bit3 "1" next skip
bcf td63_dat ; bit3 "0" ---->data port "0"
rl pll_tmp ; pll_tmp <-- <-- <--
call td63_clkout
bcf td63_dat
dec pll_cnt
jnz sb1 ;IF (CNT= 0) Skip CNT>0 non Skip
;--PLL MAIN ------send to PLL data of maincounter
;
mov pll_tmp,dat_high
mov pll_cnt,#02h ;set data count
sh1
btfsc pll_tmp,1 ;data chick XXXX XX12 :pll_h 3456 7890:pll_l
bsf td63_dat ;if data 1
btfss pll_tmp,1
bcf td63_dat ;else data 0
rl pll_tmp ;
call td63_clkout
bcf td63_dat
dec pll_cnt
jnz sh1 ;IF (CNT= 0) Skip CNT>0 non Skip
;--send PLL DADA MID bit -----
mov pll_tmp,dat_mid
mov pll_cnt,#08h ;★処理データは8ケ
sm1
btfsc pll_tmp,7 ;data ck pll_low
bsf td63_dat ;if dat =1
btfss pll_tmp,7
bcf td63_dat ;else dat=0
rl pll_tmp
call td63_clkout
bcf td63_dat
dec pll_cnt
jnz sm1
;--SEND PLL SWALOW COUNTER---------
mov pll_tmp,dat_low ;一時メモリにバンドデータを
mov pll_cnt,#05h ;カウンタに有効5ビットを
sl1
btfsc pll_tmp,7 ; bit7 "0" next skip
bsf td63_dat ; bit7 "1" --> data port "1"
btfss pll_tmp,7 ; if bit7 "1" next skip
bcf td63_dat ; else data port "0"
rl pll_tmp ; pll_tmp <-- <-- <--
bcf pll_tmp,0
call td63_clkout
bcf td63_dat
dec pll_cnt
jnz sl1
call time3
call time3
bcf td63_ena ;ENABL OFF
call time3
call time3
call time3
call time3
bcf td63_ena
bcf td63_dat
bcf td63_clk
ret
;************************************************
dsp_f ;周波数をlcdに表示する
call csrm1 ;LCD csr 1行目へ
mov chr,#10100000b ;space
call dsp_one
;---周波数計算-----
mov xx[0],#05h ; 50khz -->5で計算して1桁もうけ
mov yy[0],dat_low
mov yy[1],dat_mid
mov xx[1],dat_high ;xx[1]を仮使用し最後に開放
rr xx[1]
rr yy[1]
rr yy[0]
rr xx[1]
rr yy[1]
rr yy[0]
rr xx[1]
rr yy[1]
rr yy[0]
bcf yy[1],7
mov xx[1],#0 ;
call mul_xy ; 答えはz配列に入る
mov val[0],zz[0]
mov val[1],zz[1]
mov val[2],zz[2]
mov val[3],zz[3]
call stbd ;binary->decmal convert sub
mov chr,dec[5]
add chr,#30h ;asc code shif
call dsp_one
mov chr,dec[6]
add chr,#30h ;asc code shif
call dsp_one
mov chr,dec[7]
add chr,#30h ;asc code shif
call dsp_one
mov chr,#00101110b ;chrコードで . (点)
call dsp_one ;周波数の区切り表示
mov chr,dec[8]
add chr,#30h ;asc code shif
call dsp_one
mov chr,dec[9]
add chr,#30h ;asc code shif
call dsp_one
mov chr,#'0'
call dsp_one
mov chr,#01001101b ;'M'
call dsp_one
mov chr,#01001000b ;'H'
call dsp_one
mov chr,#01111010b ;'z'
call dsp_one
mov chr,#10100000b
call dsp_one
mov chr,#10100000b
call dsp_one
mov chr,#0b0h ;'-10 と表示 意味はない!ダジャレ'
call dsp_one
mov chr,#'1'
call dsp_one
mov chr,#'0'
call dsp_one
mov wait_cn,#2
call wait_ms
dsp_band
call csrm2 ;LCD csr 2行目へ
mov chr,#10100000b
call dsp_one
mov chr,#'v'
call dsp_one
mov chr,#'c' ;'vco:
call dsp_one
mov chr,#'o' ;'vco:
call dsp_one
mov chr,#':'
call dsp_one
btfsc pll_b,0
movlw 'A'
btfsc pll_b,1
movlw 'B'
btfsc pll_b,2
movlw 'C'
btfsc pll_b,3
movlw 'D'
movwf chr
call dsp_one
mov wait_cn,#2
call wait_ms
ret
;---------------液晶初期化ルーチン---------
init_lcd
mov wait_cn,#15 ; wait 15ms
call wait_ms
clrb RS ; RS='L'
mov d8,#00110000b
call write_lcd8
mov wait_cn,#5 ; wait 4.1ms
call wait_ms
mov d8,#00110000b
call write_lcd8
mov wait_cn,#100 ; wait 100us
call wait_us
mov d8,#00110000b
call write_lcd8 ; 0 0 0011 (3)
mov d8,#00100000b
call write_lcd8 ; 0 0 0010 (4bit)
;
mov d4,#00101000b ; duty,font set9
call write_lcd4
mov d4,#00000001b ; クリアコマンド
call write_lcd4
mov wait_cn,#2 ; クリアが終わるまで待つ
call wait_ms
mov d4,#00000110b ; entry mode set
call write_lcd4
mov d4,#00001100b ; display on,cursor off
call write_lcd4
ret
;-----------------------------------
cshome ;カーソルホーム移動
clrb RS
mov d4,#1
call write_lcd4
ret
;------------------------------------
csrm1 ;カーソル1行目に移動
clrb RS
mov d4,#10000000b
call write_lcd4
ret
;----------------------------------
csrm2 ;カーソル2行目に移動
clrb RS
mov d4,#11000000b
call write_lcd4
ret
;-----------------------------------
cls ;表示クリア
clrb RS
mov d4,#00000001b ; クリアコマンド
call write_lcd4
mov wait_cn,#2 ; クリアが終わるまで待つ
call wait_ms
mov d4,#00000110b ; entry mode set
call write_lcd4
mov d4,#00001100b ; display on,cursor off
call write_lcd4
ret
;------------------------------
dsp_one ;1文字表示 reg:chrにコードを入れて使う
setb RS
mov d4,chr
call write_lcd4
ret
;---------------8ビットモード専用液晶ライトルーチン
write_lcd8
movf d8,0
andlw 11110000b
movwf rb ; RBポートへ出力
nop
setb E ; Eピンを'H'
nop
clrb E
mov wait_cn,#40
call wait_us
ret
;-------------- 4ビットモード専用液晶ライトルーチン
write_lcd4
mov d8,d4
call write_lcd8 ;最初に4ビット
mov d8,d4
swap d8 ;ビット入れ替えしてもう4ビット
call write_lcd8
ret
ad32 ;---- 32 bit バイナリ加算------------- 971213ms---
incsz val[0] ;inc reg if carry skip next
goto ad32exit ;not caryy exit loop
incsz val[1] ;on caryy next byte adder
goto ad32exit ;以下同じ繰り返し
incsz val[2]
goto ad32exit
incsz val[3] ;32bit over flow
ad32exit
ret
;******************* bin-> dec converter *********************************
;
bdm1
mov fsr,#dec_top ; 格納場所初期値
call devide ; 最下位変換
call devide
call devide
call devide
call devide
call devide
call devide
call devide
call devide
call devide ; 最上位変換
ret
;------- ÷10サブルーチン
;
devide
mov cnd,#32 ; 32ビットくり返し
clr val_m
devide0
clc
rl val[0]
rl val[1]
rl val[2]
rl val[3]
rl val_m
movlw 11110110b
addwf val_m,0
btfsc c
mov val_m,w
btfsc c
inc val[0]
djnz cnd,devide0
dec fsr
mov indirect,val_m ; 余り
ret
;-----------------------------------
mul_xy
mov zz[0],xx[0]
mov zz[1],xx[1]
clr zz[2]
clr zz[3]
mov cn1,#16
mul_xy0
btfss zz[0].0
goto mul_xy9
bcf zz[0].0
add zz[2],yy[0]
movlw 1
btfsc c
addwf zz[3],1
btfsc c
addwf zz[0],1
add zz[3],yy[1]
movlw 1
btfsc c
addwf zz[0],1
mul_xy9:
movb c,zz[0].0
rr zz[3]
rr zz[2]
rr zz[1]
rr zz[0]
djnz cn1,mul_xy0
ret
;------td63 dataclock make--------------------------------------
td63_clkout
call time3
bsf td63_clk
call time3
bcf td63_clk
call time3
ret
;---------------------------rotary sw wait timer -----304usec -------
rsw_wait ;
;about 304usec
mov cnt1,#6ch ;call:2+mov 2=4
t_lp1
nop ;
nop
nop
nop ;1X4=4
decfsz cnt1,1 ;2
goto t_lp1 ;2
ret ;2
;call で入る1回目 (11)
;loop のクロック (7)
;return のクロック 8
; 9+(7X106)+8=761
;0.4usecx 761=304.4
time3 ;------ 3.2usec------
NOP ;call 2
NOP ;nop 4
NOP ;ret 2
NOP
ret ;8x0.4usec=3.2usec
time10
mov cnt2,#05h ;1
;1
t_lp2
decfsz cnt2,1 ;1 (2)
jmp t_lp2
nop
nop
nop
nop
nop ;1
ret ;2 7+(3x3)+9=21 25x0.4usec=10.0
;
;------msオーダーのウェイト --------------------------------
wait_ms
wait_ms0
mov wait_cn2,#0
wait_ms1
nop
nop
nop
nop
nop
nop
nop
djnz wait_cn2,wait_ms1
djnz wait_cn,wait_ms0
ret
;-------μsオーダーのウェイト-------------------------------
;
wait_us
wait_us0
djnz wait_cn,wait_us0
ret
wait_sec ;---秒単位の時間ルーチン----------------------
mov wait_cn,#250
call wait_ms
mov wait_cn,#250
call wait_ms
djnz wait_s,wait_sec
ret
nop
retw '99-10-01 PLL50A 50k';ここがpicの最後に書かれるライタで読んだ時にバージョン確認の為
retw 'LCD JA0ESA masa/suu'
nop
nop
end |
|