' ' ********************************************** ' * * ' * AVR & BASCOM-AVR トレーニング・ボード * ' * 初期設定 Ver.1.01 * ' * * ' * AVR is using ATmega88P * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2010.10.29 * ' ********************************************** ' $regfile = "m88pdef.dat" '使用するAVRを設定。 $crystal = 16000000 'AVRクロックを設定。 ' $hwstack = 64 'ハードウェア・スタックの容量を設定。 $swstack = 10 'ソフトウェア・スタックの容量を設定。 $framesize = 24 'フレーム領域の容量を設定。 ' ' * ポート名の定義 * ' Sw_1 Alias Pind.0 'スイッチ[1]の接続ポート。 Sw_2 Alias Pind.1 'スイッチ[2]の接続ポート。 Sw_3 Alias Pind.2 'スイッチ[3]の接続ポート。 Sw_4 Alias Pind.3 'スイッチ[4]の接続ポート。 ' Led_1r Alias Portd.4 'LED1[赤]の接続ポート。 Led_2g Alias Portd.5 'LED2[緑]の接続ポート。 Led_3y Alias Portd.6 'LED3[黄]の接続ポート。 Led_4b Alias Portd.7 'LED4[青]の接続ポート。 Sp_out Alias Portc.5 'スピーカーの接続ポート。 ' Ad_photo Alias 0 '光センサーのA/Dコンバータ・チャネル番号。 Ad_thermo Alias 1 '温度センサーのA/Dコンバータ・チャネル番号。 Ad_ain1 Alias 2 '測定入力[1]のA/Dコンバータ・チャネル番号。 Ad_ain2 Alias 3 '測定入力[2]のA/Dコンバータ・チャネル番号。 Ad_ain3 Alias 4 '測定入力[3]のA/Dコンバータ・チャネル番号。 Ad_spin Alias 5 'スピーカー入力のA/Dコンバータ・チャネル番号。 ' ' * ポートの初期設定 * ' Config Led_1r = Output 'LED1の接続ポートを出力に設定する。 Config Led_2g = Output 'LED2の接続ポートを出力に設定する。 Config Led_3y = Output 'LED3の接続ポートを出力に設定する。 Config Led_4b = Output 'LED4の接続ポートを出力に設定する。 Config Sp_out = Output 'スピーカーの接続ポートを出力に設定する。 ' Set Portd.0 'スイッチ[1]の接続ポートをプルアップする。 Set Portd.1 'スイッチ[2]の接続ポートをプルアップする。 Set Portd.2 'スイッチ[3]の接続ポートをプルアップする。 Set Portd.3 'スイッチ[4]の接続ポートをプルアップする。 Didr0 = &B00111111 'デジタル入力禁止レジスタの設定。 ' ' * LCDの初期設定 * ' Config Lcdmode = Port 'LCDを4ビットのポートモードに設定。 Config Lcdbus = 4 'LCDデータバスを4bitに設定。 Config Lcdpin = Pin , Db4 = Portb.3 , Db5 = Portb.2 'LCDのポート割り当て。 Config Lcdpin = Pin , Db6 = Portb.1 , Db7 = Portb.0 Config Lcdpin = Pin , E = Portb.4 , Rs = Portb.5 Config Lcd = 16 * 2 'LCD表示を16文字2行に設定。 Cls 'LCD表示をすべて消去。 ' ' * A/Dコンバータの初期設定 * ' Config Adc = Single , Prescaler = Auto , Reference = Avcc 'A/Dコンバータの設定。 Start Adc 'A/Dコンバータに電源を供給。 ' ' ↓********************************************↓ ' ↓ これ以降に各自のプログラムを作成して下さい ↓ ' ↓********************************************↓ ' Cursor Off 'LCDのカーソルをオフにする。 ' ' ******************************************** ' * DS3234S TCXO水晶内蔵 SPIバスRTC * ' * 時計 テスト プログラム * ' * (Ver.1.01) * ' * Copyright By O-Family 2011.10. 5 * ' ******************************************** ' ' Dim Dbuff(10) As Byte 'DS3234Sの送受信バッファー。 Dim Monthlast As Byte '月の最終日。 Dim Mf1224h As Byte '時間表示モード。(0=24時間制 , 1=12時間制) Dim Keycun As Byte 'キー入力チェック用タイマーカウンター。 Dim Keyflg As Byte 'キー入力検出フラグ。 Dim Keydata As Byte 'キー入力データ。 Dim Keytemp As Byte 'キー入力用テンポラリ。 ' 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 Temp9 As Byte '汎用テンポラリ変数 Byte型 No.9 Dim Tempi1 As Integer '汎用テンポラリ変数 Integer型 No.1 Dim Tempstr As String * 20 '汎用テンポラリ変数 String型 ' Dim Eep1224h As Eram Byte 'EEPROM 時間表示モード。(0=24時間制 , 1=12時間制) ' ' * ソフトウェアSPIの設定 * ' Cs_out Alias Portd.4 '[/CS]ピンを割り当てる。 Config Cs_out = Output Set Cs_out '[/CS]を[H]にする。 ' Config Spi = Soft , Clock = Portd.5 , Dout = Portd.6 , Din = Pind.7 , Ss = None Spiinit 'SPIポートを初期化する。 ' Hz1_in Alias Pind.0 '1Hz信号の入力ピンを割り当てる。 Waitus 1 '/CSの待ち時間。 ' ' * DS3234Sの動作モードを設定する (方形波出力を1Hzにする) * ' Dbuff(1) = &H8E '制御レジスターのアドレスを指定。 Dbuff(2) = &B0000_0000 'RS2=0,RS1=0(1Hz) , INTCN=0(方形波出力) Reset Cs_out '[/CS]を[L]にする。 Spiout Dbuff(1) , 2 'DS3234Sの制御レジースターを設定する。 Set Cs_out '[/CS]を[H]にする。 Waitus 1 '/CSの待ち時間。 ' ' * Timerの設定 * ' Config Timer2 = Timer , Prescale = 1024 , Clear Timer = 1 'Timer2の設定。16,000,000Hz / 1024 = 15,625Hz Ocr2a = 156 - 1 '62,500Hz / 100Hz(10mS) = 約156カウント ' ' * 初期設定 * ' Config Clock = User '時計機能をUserモードに設定。(曜日の計算用) ' If Eep1224h > 1 Then 'If EEPROMが初期値か? Then Eep1224h = 0 '時間表示モードを[24時間制]に設定する。 End If Mf1224h = Eep1224h 'EEPROM値を変数に読み込む。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: ' ' * 1秒毎に時刻データを読み出す * ' If Temp1 = 0 Then 'If 1Hz出力の[H]チェック中か? Then If Hz1_in = 1 Then 'If 1Hz出力が[H]か?Then Temp1 = 1 Gosub Timeread '時刻データを読み込む。 Gosub Timedisp '時刻データを表示する。 End If Else '1Hz出力の[L]チェック中。 If Hz1_in = 0 Then 'If 1Hz出力が[L]か?Then Temp1 = 0 End If End If ' ' * スイッチ入力の確認 * ' Gosub Keychk 'スイッチ入力を調べる。 If Keyflg = 1 Then 'If スイッチ入力が有ったか? Then Keyflg = 0 If Keydata = &B00000010 Then 'If スイッチ[2]が押されたか? Then Toggle Mf1224h.0 '時間表示モードを変更する。 Eep1224h = Mf1224h 'EEPROMに保存する。 Gosub Timedisp 'LCDに時刻を表示する。 End If ' If Keydata = &B00001100 Then Goto Timeset 'If スイッチ[3 と 4]が押されたか? Then End If Goto Main ' ' ******************************************* ' * DS3234Sから、時刻と温度データを読み出す * ' ******************************************* ' Timeread: Reset Cs_out '[/CS]を[L]にする。 Temp1 = &H00 '[秒]レジスターのアドレス。 Spiout Temp1 , 1 '[秒]レジスターのアドレスを指定する。 Spiin Dbuff(1) , 7 '時刻データを読み出す。 Set Cs_out '[/CS]を[H]にする。 Waitus 1 '/CSの待ち時間。 ' Reset Cs_out '[/CS]を[L]にする。 Temp1 = &H11 '温度レジスターのアドレス。 Spiout Temp1 , 1 '温度レジスターのアドレスを指定する。 Spiin Dbuff(8) , 2 '温度データを読み出す。 Set Cs_out '[/CS]を[H]にする。 Waitus 1 '/CSの待ち時間。 Return ' ' *********************************** ' * 時刻と温度データをLCDへ表示する * ' *********************************** ' Timedisp: Locate 1 , 1 Lcd "20" ; Bcd(dbuff(7)) ; '[年]を表示。 _year = Makedec(dbuff(7)) 'BCD値を10進数の数値に変換する。 ' Temp9 = Dbuff(6) And &B0001_1111 '[世紀]ビットを排除する。 _month = Makedec(temp9) 'BCD値を10進数の数値に変換する。 Tempstr = Str(_month) '数値変数を文字変数に変換する。 Lcd "/" ; Format(tempstr , " 0") ; '[月]を表示。(ゼロサプレス) ' _day = Makedec(dbuff(5)) 'BCD値を10進数の数値に変換する。 Tempstr = Str(_day) '数値変数を文字変数に変換する。 Lcd "/" ; Format(tempstr , " 0") ; '[日]を表示。(ゼロサプレス) ' Temp9 = Dayofweek() '曜日を計算する。 Lcd " " ; Lookupstr(temp9 , Weekdata) '[曜日]を表示。 ' Locate 2 , 1 Temp9 = Dbuff(3) And &B0011_1111 'DS3234S内の12/24hフラグを排除する。 _hour = Makedec(temp9) 'BCD値を10進数の数値に変換する。 If Mf1224h = 0 Then 'If 時間表示モードが24時間制か? Then Tempstr = Str(_hour) '数値変数を文字変数に変換する。 Lcd " " ; Format(tempstr , " 0") ; '[時]を24時間制で表示。(ゼロサプレス) Else Temp9 = _hour '24時間制時刻を12時間制に変換。 If Temp9 = 0 Then Temp9 = 24 'If 午前0時か? Then If Temp9 > 12 Then Temp9 = Temp9 - 12 'If 午後か? Then ' If _hour < 12 Then 'If 午前か? Then Lcd "am"; Else Lcd "pm"; End If Tempstr = Str(temp9) '数値変数を文字変数に変換する。 Lcd Format(tempstr , " 0") ; '[時]を12時間制で表示。(ゼロサプレス) End If ' Lcd ":" ; Bcd(dbuff(2)) ; '[分]を表示。 _min = Makedec(dbuff(2)) 'BCD値を10進数の数値に変換する。 ' Lcd ":" ; Bcd(dbuff(1)) '[秒]を表示。 _sec = Makedec(dbuff(1)) 'BCD値を10進数の数値に変換する。 ' ' Locate 2 , 12 Tempi1 = Makeint(dbuff(9) , Dbuff(8)) 'バイトの温度値を16bitに変換する。 Shift Tempi1 , Right , 6 , Signed '下位ビットへそろえる。 Tempi1 = Tempi1 * 25 '0.25℃を掛け算する。 Tempi1 = Tempi1 / 10 '小数点以下を1桁にする。 Tempstr = Str(tempi1) '数値変数を文字変数に変換する。 Select Case Tempi1 Case Is =< -100 : '-10℃以下か? Lcd Left(tempstr , 3) ; " c" '[-40〜-10]の温度を表示。 Case Is < 0 : '0℃以下か? Lcd Format(tempstr , "0.0") ; "c" '[-9.9〜-0.1]の温度を表示。 Case Else : Lcd Format(tempstr , " 0.0") ; "c" '[+]の温度を表示。 End Select Return ' ' ***************************** ' * スイッチ入力 サブルーチン * (Keyflg = スイッチ入力が有ると1) ' ***************************** (Keydata = スイッチデータ) ' Keychk: If Tifr2.ocf2a = 0 Then Return 'If 10mS経過したか? Else Set Tifr2.ocf2a 'Timer2 比較A一致フラグをリセット。 ' 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 リピート期間待ち(1秒)か? 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 ' ' * キー接続ポートからのデータ入力サブルーチン * (Keydata = キー・データ) ' Keyport: Keydata = 0 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 ' **************** ' * 時刻設定処理 * ' **************** ' Timeset: _sec = 0 '[秒]を00に設定する。 Dbuff(1) = Makebcd(_sec) Gosub Timedisp 'LCDに時刻を表示する。 Cursor On , Blink 'LCDのカーソルをオン+点滅にする。 ' '[年]の設定。 Temp1 = 0 '設定値の下限を指定。 Temp2 = 99 '設定値の上限を指定。 Temp3 = _year '設定項目を指定する。 Timset11: Locate 1 , 4 'LCDのカーソルを移動する。 Gosub Tmskey '時刻設定用のキー入力処理。 If Keydata = &B00001000 Then Goto Timeset2 'If スイッチ[4]が押されたか? Then _year = Temp3 Dbuff(7) = Makebcd(_year) Gosub Timedisp 'LCDに時刻を表示する。 Goto Timset11 ' Timeset2: '[月]の設定。 Temp1 = 1 '設定値の下限を指定。 Temp2 = 12 '設定値の上限を指定。 Temp3 = _month '設定項目を指定する。 Timset21: Locate 1 , 7 'LCDのカーソルを移動する。 Gosub Tmskey '時刻設定用のキー入力処理。 If Keydata = &B00001000 Then Goto Timeset3 'If スイッチ[4]が押されたか? Then _month = Temp3 Dbuff(6) = Makebcd(_month) Gosub Timedisp 'LCDに時刻を表示する。 Goto Timset21 ' Timeset3: '[日]の設定。 Temp1 = 1 '設定値の下限を指定。 Gosub Monthchk '月ごとの日にちの最終日を計算する。 Temp2 = Monthlast '設定値の上限を指定。 Temp3 = _day '設定項目を指定する。 Timset31: Locate 1 , 10 'LCDのカーソルを移動する。 Gosub Tmskey '時刻設定用のキー入力処理。 If Keydata = &B00001000 Then Goto Timeset4 'If スイッチ[4]が押されたか? Then _day = Temp3 Dbuff(5) = Makebcd(_day) Gosub Timedisp 'LCDに時刻を表示する。 Goto Timset31 ' Timeset4: '[時]の設定。 Temp1 = 0 '設定値の下限を指定。 Temp2 = 23 '設定値の上限を指定。 Temp3 = _hour '設定項目を指定する。 Timset41: Locate 2 , 4 'LCDのカーソルを移動する。 Gosub Tmskey '時刻設定用のキー入力処理。 If Keydata = &B00001000 Then Goto Timeset5 'If スイッチ[4]が押されたか? Then _hour = Temp3 Dbuff(3) = Makebcd(_hour) Gosub Timedisp 'LCDに時刻を表示する。 Goto Timset41 ' Timeset5: '[分]の設定。 Temp1 = 0 '設定値の下限を指定。 Temp2 = 59 '設定値の上限を指定。 Temp3 = _min '設定項目を指定する。 Timset51: Locate 2 , 7 'LCDのカーソルを移動する。 Gosub Tmskey '時刻設定用のキー入力処理。 If Keydata = &B00001000 Then Goto Timeset6 'If スイッチ[4]が押されたか? Then _min = Temp3 Dbuff(2) = Makebcd(_min) Gosub Timedisp 'LCDに時刻を表示する。 Goto Timset51 ' Timeset6: '設定終了。 Reset Cs_out '[/CS]を[L]にする。 Temp1 = &H80 '[秒]レジスターのアドレス。 Spiout Temp1 , 1 '[秒]レジスターのアドレスを指定する。 Spiout Dbuff(1) , 7 '時刻をを書き込む。 Set Cs_out '[/CS]を[H]にする。 Waitus 1 '/CSの待ち時間。 ' Cursor Off , Noblink 'LCDのカーソルをオフにする。 Goto Main ' (Temp1 = 設定値の下限) ' * 時刻設定用のキー入力処理 サブルーチン * (Temp2 = 設定値の上限) ' (Temp3 = 修正する設定項目値) Tmskey: Gosub Keychk 'スイッチ入力を調べる。 If Keyflg = 0 Then Goto Tmskey 'If スイッチ入力が無いかか? Then Keyflg = 0 If Keydata = &B00001000 Then Return 'If スイッチ[4]が押されたか? Then If Keydata = &B00000010 Then Goto Tmskey1 'If スイッチ[2]が押されたか? Then If Keydata = &B00000100 Then Goto Tmskey2 'If スイッチ[3]が押されたか? Then Goto Tmskey ' Tmskey1: 'スイッチ[2]が押された(-)処理。? If Temp3 = Temp1 Then 'If 設定の下限値か? Then Temp3 = Temp2 Else Temp3 = Temp3 - 1 End If Return ' Tmskey2: 'スイッチ[3]が押された(+)処理。? Temp3 = Temp3 + 1 If Temp3 > Temp2 Then 'If 設定の上限値か? Then Temp3 = Temp1 End If Return ' ' * 月ごとの日にちの最終日を計算するサブルーチン * (Monthlast = その月の最終日) ' Monthchk: Select Case _month '月を確認する。 Case 2 : Temp4 = _year And &H03 '2月。 If Temp4 = 0 Then 'If 閏年か? Then Monthlast = 29 Else Monthlast = 28 End If Case 4 : Monthlast = 30 '4月。 Case 6 : Monthlast = 30 '6月。 Case 9 : Monthlast = 30 '9月。 Case 11 : Monthlast = 30 '11月。 Case Else : Monthlast = 31 '上記以外の月。 End Select Return ' ' End ' ' * 曜日 データ・テーブル * ' Weekdata: Data "MON" , "TUE" , "WED" , "THU" , "FRI" , "SAT" , "SUN"