' ' *********************************************** ' * * ' * ATmega88P RTC化 時計 + 温度計 プログラム * ' * * ' * AVR is using ATmega88P * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2009.12.30 * ' *********************************************** ' ' Ver 1.01 初回公開バージョン ' Ver 1.02 BASCOMの"m88pdef.dat"修正に伴いレジファイル名を修正。 ' ' Const Prgverh = 01 'プログラム・バージョン。(上位桁) Const Prgverl = 02 'プログラム・バージョン。(下位桁) ' ' $regfile = "m88pdef.dat" '使用するAVRを設定。 $crystal = 1000000 'AVRクロックを設定。 ' $hwstack = 64 'ハードウェア・スタックの容量を設定。 $swstack = 8 'ソフトウェア・スタックの容量を設定。 $framesize = 24 'フレーム領域の容量を設定。 ' ' * 変数の宣言 * ' Dim Dispmode As Byte '表示モード。 Dim Modetemp As Byte '表示モードの保管用。 Dim Mf1224h As Byte '時間表示モード 0=12時間制 / 1=24時間制 Dim Tempsec As Byte '[秒]更新用テンポラリ。 Dim Dpblken As Byte 'D.P点滅許可フラグ。 Dim Tim500ms As Byte '500mSタイマー。 Dim Brightchf As Byte 'LEDの表示輝度変更フラグ。 Dim Keycun As Byte 'キー入力チェック用タイマーカウンター。 Dim Keyflg As Byte 'キー入力検出フラグ。 Dim Keydata As Byte 'キー入力データ。 Dim Keytemp As Byte 'キー入力用テンポラリ。 Dim Refadj As Byte 'AVR 1.1V基準電圧の校正値。(0〜20→1.00〜1.20V) ' Dim Leddata1 As Byte 'LED[1] DMA表示用データ。 Dim Leddata2 As Byte 'LED[2] DMA表示用データ。 Dim Leddata3 As Byte 'LED[3] DMA表示用データ。 Dim Leddata4 As Byte 'LED[4] DMA表示用データ。 Dim Dmano As Byte 'DMAの表示番号。 ' 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 Temp5 As Byte '汎用テンポラリ変数 Byte型 No.5 Dim Temp6 As Byte '汎用テンポラリ変数 Byte型 No.6 Dim Tempsb1 As Byte '汎用変数サブルーチン用 Byte型 No.1 Dim Tempsb2 As Byte '汎用変数サブルーチン用 Byte型 No.2 Dim Tempsb3 As Byte '汎用変数サブルーチン用 Byte型 No.3 Dim Tempsb4 As Byte '汎用変数サブルーチン用 Byte型 No.4 Dim Tempw1 As Word '汎用テンポラリ変数 Word型 No.1 Dim Tempw2 As Word '汎用テンポラリ変数 Word型 No.2 Dim Tempi1 As Integer '汎用テンポラリ変数 Integer型 No.1 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 ' Dim Eep1224h As Eram Byte At $10 'EEPROM 時間表示モード 0=12時間制 / 1=24時間制。 Dim Eeprefadj As Eram Byte At $11 'EEPROM AVR 1.1V基準電圧の校正値。 ' ' * ポート名の定義 * ' Led_seg Alias Portd 'LEDのセグメントを接続するポート。 Led_com1 Alias Portb.1 'LED[1]のコモン端子を接続するポート。 Led_com2 Alias Portb.2 'LED[2]のコモン端子を接続するポート。 Led_com3 Alias Portb.0 'LED[3]のコモン端子を接続するポート。 Led_com4 Alias Portb.3 'LED[4]のコモン端子を接続するポート。 Sw_1 Alias Pinc.5 'スイッチ[1]の接続ポート。 Sw_2 Alias Pinc.4 'スイッチ[2]の接続ポート。 Sw_3 Alias Pinb.4 'スイッチ[3]の接続ポート。 Sw_4 Alias Pinb.5 'スイッチ[4]の接続ポート。 Sw_1pu Alias Portc.5 'スイッチ[1]の接続ポート(プルアップ用)。 Sw_2pu Alias Portc.4 'スイッチ[2]の接続ポート(プルアップ用)。 Sw_3pu Alias Portb.4 'スイッチ[3]の接続ポート(プルアップ用)。 Sw_4pu Alias Portb.5 'スイッチ[4]の接続ポート(プルアップ用)。 Pt_power Alias Pinc.0 '電源電圧監視用のポート。 Ad_power Alias 0 '電源電圧監視用A/Dコンバータのチャネル番号。 Ad_vs Alias Portc.2 'センサー用の電源ポート。 Ad_temp Alias 3 '温度センサーを接続するA/Dコンバータのチャネル番号。 Ad_cds Alias 1 'CDSセンサーを接続するA/Dコンバータのチャネル番号。 ' ' * ポートの初期設定 * ' Gosub Portinit 'ポートの初期設定を行う。 ' ' * Timer + ADC の設定 * ' Config Timer0 = Pwm , Prescale = 8 , Clear Timer = 1 'LEDのDMA用 1,000,000Hz / 8 = 125,000Hz Set Tccr0b.wgm02 '高速PWMモード。 (TOP = OCR0A) Ocr0a = 250 - 1 'スキャン周波数。(125,000Hz ÷ 250カウント = 500Hz) Ocr0b = 25 'パルス幅 (明25〜暗225) (初期値 25) 1カウントは8μS。 On Oc0a Tint0a 'TIMER0比較一致A割り込みルーチンのラベルを設定。 Enable Oc0a 'TIMER0比較一致A割り込みを許可。 On Oc0b Tint0b 'TIMER0比較一致B割り込みルーチンのラベルを設定。 Enable Oc0b 'TIMER0比較一致B割り込みを許可。 ' Config Timer1 = Timer , Prescale = 1 , Clear Timer = 1 '10mSタイマー Compare1a = 10000 - 1 '1,000,000Hz / 10000 = 100Hz (10mS) ' Config Adc = Single , Prescaler = Auto , Reference = Avcc 'A/Dコンバータの設定。 Start Adc 'A/Dコンバータに電源を供給。 ' ' * 時計用のライブラリを組み込む * ' Config Clock = Soft '時計(Timer2を使用)をSoftモードに設定。 Config Date = Ymd , Separator = / '日付の表現方法(形式)を設定。 ' ' * EEPROMのデータを確認する * ' If Eep1224h > 1 Then Eep1224h = 1 'If EEPROMが初期値か? Then Mf1224h = Eep1224h '時間表示モード 0=12時間制 / 1=24時間制 If Eeprefadj > 20 Then Eeprefadj = 10 'If EEPROMが初期値か? Then Refadj = Eeprefadj 'AVR 1.1V基準電圧の校正値。(0〜20→1.00〜1.20V) ' ' * ポートと変数の初期設定 * ' Dmano = 1 'LEDのDMA表示番号の初期値。 Dispmode = 1 '表示モードの初期値。 Tempsec = 255 '1秒更新テンポラリの初期化。 ' Enable Interrupts 'すべての割り込みを許可。 ' ' * プログラム・バージョンを表示 * ' Prgvds: Temp1 = Prgverh 'プログラム・バージョンの上位を表示。 Temp2 = 1 'LEDの上位桁を指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Reset Leddata3.7 '3桁目に小数点を表示。 ' Temp1 = Prgverl 'プログラム・バージョンの下位を表示。 Temp2 = 0 'LEDの下位桁を指定。 Temp3 = 0 '設定値の下限。 Temp4 = 99 '設定値の上限。 Gosub Tmskey '時刻設定用のキー入力処理。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: Gosub Expower '外部電源の電圧を監視する。(スリープモードに移行する) Gosub Every10ms '10mSごとの処理を行う。(キーチェック) Gosub Ledbright 'LEDの輝度を調整する。 Gosub Dispren1s '1秒ごとに表示を更新する。 Gosub Keycont 'キー入力により表示を切り換える。 Goto Main ' ' ************************************ ' * 外部電源の電圧を監視するルーチン * ' ************************************ ' Expower: Tempw1 = Getadc(ad_power) '外部電源の電圧値をA/D変換する。 If Tempw1 > 920 Then Return 'If 外部電源の電圧が4.5V以上あるか? Then ' ' * スリープモードへ移行する * ' Stop Adc 'A/Dコンバータの電源を切る。 Stop Timer0 'タイマー0を停止させる。 Stop Timer1 'タイマー1を停止させる。 ' Config Portb = Input 'PORTBをすべて入力に設定する。 Config Portc = Input 'PORTCをすべて入力に設定する。 Config Portd = Input 'PORTDをすべて入力に設定する。 Portb = 0 'PORTBのプルアップをすべて解除する。 Portc = 0 'PORTCのプルアップをすべて解除する。 Portd = 0 'PORTDのプルアップをすべて解除する。 Didr0 = &B00001110 'デジタル入力禁止レジスタの設定。 ' Slploop: Powersave 'スリープモードへ移行する。(1秒割り込みで再起動する) If Pt_power = 0 Then Goto Slploop 'If 外部電源が切れているか? Then ' ' * 外部電源が復旧後、通常動作へ移行する * ' Gosub Portinit 'ポートの初期設定を行う。 Start Adc 'A/Dコンバータに電源を供給。 Start Timer0 'タイマー0を再始動させる。 Start Timer1 'タイマー1を再始動させる。 Waitms 5 'A/Dの基準電圧が安定するまでの待ち時間。 Return ' ' -------------------------------------- ' * ポートの初期設定を行うサブルーチン * ' -------------------------------------- ' Portinit: Config Led_seg = Output 'LEDのセグメント接続ポートを出力に設定。 Config Led_com1 = Output 'LED[1]のコモン端子接続ポートを出力に設定。 Config Led_com2 = Output 'LED[2]のコモン端子接続ポートを出力に設定。 Config Led_com3 = Output 'LED[3]のコモン端子接続ポートを出力に設定。 Config Led_com4 = Output 'LED[4]のコモン端子接続ポートを出力に設定。 Didr0 = &B00001111 'デジタル入力禁止レジスタの設定。 Config Ad_vs = Output 'センサー用の電源ポートを出力に設定。 Set Ad_vs 'センサーに電源を供給する。 Set Sw_1pu 'スイッチ[1]の接続ポートをプルアップ。 Set Sw_2pu 'スイッチ[2]の接続ポートをプルアップ。 Set Sw_3pu 'スイッチ[3]の接続ポートをプルアップ。 Set Sw_4pu 'スイッチ[4]の接続ポートをプルアップ。 Return ' ' ************************************************ ' * 10mSごとに処理を行うルーチン (キーチェック)* ' ************************************************ ' Every10ms: If Tifr1.ocf1a = 0 Then Return 'If 10mS経過したか? Else Set Tifr1.ocf1a 'Timer1 比較A一致フラグをリセット。 ' Tim500ms = Tim500ms + 1 '500mSタイマーを加算。 Select Case Tim500ms Case 50 : '[D.P]点灯から500mS経過した。 If Dpblken = 1 Then 'If [D.P]の点滅が許可されているか? Then Set Leddata3.7 '3桁目の小数点を消灯。 End If Case 25 : '500mSごとにLEDの輝度を調整する。 Brightchf = 1 Case 75 : '500mSごとにLEDの輝度を調整する。 Brightchf = 1 End Select ' ' * キー入力を確認する * (Keyflg = キー入力が有ると1) , (Keydata = キーデータ) ' Keychk: If Keycun = 0 Then Goto Keychk1 'If キー入力チェック開始か? Then If Keycun < 3 Then Goto Keychk5 'If チャタリング チェック期間か? Then If Keycun = 3 Then Goto Keychk3 'If キー入力再確認か? Then ' Gosub Keyport 'キーオフを確認する。 If Keydata <> Keytemp Then Goto Keychk4 'If キーオフか? Then If Keycun < 103 Then Goto Keychk5 'If リピート期間待ち(1Sec)か? Then Keyflg = 1 Keycun = 92 'リピートを開始。 Return ' ' Keychk1: 'キー入力チェック開始。 Gosub Keyport 'キー接続ポートからデータを入力。 If Keydata <> 0 Then Goto Keychk2 'If キー入力有りか? Then Keychk4: Keycun = 0 Return ' Keychk2: 'キー入力有り。 Keytemp = Keydata 'キー・データを一時保存。 Keychk5: Keycun = Keycun + 1 Return ' Keychk3: 'キー入力再確認。 Gosub Keyport 'キー接続ポートからデータを入力。 If Keydata <> Keytemp Then Goto Keychk4 'If キー入力エラーか? Then Keyflg = 1 Goto Keychk5 ' ' -------------------------------------------------- ' * キー接続ポートからデータを入力するサブルーチン * (Keydat = キー・データ) ' -------------------------------------------------- ' Keyport: Keydata = 0 If Sw_1 = 0 Then Set Keydata.0 'If [SW1]が押されているか? Then If Sw_2 = 0 Then Set Keydata.1 'If [SW2]が押されているか? Then If Sw_3 = 0 Then Set Keydata.2 'If [SW3]が押されているか? Then If Sw_4 = 0 Then Set Keydata.3 'If [SW4]が押されているか? Then Return ' ' ******************************* ' * LEDの輝度を調整するルーチン * ' ******************************* ' Ledbright: If Brightchf = 0 Then Return 'If 500mS経過したか? Else Brightchf = 0 ' Tempw1 = Getadc(ad_cds , &H20) 'CDSセンサーをA/D変換する(8bit)。 Reset Admux.adlar 'A/Dデータの左揃えを解除する。 Temp1 = High(tempw1) '輝度の実測値 (暗25〜明250) ' Temp1 = Not Temp1 '輝度傾斜を反転する。 If Temp1 > 225 Then Temp1 = 225 'If パルス幅の上限を超えたか? Then If Temp1 < 25 Then Temp1 = 25 'If パルス幅の下限を超えたか? Then Ocr0b = Temp1 'パルス幅を変更する。 Return ' ' **************************************** ' * 1秒ごとにLEDの表示を更新するルーチン * ' **************************************** ' Dispren1s: If Tempsec = _sec Then Return 'If [秒]が更新されたか? Else Tempsec = _sec Tim500ms = 0 '500mSタイマーを初期化。 ' ' * LEDに情報を表示する * ' Displed: On Dispmode Goto Dlmode0 , Dlmode1 , Dlmode2 , Dlmode3 , Dlmode4 , Dlmode5 , Dlmode6 ' ' * MODE(0) 表示オフ * ' Dlmode0: Gosub Ledoffl 'LEDの下位2桁を消灯する。 Gosub Ledoffu 'LEDの上位2桁を消灯する。 Goto Dlmode11 ' ' * MODE(1) [時・分]を表示 * ' Dlmode1: Temp1 = _min '[分]を表示。 Temp2 = 0 'LEDの下位桁を指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Temp1 = _hour '[時]を表示。 Temp2 = 3 'LEDの上位桁をゼロサプレスで指定。 Gosub Hourcvwr '時間を12/24時間制で識別して表示。 ' Dlmode11: If Tim500ms < 50 Then 'If [D.P]点灯期間か? Then Reset Leddata3.7 '3桁目に小数点を表示。 End If Dpblken = 1 '[D.P]の点滅を許可する。 Return ' ' * MODE(2) [分・秒]を表示 * ' Dlmode2: Temp1 = _sec '[秒]を表示。 Temp2 = 0 'LEDの下位桁を指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Temp1 = _min '[分]を表示。 Temp2 = 1 'LEDの上位桁を指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Goto Dlmode11 ' ' * MODE(3) [月・日]を表示 * ' Dlmode3: Temp1 = _day '[日]を表示。 Temp2 = 2 'LEDの下位桁をゼロサプレスで指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Temp1 = _month '[月]を表示。 Temp2 = 3 'LEDの上位桁をゼロサプレスで指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Dpblken = 0 '[D.P]の点滅を禁止する。 Return ' ' * MODE(4) 8秒間[時・分]、2秒間[[月・日]を表示 * ' Dlmode4: Temp1 = _sec Gosub Binseg 'バイナリ値をBCD値に変換する。 If Tempsb3 < 8 Then Goto Dlmode1 'If [秒]の下位が0-7? Then Goto Dlmode3 '[秒]の下位が8-9の場合。 ' ' * MODE(5) [温度]を表示 * ' Dlmode5: Gosub Thermo '温度を表示する。 Dpblken = 0 '[D.P]の点滅を禁止する。 Return ' ' * MODE(6) 8秒間[時・分]、2秒間[[温度]を表示 * ' Dlmode6: Temp1 = _sec Gosub Binseg 'バイナリ値をBCD値に変換する。 If Tempsb3 < 8 Then Goto Dlmode1 'If [秒]の下位が0-7? Then Goto Dlmode5 '[秒]の下位が8-9の場合。 ' ' ------------------------------ ' * 温度を表示するサブルーチン * ' ------------------------------- ' Thermo: Config Adc = Single , Prescaler = Auto , Reference = Internal_1.1 'A/Dコンバータの基準電圧を変更。(内部1.1V) Waitms 5 'A/Dの基準電圧が安定するまでの待ち時間。 ' Disable Interrupts 'すべての割り込みを禁止。 Set Led_com1 'A/D変換器のノイズ防止のため、LEDを全て消灯する。 Set Led_com2 Set Led_com3 Set Led_com4 Led_seg = &B11111111 Waitus 100 '電源ラインが安定するまで待つ。 Tempw1 = Getadc(ad_temp) '温度センサー値をA/D変換。 Enable Interrupts 'すべての割り込みを許可。 ' Config Adc = Single , Prescaler = Auto , Reference = Avcc 'A/Dコンバータの基準電圧を戻す。(AVCC) ' Temp1 = Refadj + 100 'AVR 1.1V基準電圧の校正値を計算。 Tempw2 = Temp1 * 10 '小数点を省くため校正値を1000倍しておく。(1.1V*1000=1100) Templ1 = Tempw2 * Tempw1 '1.1V ÷ 1024 × 1000000 × [A/D値] ÷ 1000 Shift Templ1 , Right , 10 , Signed '式を変えて 1.1V × 1000 × [A/D値] ÷ 1024(割り算を使わない) Tempi1 = Templ1 Tempi1 = Tempi1 - 600 '温度センサーIC [LM61]の温度変換計算。 ' If Tempi1 >= 0 Then 'If プラスの温度か? Then Gosub Partbcd 'BCD値を[100の位]と[10と1の位]に分ける。 Leddata2 = Tempsb1 '[X.X]の桁を表示する。 Leddata3 = Tempsb2 ' Temp1 = Tempw1 '[X0.0]の桁を表示する。 If Temp1 <> 0 Then 'If 10℃以上か? Then Gosub Binseg 'バイナリ値を2桁のセグメントコードに変換する。 Leddata4 = Tempsb1 Else Leddata4 = &B11111111 '消灯。(ゼロサプレス) End If Reset Leddata3.7 '3桁目に小数点を表示。 ' Else 'マイナスの範囲。 Leddata4 = &B10111111 '[-]を表示する。 Tempi1 = Abs(tempi1) '絶対値を求める。 Gosub Partbcd 'BCD値を[100の位]と[10と1の位]に分ける。 Temp1 = Tempw1 If Temp1 <> 0 Then 'If -10℃以下か? Then Leddata2 = Tempsb2 '[-10〜-99]で表示する。 Gosub Binseg 'バイナリ値を2桁のセグメントコードに変換する。 Leddata3 = Tempsb1 Else Leddata2 = Tempsb1 '[-X.X]で表示する。 Leddata3 = Tempsb2 Reset Leddata3.7 '3桁目に小数点を表示。 End If End If Leddata1 = &B10100111 '1桁目に[c]を表示する。 ' Waitms 1 'A/Dの基準電圧が安定するまでの待ち時間。 Return ' ' * BCD値を[100の位]と[10と1の位]に分けるサブルーチン * ' Partbcd: Tempw1 = Tempi1 / 100 '100の位を抽出する。(Tempw1) Tempw2 = Tempw1 * 100 '10と1の位を抽出する。(Tempw2) Tempw2 = Tempi1 - Tempw2 Temp1 = Tempw2 Gosub Binseg '10と1の位を2桁のセグメントコードに変換する。 Return ' ' ****************************************** ' * キー入力により表示を切り換えるルーチン * ' ****************************************** ' Keycont: If Keyflg = 0 Then Return 'If キー入力が有ったか? Else Keyflg = 0 ' Select Case Keydata Case &B00000001 : '[SW1]が押された場合。 If Dispmode = 0 Then 'If 表示モードが(0)か? Then Dispmode = Modetemp '消灯以前の状態に戻す。 Else Modetemp = Dispmode '表示を消灯する。 Dispmode = 0 End If Case &B00000010 : '[SW2]が押された場合。 If Dispmode = 1 Then 'If 表示モードが(1)か? Then Dispmode = 2 '[分・秒]表示にする。 Else Dispmode = 1 '[時・分]表示にする。 End If Case &B00000100 : '[SW3]が押された場合。 If Dispmode = 3 Then 'If 表示モードが(3)か? Then Dispmode = 4 '8秒間[時・分]、2秒間[[月・日]表示にする。 Else Dispmode = 3 '[月・日]表示にする。 End If Case &B00001000 : '[SW4]が押された場合。 If Dispmode = 5 Then 'If 表示モードが(5)か? Then Dispmode = 6 '8秒間[時・分]、2秒間[[温度]表示にする。 Else Dispmode = 5 '[温度]表示にする。 End If Case &B00000110 : '[SW2+SW3]が押された場合。 Toggle Mf1224h.0 '時間表示モードを変更。 Eep1224h = Mf1224h 'EEPROMに保存。 Dispmode = 1 '[時・分]表示にする。 ' Case &B00001010 : '[SW2+SW4]が押された場合。 Goto Timset '時刻設定処理。 ' Case &B00001001 : '[SW1+SW4]が押された場合。 Goto Refset 'AVR 1.1V基準電圧の校正処理。 End Select Keycont1: Gosub Displed 'LEDに情報を表示する。 Return ' ' * 時刻設定 処理ルーチン * ' Timset: Disable Timer2 '1秒割り込みを禁止。 ' Temp1 = 20 '時刻設定モードに入ったことを表示する。 Temp2 = 1 'LEDの上位桁を指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Gosub Ledoffl 'LEDの下位2桁を消灯する。 Gosub Keyoff 'キーが離されるまで待つ。 ' Temp1 = _year '[年]の設定。 Temp2 = 0 'LEDの下位桁を指定。 Temp3 = 0 '設定値の下限。 Temp4 = 99 '設定値の上限。 Gosub Tmskey '時刻設定用のキー入力処理。 _year = Temp1 ' Temp1 = _day '[月]の設定。 Temp2 = 2 'LEDの下位桁をゼロサプレスで指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Temp1 = _month Temp2 = 3 'LEDの上位桁をゼロサプレスで指定。 Temp3 = 1 '設定値の下限。 Temp4 = 12 '設定値の上限。 Gosub Tmskey '時刻設定用のキー入力処理。 _month = Temp1 ' Temp1 = _month '[日]の設定。 Temp2 = 3 'LEDの上位桁をゼロサプレスで指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Temp1 = _day Temp2 = 2 'LEDの下位桁をゼロサプレスで指定。 Temp4 = Lookup(_month , Monthtab) '月による設定値の上限を取得する。 If _month = 2 Then 'If 2月か? Then Temp3 = _year And &H03 '閏年の確認。 If Temp3 = 0 Then 'If 閏年か? Then Temp4 = 29 End If End If Temp3 = 1 '設定値の下限。 Gosub Tmskey '時刻設定用のキー入力処理。 _day = Temp1 ' Temp1 = _min '[時]の設定。 Temp2 = 0 'LEDの下位桁を指定。 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Temp1 = _hour Temp2 = &H83 'LEDの上位桁をゼロサプレスで指定。 Temp3 = 0 '設定値の下限。 Temp4 = 23 '設定値の上限。 Gosub Tmskey '時刻設定用のキー入力処理。 _hour = Temp1 ' Temp1 = _hour '[分]の設定。 Temp2 = 3 'LEDの上位桁をゼロサプレスで指定。 Gosub Hourcvwr '時間を12/24時間制で識別して表示。 Temp1 = _min Temp2 = 0 'LEDの下位桁を指定。 Temp3 = 0 '設定値の下限。 Temp4 = 59 '設定値の上限。 Gosub Tmskey '時刻設定用のキー入力処理。 _min = Temp1 ' _sec = 0 '[秒]をリセット。 Enable Timer2 '1秒割り込みを許可。 Dispmode = 1 '[時・分]表示にする。 Goto Keycont1 ' ' * AVR 1.1V基準電圧の校正ルーチン * ' Refset: Config Adc = Single , Prescaler = Auto , Reference = Internal_1.1 'A/Dコンバータの基準電圧を変更。(内部1.1V) Leddata3 = &B01111001 '[r1.]を表示する。 Leddata4 = &B10101111 Gosub Ledoffl 'LEDの下位2桁を消灯する。 Gosub Keyoff 'キーが離されるまで待つ。 ' Temp1 = Refadj 'A/Dコンバータの基準電圧の設定。 Temp2 = 0 'LEDの下位桁を指定。 Temp3 = 0 '設定値の下限。 Temp4 = 20 '設定値の上限。 Gosub Tmskey '時刻設定用のキー入力処理。 Refadj = Temp1 Eeprefadj = Refadj 'EEPROMに書き込む。 Config Adc = Single , Prescaler = Auto , Reference = Avcc 'A/Dコンバータの基準電圧を戻す。(AVCC) Goto Keycont1 ' ' ------------------------------------ (Temp1 = 設定するデータ値) ' * 時刻設定用 キー入力 サブルーチン * (Temp2 = 設定するデータの桁位置) ' ------------------------------------ (Temp3 = 設定値の下限) ' (Temp4 = 設定値の上限) Tmskey: Temp5 = 1 '点滅用 F/F。 Temp6 = 1 '点滅用タイマー値。 ' Tmskey1: If Tifr1.ocf1a = 0 Then Goto Tmskey1 'If 10mS経過したか? Else Set Tifr1.ocf1a 'Timer1 比較A一致フラグをリセットする。 ' Gosub Keychk 'キー入力を確認する。 If Keyflg <> 0 Then Goto Tmskey2 'If キー入力が有りか? Then ' Temp6 = Temp6 - 1 '表示を点滅させる。 If Temp6 <> 0 Then Goto Tmskey1 'If 点滅タイマー カウント終了か? Else If Temp5 = 0 Then '点滅用 F/Fを反転する。 Temp5 = 1 Temp6 = 20 '点滅用のタイマー値。 If Temp2.0 = 0 Then 'If 下位桁を設定中か? Then Gosub Ledoffl 'LEDの下位2桁を消灯する。 Else Gosub Ledoffu 'LEDの上位2桁を消灯する。 End If Else Temp5 = 0 Temp6 = 40 '点滅用のタイマー値。 If Temp2.7 = 1 Then 'If [時]表示か? Then Gosub Hourcvwr '時間を12/24時間制で識別して表示する。 Else Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 End If End If Goto Tmskey1 ' ' Tmskey2: Keyflg = 0 'キー入力フラグをリセットする。 If Keydata = &B00000010 Then Goto Tmskey5 'If [SW2]が押されたか? Then If Keydata = &B00000100 Then Goto Tmskey3 'If [SW3]が押されたか? Then If Keydata = &B00001000 Then Goto Tmskey4 'If [SW4]が押されたか? Then Goto Tmskey1 ' ' Tmskey3: '[SW3] 設定値を加算。 Temp1 = Temp1 + 1 If Temp1 > Temp4 Then Temp1 = Temp3 'If 設定値が上限を超えたか? Then Goto Tmskey ' Tmskey4: '[SW4] 設定値を減算。 If Temp1 = Temp3 Then 'If 設定値が下限を超えるか? Then Temp1 = Temp4 Else Temp1 = Temp1 - 1 End If Goto Tmskey ' Tmskey5: '[SW2] 設定終了。 Gosub Keyoff 'キーが離されるまで待つ。 Return ' ' -------------------------------------- ' * キーが離されるまで待つサブルーチン * ' -------------------------------------- ' Keyoff: Gosub Keyport 'キー接続ポートからデータを入力。 If Keydata <> 0 Then Goto Keyoff 'If キーが離されたか? Else Waitms 100 Return ' ' --------------------------------------------- ' * バイナリ値を2桁のセグメントコードに変換し * (Temp1 = バイナリ・データ) ' * LEDに表示するサブルーチン * (Temp2 = 0 : LEDの下位2桁へ表示 , 1 : LEDの上位2桁へ表示) ' --------------------------------------------- (Temp2 = 2 : 下位へゼロサプレス表示 , 3 : 上位へゼロサプレス表示) ' Binsegwr: Gosub Binseg 'バイナリ値を2桁のセグメントコードに変換する。 ' If Temp2 > 1 Then 'If ゼロサプレス有りか? Then If Temp1 < 10 Then 'If バイナリ値が10未満か? Then Tempsb2 = &B11111111 '消灯。 End If End If ' If Temp2.0 = 0 Then 'If LEDの下位桁を指定か? Then Leddata1 = Tempsb1 Leddata2 = Tempsb2 Else 'LEDの上位桁の場合。 Leddata3 = Tempsb1 Leddata4 = Tempsb2 End If Return ' ' --------------------------------------- (Temp1 = バイナリ・データ) ' * バイナリ値を2桁のセグメントコードに * (Tempsb1 = 下位のセグメントコード) ' * 変換するサブルーチン * (Tempsb2 = 上位のセグメントコード) ' --------------------------------------- (Tempsb3 = 下位のBCD値) ' Binseg: Tempsb2 = Makebcd(temp1) 'バイナリ値を、BCD(Binary coded decimal)値に変換。 Tempsb3 = Tempsb2 And &H0F '下位のBCDコードを取得。 Tempsb1 = Lookup(tempsb3 , Segtab) '数値をセグメントコードへ変換する。 ' Tempsb2 = Tempsb2 And &HF0 '上位のBCDコードを取得。 Shift Tempsb2 , Right , 4 '下位へ移動する。 Tempsb2 = Lookup(tempsb2 , Segtab) '数値をセグメントコードへ変換する。 Return ' ' ------------------------------------------ ' * 時間 12/24時間制 識別表示 サブルーチン * (Temp1 = バイナリ・データ) ' ------------------------------------------ ' Hourcvwr: If Mf1224h = 1 Then 'If 24時間制か? Then Gosub Binsegwr '24時間制で表示する。 Else '12時間制表示。 Tempsb4 = Temp1 '24時間制時刻を12時間制に変換する。 If Temp1 = 0 Then Temp1 = 24 If Temp1 > 12 Then Temp1 = Temp1 - 12 Gosub Binsegwr 'バイナリ値を2桁のセグメントコードに変換してLED表示する。 Temp1 = Tempsb4 ' If Temp1 < 12 Then 'If AM or PM? Reset Leddata4.5 '[AM] セグメントを点灯する。 Else Reset Leddata4.4 '[PM] セグメントを点灯する。 End If End If Return ' ' -------------------------------------- ' * LEDの下位2桁を消灯するサブルーチン * ' -------------------------------------- ' Ledoffl: Leddata1 = &B11111111 Leddata2 = &B11111111 Return ' ' -------------------------------------- ' * LEDの上位2桁を消灯するサブルーチン * ' -------------------------------------- ' Ledoffu: Leddata3 = &B11111111 Leddata4 = &B11111111 Return ' ' *************************************** ' * TIMER0 比較一致(B) 割り込みルーチン * ' *************************************** ' Tint0b: Select Case Dmano 'DMA表示番号により、桁ごとのLEDセグメントデータをセットする。 Case 1 : Led_seg = Leddata1 'LED[1]のセグメントデータをセットする。 Reset Led_com1 'LED[1]のコモン信号をアクティブにする。 Dmano = 2 Case 2 : Led_seg = Leddata2 'LED[2]のセグメントデータをセットする。 Reset Led_com2 'LED[2]のコモン信号をアクティブにする。 Dmano = 3 Case 3 : Led_seg = Leddata3 'LED[3]のセグメントデータをセットする。 Reset Led_com3 'LED[3]のコモン信号をアクティブにする。 Dmano = 4 Case Else : Led_seg = Leddata4 'LED[4]のセグメントデータをセットする。 Reset Led_com4 'LED[4]のコモン信号をアクティブにする。 Dmano = 1 End Select Return ' ' *************************************** ' * TIMER0 比較一致(A) 割り込みルーチン * ' *************************************** ' Tint0a: Set Led_com1 '全ての桁のコモン信号をオフする。 Set Led_com2 Set Led_com3 Set Led_com4 Return ' ' End ' ' ************************************************* ' * 数値からLEDのセグメントコードへの変換テーブル * ' ************************************************* ' Segtab: Data &B11000000 '0 Data &B11111001 '1 Data &B10100100 '2 Data &B10110000 '3 Data &B10011001 '4 Data &B10010010 '5 Data &B10000010 '6 Data &B11111000 '7 Data &B10000000 '8 Data &B10010000 '9 ' ' ************************************ ' * 月ごとの最終日を取得するテーブル * ' ************************************ ' Monthtab: Data 0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31