$prog &HFF , &HF7 , &HD9 , &HFE 'CKDIV8 = 1 , SUT = 11 , CKSEL = 0111 , BODLEVEL = 1.8V ' ' *************************************** ' * GPS AE-GYSFDMAXB , GT-502MGG-N * ' * 高精度1Hz出力 (周波数カウンター版) * ' * Basic Compiler is BASCOM-AVR * ' * Copyright O-Family 2016. 6. 6 * ' *************************************** ' ' Ver. F0.21 初回公開バージョン。2016. 6. 6 ' Ver. F0.22 GT-502MGG-Nに対応。2023.10.17 ' ' Const Prgver = "F0.22" 'プログラム・バージョン。 $regfile = "m328pdef.dat" '使用するAVRを設定。 $crystal = 20000000 'AVRクロックを設定。 ' $hwstack = 64 'ハードウェア・スタックの容量を設定。 $swstack = 32 'ソフトウェア・スタックの容量を設定。 $framesize = 24 'フレーム領域の容量を設定。 ' ' * ポート名の定義 * ' Sw_1 Alias Pinc.0 'スイッチ[1]の接続ポート。 Sw_2 Alias Pinc.1 'スイッチ[2]の接続ポート。 Sw_3 Alias Pinc.2 'スイッチ[3]の接続ポート。 ' ' * 変数の宣言 * ' Dim Capmode As Byte 'キャプチャー割り込みの動作モード。 Dim Capendf As Byte 'キャプチャー計測完了フラグ。 Dim Capdat1 As Word 'キャプチャー・レジスター値 バッファー1。 Dim Capovf1 As Word 'オーバーフロー・カウント値 バッファー1。 Dim Capdat2 As Word 'キャプチャー・レジスター値 バッファー2。 Dim Capovf2 As Word 'オーバーフロー・カウント値 バッファー2。 Dim Capovfc As Word 'オーバーフロー・カウンター。 Dim Freqdata As Long 'キャプチャー・データを差分計算したカウント値。 ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Temp3 As Byte '汎用テンポラリ変数 Byte型 No.3 Dim Temp4 As Byte '汎用テンポラリ変数 Byte型 No.4 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Templ2 As Long '汎用テンポラリ変数 Long型 No.2 Dim Tempstr As String * 20 '汎用テンポラリ変数 String型 No.1 Dim Tempstr2 As String * 20 '汎用テンポラリ変数 String型 No.2 ' ' * ポートの初期設定 * ' Set Portc.0 'スイッチ[1]の接続ポートをプルアップする。 Set Portc.1 'スイッチ[2]の接続ポートをプルアップする。 Set Portc.2 'スイッチ[3]の接続ポートをプルアップする。 ' Set Portc.3 '未使用ポートをプルアップする。 Set Portc.4 '未使用ポートをプルアップする。 Set Portc.5 '未使用ポートをプルアップする。 Set Portd.2 '未使用ポートをプルアップする。 Set Portd.3 '未使用ポートをプルアップする。 Set Portd.4 '未使用ポートをプルアップする。 ' ' * LCDの初期設定 * ' Config Lcdmode = Port 'LCDを4ビットのポートモードに設定。 Config Lcdbus = 4 'LCDデータバスを4bitに設定。 Config Lcdpin = Pin , Db4 = Portb.2 , Db5 = Portb.1 'LCDのポート割り当て。 Config Lcdpin = Pin , Db6 = Portb.4 , Db7 = Portb.5 Config Lcdpin = Pin , E = Portb.3 , Rs = Portd.7 Config Lcd = 16 * 2 'LCD表示を16文字2行に設定。 Cls 'LCD表示をすべて消去。 ' ' * LCDへ起動メッセージを表示 * ' Cursor Off 'LCDのカーソルをオフにする。 Locate 1 , 1 'LCDにタイトルを表示する。 Lcd "GPS Freq Counter" Locate 2 , 5 'LCDにプログラム・バージョンを表示する。 Lcd "Ver. " ; Prgver Wait 2 '表示の待ち時間。 Cls 'LCD表示をすべて消去。 ' ' * 完全コールドスタート(工場出荷時のデフォルト状態) * ' If Sw_3 = 0 Then 'If [SW3]が押されているか? Then Print "$PMTK104*37" '完全コールドスタート(工場出荷時のデフォルト状態)コマンドを送信する。 Locate 1 , 1 Lcd "Full ColdRestart" Locate 2 , 1 Lcd " System Defaults" Bitwait Sw_3 , Set '[SW3]が離されるまで待つ。 Waitms 30 'チャタリング・タイマー。 Cls 'LCD表示をすべて消去。 End If ' ' * Timerの設定 * ' Config Timer0 = Timer , Prescale = 1 , Clear Timer = 1 , Compare A = Toggle 'Timer0の設定。 Compare0a = 10 - 1 '20,000,000Hz / 10カウント * 2 = 1,000,000Hz ' Config Timer1 = Counter , Edge = Falling , Capture Edge = Falling '[T1]の立ち下がりエッジでカウント。 On Capture1 Tintcap Nosave 'キャプチャー割り込みルーチンのラベルを設定。 Enable Capture1 'キャプチャー割り込みを許可する。 On Timer1 Tintovf Nosave 'オーバーフロー割り込みルーチンのラベルを設定。 Enable Timer1 'TIMER1オーバーフロー割り込みを許可する。 ' ' ************************** ' * 周波数カウンターモード * ' ************************** ' Freqinit: Enable Interrupts 'すべての割り込みを許可。 Cls 'LCD表示をすべて消去。 Capendf = 0 'キャプチャー計測完了フラグをクリア。 ' ' ************************************** ' * 周波数カウンター用 メイン ルーチン * ' ************************************** ' Freqmain: Gosub Freqcal 'カウント値の計算処理。 Goto Freqmain '------------------------------------------------------------ ' ' ************************************ ' * カウント値の計算処理サブルーチン * ' ************************************ ' Freqcal: If Capendf = 0 Then Return 'If キャプチャー計測が完了したか? Else ' Gosub Capsubt 'キャプチャー・バッファーの値を差分計算する。=> (Freqdata) ' ' * LCDへ周波数を表示する * ' Tempstr = Str(freqdata) '計測値を文字列に変換。 Temp1 = Len(tempstr) '計測値の桁数を調べる。 Locate 1 , 3 Lcd " " ; Select Case Temp1 '周波数により表示桁を整える。 Case 8 : Lcd Format(tempstr , " . ") ; " MHz" '10MHz以上。 Case 7 : Lcd Format(tempstr , " . ") ; " MHz" '1〜9MHz。 Case Is > 3 : Lcd Spc(2) ; Format(tempstr , " . ") ; " KHz" '1〜999KHz。 Case Else : Lcd Spc(6) ; Format(tempstr , " ") ; " Hz " '1〜999Hz。 End Select ' ' * LCDへ周期を表示 * ' Templ1 = 1000000000 / Freqdata '計測値を周期に変換。 Tempstr = Str(templ1) '周期値を文字列に変換。 Temp1 = Len(tempstr) '周期値の桁数を調べる。 Locate 2 , 4 Select Case Temp1 '周期値により表示桁を整える。 Case 10 : Tempstr = Left(tempstr , 8) Lcd Format(tempstr , " . ") ; " S " '1S以上。 Case 9 : Tempstr = Left(tempstr , 8) '100〜999mS。 Lcd Format(tempstr , " . ") ; " mS " Case Is >= 7 : Lcd Format(tempstr , " . ") ; " mS " '1〜99mS。 Case Is >= 4 : Lcd Spc(2) ; Format(tempstr , " . ") ; " uS " '1〜999uS。 Case Else : Lcd Spc(6) ; Format(tempstr , " ") ; " nS " '1〜999nS。 End Select ' Freqcal2: Capendf = 0 'キャプチャー計測完了フラグをクリア。 Return '------------------------------------------------------------ ' ' ********************************************************** ' * キャプチャー・バッファーの値を差分計算するサブルーチン * 差分カウント値 => Freqdata(ロング型) ' ********************************************************** ' Capsubt: $asm LDS R24,{Capendf} 'キャプチャー・バッファーの使用状況を調べる。 SBRC R24,0 'バッファー1が測定終了データか? Then RJMP Capsubt1 ; LDS R16,{capdat1} '32bit引き算(バッファー2)−(バッファー1)。 LDS R17,{capdat1+1} LDS R18,{capovf1} LDS R19,{capovf1+1} LDS R20,{capdat2} LDS R21,{capdat2+1} LDS R22,{capovf2} LDS R23,{capovf2+1} RJMP Capsubt2 ; Capsubt1: LDS R16,{capdat2} '32bit引き算(バッファー1)−(バッファー2)。 LDS R17,{capdat2+1} LDS R18,{capovf2} LDS R19,{capovf2+1} LDS R20,{capdat1} LDS R21,{capdat1+1} LDS R22,{capovf1} LDS R23,{capovf1+1} ; Capsubt2: Sub R20 , R16 '32bit引き算。 SBC R21,R17 SBC R22,R18 SBC R23,R19 STS {Freqdata},R20 '計算結果をロング型変数に格納。 STS {Freqdata+1},R21 STS {Freqdata+2},R22 STS {Freqdata+3},R23 $end Asm Return ' ' ******************************************** ' * Timer1 キャプチャー 割り込み処理ルーチン * ' ******************************************** ' Tintcap: $asm PUSH R1 IN R1,SREG 'ステータス・レジスタを待避。 PUSH R22 PUSH R23 'R23は、拡張I/Oレジスタへのアクセスに使用する。 PUSH R24 PUSH R25 ; LDS R22,{Capendf} 'メインルーチンの処理状態をチェック。 CPI R22,0 BREQ Tintcap1 'If メインルーチンでキャプチャー・データの処理が終了しているか? Else JMP Tintcap8 ; Tintcap1: IN R24,ICR1L 'キャプチャー・レジスターの下位バイトを取得。 IN R23,ICR1H 'キャプチャー・レジスターの上位バイトを取得。 ; LDS R22,{Capmode} 'キャプチャー割り込みのモードを調べる。 SBRC R22,0 'If データ・バッファー2 へ書き込み? Then RJMP Tintcap2 ; ; '---<データ・バッファー1 書き込み処理>--- STS {Capdat1},R24 'データ・バッファー1へ保存。 STS {Capdat1+1},R23 ; LDS R24,{Capovfc} 'オーバーフロー・カウント値を取得。 LDS R25,{Capovfc+1} CPI R23,0 BRNE Tintcap3 'If キャプチャー・データの上位バイトが00? Else ; IN R23,TIFR1 SBRS R23,TOV1 'オーバーフローが発生しているか? Else RJMP Tintcap3 ; ADIW R24,1 'オーバーフロー・カウント値を+1 ; Tintcap3: STS {Capovf1},R24 'データ・バッファー1へ保存。 STS {Capovf1+1},R25 ORI R22,&H01 'モードをデータ・バッファー2 書き込みに変更。 RJMP Tintcap5 ; ; Tintcap2: '---<データ・バッファー2 書き込み処理>--- STS {Capdat2},R24 'データ・バッファー2へ保存。 STS {Capdat2+1},R23 ; LDS R24,{Capovfc} 'オーバーフロー・カウント値を取得。 LDS R25,{Capovfc+1} CPI R23,0 BRNE Tintcap4 'If キャプチャー・データの上位バイトが00? Else ; IN R23,TIFR1 SBRS R23,TOV1 'オーバーフローが発生しているか? Else RJMP Tintcap4 ; ADIW R24,1 'オーバーフロー・カウント値を+1 ; Tintcap4: STS {Capovf2},R24 'データ・バッファー2へ保存。 STS {Capovf2+1},R25 ANDI R22,&HF0 'モードをデータ・バッファー1 書き込みに変更。 ; ; Tintcap5: CPI R22,&H10 BRCC Tintcap6 'If 1と2の両バッファーにデータの準備が完了か? Then ORI R22,&H10 'キャプチャー・モードを2つめのデータ待ちにセット。 RJMP Tintcap7 ; Tintcap6: STS {Capendf},R22 'キャプチャー計測完了フラグをセット。 Tintcap7: STS {Capmode},R22 'キャプチャー・モードを更新。 ; POP R25 POP R24 POP R23 POP R22 Out Sreg , R1 'ステータス・レジスタを復帰 POP R1 $end Asm Return ' ' $asm Tintcap8: 'メインルーチンでキャプチャー・データの処理が終わっていない。 LDI R22,0 'キャプチャー・モードを初期化する。 RJMP Tintcap7 $end Asm ' ' ********************************************** ' * Timer1 オーバーフロー 割り込み処理ルーチン * ' ********************************************** ' Tintovf: $asm PUSH R1 IN R1,SREG 'ステータス・レジスタを待避。 PUSH R24 PUSH R25 ; LDS R24,{Capovfc} 'オーバーフロー・カウント値を+1。 LDS R25,{Capovfc+1} ADIW R24,1 STS {Capovfc},R24 STS {Capovfc+1},R25 ; POP R25 POP R24 Out Sreg , R1 'ステータス・レジスタを復帰 POP R1 $end Asm Return End