' ' ********************************************** ' * * ' * 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のカーソルをオフにする。 ' ' ******************************************** ' * MPL115A2 デジタル気圧センサー * ' * 気圧計+天気予報 プログラム * ' * (Ver.1.01) * ' * Copyright By O-Family 2012. 2.10 * ' ******************************************** ' ' Const Serialoption = 0 'データのシリアル出力。(0=出力しない , 1=出力する) ' ' ' * 変数の宣言 * ' Dim Rxbuff(20) As Byte 'I2Cの受信データ・バッファー。 Dim Uipadc As Word '圧力のA/D変換値。 Dim Uitadc As Word '温度のA/D変換値。 Dim Sia0 As Integer '[a0] 圧力のオフセット係数。 Dim Sib1 As Integer '[b1] 圧力の感度係数。 Dim Sib2 As Integer '[b2] 1次の温度オフセット係数 (TCO)。 Dim Sic12 As Integer '[c12]温度感度係数(TCS)のための係数。 Dim Sic11 As Integer '[c11]圧力の直線性(2次)係数。 Dim Sic22 As Integer '[c22]2次の温度オフセット係数。 ' Dim Tl1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Tl2 As Long '汎用テンポラリ変数 Long型 No.2 Dim Tl3 As Long '汎用テンポラリ変数 Long型 No.3 Dim Tl4 As Long '汎用テンポラリ変数 Long型 No.4 ' Dim Average(32) As Word '移動平均用バッファー。 Dim Avgpoi As Byte '移動平均のポインター。 Dim Avgsum As Long '移動平均の合計値。 Dim Baropress As Word '気圧値。 Dim Deviation As Integer '気圧の24時間偏差値。 Dim Weather As Byte '天気予報値。 Dim Temperature As Integer '温度値。(x0.1) Dim Dbuf(24) As Word '24時間のデータバッファー。 Dim Dbufpoi As Byte '24時間のデータバッファー用ポインター。 Dim Hourtemp As Byte '[時]更新用テンポラリ。 Dim _sec As Byte '[秒]カウンター。 Dim _min As Byte '[分]カウンター。 Dim _hour As Byte '[時]カウンター。 ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Temp3 As Byte '汎用テンポラリ変数 Byte型 No.3 Dim Tempw1 As Word '汎用テンポラリ変数 Word型 No.1 Dim Tempi1 As Integer '汎用テンポラリ変数 Integer型 No.1 Dim Tempstr As String * 20 '汎用テンポラリ変数 String型 No.1 ' ' * Timerの設定 * ' Config Timer1 = Timer , Prescale = 1024 , Clear Timer = 1 'Timer1の設定。16,000,000Hz / 1024 = 15,625Hz Compare1a = 15625 - 1 '15,625Hz / 1Hz(1秒) = 15625カウント ' ' * カスタム文字をLCDへ書き込む * ' Deflcdchar 1 , &H10 , &H18 , &H14 , &H14 , &H02 , &H05 , &H06 , &H04 'カスタム文字[hp]をLCDへ書き込む。 Deflcdchar 2 , &H08 , &H14 , &H08 , &H06 , &H09 , &H08 , &H09 , &H06 'カスタム文字[℃]をLCDへ書き込む。 Deflcdchar 5 , &H04 , &H15 , &H0E , &H1F , &H0E , &H15 , &H04 , &H00 'カスタム文字[晴]をLCDへ書き込む。 Deflcdchar 6 , &H00 , &H0C , &H1E , &H1F , &H1F , &H0E , &H07 , &H00 'カスタム文字[雲]をLCDへ書き込む。 Deflcdchar 7 , &H04 , &H0E , &H1F , &H04 , &H04 , &H05 , &H02 , &H00 'カスタム文字[雨]をLCDへ書き込む。 ' ' * I2Cの初期設定 * ' Config Scl = Portd.2 'I2CバスのSCLラインを接続するポートピンを設定。 Config Sda = Portd.3 'I2CバスのSDAラインを接続するポートピンを設定。 ' Config I2cdelay = 1 'SCLクロック速度を設定。(BASCOMの仕様により約200KHz) I2cinit 'I2CバスのSCL,SDAラインを初期化。 ' ' * MPL115A2から係数ROMデータを読み出す * ' Rxbuff(1) = &H04 '係数ROMデータのメモリー・アドレスを指定する。 I2creceive &HC0 , Rxbuff(1) , 1 , 12 'I2Cバスで、1バイトのコマンドを送信し、12バイトのデータを受信する。 ' ' * 係数のバイト・データを16bitのワードに変換する * ' Sia0 = Makeint(rxbuff(2) , Rxbuff(1)) '[a0] 圧力のオフセット係数。 Sib1 = Makeint(rxbuff(4) , Rxbuff(3)) '[b1] 圧力の感度係数。 Sib2 = Makeint(rxbuff(6) , Rxbuff(5)) '[b2] 1次の温度オフセット係数 (TCO)。 Sic12 = Makeint(rxbuff(8) , Rxbuff(7)) '[c12]温度感度係数(TCS)のための係数。 Sic11 = Makeint(rxbuff(10) , Rxbuff(9)) '[c11]圧力の直線性(2次)係数。 Sic22 = Makeint(rxbuff(12) , Rxbuff(11)) '[c22]2次の温度オフセット係数。 ' #if Serialoption = 1 'If データをシリアル出力するか? Then $baud = 9600 'ハードウェアUARTの通信速度(ボーレート)を設定。 Print Print Print "a0: b1: b2: c12: c11: c22:" Print Hex(sia0) ; " "; '係数ROMデータをシリアル出力する。 Print Hex(sib1) ; " "; Print Hex(sib2) ; " "; Print Hex(sic12) ; " "; Print Hex(sic11) ; " "; Print Hex(sic22) Print #endif ' ' * 移動平均・24時間バッファーを初期化する * ' Gosub Baroconv '[MPL115A2]から気圧取得と係数補正。 Baropress = Tempw1 For Avgpoi = 1 To 32 '移動平均バッファーを初期値で埋める。 Average(avgpoi) = Tempw1 Next Avgpoi Avgsum = Tempw1 Shift Avgsum , Left , 5 '32個の平均合計を作る。 ' For Dbufpoi = 1 To 24 '24時間のデータバッファーを初期値で埋める。 Dbuf(dbufpoi) = Tempw1 Next Dbufpoi Avgpoi = 1 '移動平均のポインターを初期化。 Dbufpoi = 1 '24時間のデータバッファーポインターを初期化。 Weather = 4 '天気の初期値。 Hourtemp = 255 '[時]の更新テンポラリの初期化。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: If Tifr1.ocf1a = 1 Then 'If 1秒経過したか? Then Set Tifr1.ocf1a 'Timer1 比較A一致フラグをリセット。 ' _sec = _sec + 1 '[秒]を更新。 If _sec > 59 Then 'If 60秒 経過したか? Then _sec = 0 _min = _min + 1 '[分]を更新。 If _min > 59 Then 'If 60分 経過したか? Then _min = 0 _hour = _hour + 1 '[時]を更新。 End If End If ' ' * 経過時間を表示する * ' Locate 1 , 8 Tempstr = Str(_hour) '数値変数を文字変数に変換する。 Lcd Format(tempstr , " 0") ; ":"; '[時]を表示。 Tempstr = Str(_min) '数値変数を文字変数に変換する。 Lcd Format(tempstr , "00") ; ":"; '[分]を表示。 Tempstr = Str(_sec) '数値変数を文字変数に変換する。 Lcd Format(tempstr , "00") '[秒]を表示。 ' ' * 温度の測定 * ' Tl1 = Getadc(ad_thermo) '温度センサー値をA/D変換する。 Tl1 = 5000 * Tl1 '5.000V÷1024×1000000×[A/D値]÷1000 Shift Tl1 , Right , 10 , Signed '式を変えて 5.000V×1000×[A/D値]÷1024 Temperature = Tl1 - 600 '温度センサーIC [LM61]の温度変換計算。 ' Locate 1 , 1 Tempstr = Str(temperature) '数値を文字列に変換する。 If Temperature >= 0 Then 'If プラスの温度か? Then Lcd Format(tempstr , " 0.0") ; 'LCDに温度を表示する。 Else Lcd Format(tempstr , " 0.0") ; 'LCDに温度を表示する。 End If Lcd Chr(2) ' ' * MPL115A2から気圧値を取得する * ' Gosub Baroconv '[MPL115A2]から気圧を取得し係数で補正する。 ' ' * 気圧値を移動平均する * ' Avgsum = Avgsum - Average(avgpoi) '一番古いデータを減算する。 Average(avgpoi) = Tempw1 '移動平均バッファーに格納する。 Avgsum = Avgsum + Tempw1 '新しいデータを合算する。 ' Avgpoi = Avgpoi + 1 '移動平均ポインターを更新する。 If Avgpoi > 32 Then 'If ポインターが上限か? Then Avgpoi = 1 End If ' Tl4 = Avgsum Shift Tl4 , Right , 5 '32個の移動平均を取る。 Baropress = Tl4 '平均気圧値。 ' ' * 気圧値をLCDに表示する * ' Locate 2 , 1 'LCDへ気圧値を表示する。 Tempstr = Str(baropress) '数値を文字列に変換する。 Lcd Format(tempstr , " 0.0") ; Chr(1) ' #if Serialoption = 1 'If データをシリアル出力するか? Then Tempstr = Str(_hour) 'シリアル出力へ[時]の送信。 Print Format(tempstr , " 00") ; ":"; Tempstr = Str(_min) 'シリアル出力へ[分]の送信。 Print Format(tempstr , "00") ; ":"; Tempstr = Str(_sec) 'シリアル出力へ[秒]の送信。 Print Format(tempstr , "00") ; " "; ' Tempstr = Str(baropress) 'シリアル出力へ[気圧]の送信。 Print Format(tempstr , " 0.0") ; " hPa "; ' Tempstr = Str(temperature) 'シリアル出力へ[温度]の送信。 Print Format(tempstr , " 0.0") ; " C" #endif ' ' * 1時間毎の処理 * ' If _hour <> Hourtemp Then 'If 1時間経過したか? Then Hourtemp = _hour ' Gosub Weatherreport '気圧値24時間偏差を求めて天気を予報する。 ' ' * 気圧の偏差値をLCDに表示する * ' Locate 2 , 8 'LCDに24時間の偏差値を表示する。 Tempstr = Str(deviation) '数値を文字列に変換する。 Lcd Format(tempstr , "+ 0.0") ' ' * 天気予報をLCDに表示する * ' Locate 2 , 15 '天気予報を表示する。 Select Case Weather Case 5 : '[晴れ] Lcd Chr(5) ; " " Case 4 : '[晴れ+曇り] Lcd Chr(5) ; Chr(6) Case 3 : '[曇り] Lcd Chr(6) ; " " Case 2 : '[雨] Lcd Chr(7) ; " " End Select End If End If Goto Main ' ' ********************************** ' * [MPL115A2]の気圧変換と係数補正 * (Tempw1 = 気圧値[XXXX.XhPa] ※整数値で下1桁が小数点以下) ' ********************************** ' Baroconv: Rxbuff(1) = &H12 '[圧力と温度] 両方の変換開始コマンド。 Rxbuff(2) = &H01 'コマンドに続くダミーのデータ。 I2csend &HC0 , Rxbuff(1) , 2 'I2Cバスで、2バイトのデータを送信する。 ' Waitms 10 'MPL115Aの変換待ち時間。 ' ' * [圧力と温度]のデータを読み出す * ' Rxbuff(1) = &H00 '[圧力の上位バイト Padc MSB]のメモリー・アドレスを指定する。 I2creceive &HC0 , Rxbuff(1) , 1 , 4 'I2Cバスで、1バイトのコマンドを送信し、4バイトのデータを受信する。 ' ' * [圧力と温度]のA/D変換値をワードに変換し、下位10bitに移動する * ' Uipadc = Makeint(rxbuff(2) , Rxbuff(1)) '圧力のA/D変換値(8bit)を16bitにまとめる。 Shift Uipadc , Right , 6 '下位10bitに移動させる。 ' Uitadc = Makeint(rxbuff(4) , Rxbuff(3)) '温度のA/D変換値(8bit)を16bitにまとめる。 Shift Uitadc , Right , 6 '下位10bitに移動させる。 ' ' * 圧力のA/D変換値に係数を適用し補償する * ' Pcomp = a0 + (b1 + c11 * Padc + c12 * Tadc) * Padc + (b2 + c22 * Tadc) * Tadc ' Tl1 = Sic11 'c11 = S(11,10) + Z[ ,11] = S(11,22) 16bitに調整(+5) → S(16,27) Tl2 = Uipadc 'Padc (10,0) Tl3 = Tl1 * Tl2 '[Tl3]: c11x1 S(26,27) = c11 S(16,27) * Padc (10,0) ' Tl1 = Sib1 'b1 S(16,13) Shift Tl1 , Left , 14 'b1 S(16,13)をc11x1 S(26,27)と小数点を合わせるため、14bit左シフト Tl3 = Tl1 + Tl3 '[Tl3]: a11 S(30,27) = b1 S(30,27) + c11x1 S(26,27) Shift Tl3 , Right , 14 , Signed '[Tl3]: 16bitに戻すため、14bit右シフト → a11 S(16,13) ' Tl1 = Sic12 'c12 = S(14,13) + Z[ ,9] = S(14,22) 16bitに調整(+2) → S(16,24) Tl2 = Uitadc 'Tadc (10,0) Tl4 = Tl1 * Tl2 '[Tl4]: c12x2 S(26,24) = c12 S(16,24) * Tadc (10,0) ' Shift Tl3 , Left , 11 'a11 S(16,13)をc12x2 S(26,24)と小数点を合わせるため、11bit左シフト Tl3 = Tl3 + Tl4 '[Tl3]: a1 S(27,24) = a11 S(27,24) + c12x2 S(26,24) Shift Tl3 , Right , 11 , Signed '[Tl3]: 16bitに戻すため、11bit右シフト → a1 S(16,13) ' Tl1 = Sic22 'c22 = S(11,10) + Z[ ,15] = S(11,25) 16bitに調整(+5) → S(16,30) Tl4 = Tl1 * Tl2 '[Tl4]: c22x2 S(26,30) = c22 S(16,30) * Tadc (10,0) ' Tl1 = Sib2 'b2 S(16,14) Shift Tl1 , Left , 15 'b2 S(16,14)をc22x2 S(26,30)と小数点を合わせるため、15bit左シフト Shift Tl4 , Right , 1 , Signed 'c22x2 S(26,30)を1bit右シフトして縮小する → c22x2 S(25,29) Tl4 = Tl1 + Tl4 '[Tl4]: a2 S(31,29)実際はS(32,29) = b2 S(31,29) + c22x2 S(25,29) Shift Tl4 , Right , 16 , Signed '[Tl4]: 16bitに戻すため、16bit右シフト → a2 S(16,13) ' Tl1 = Uipadc 'Padc (10,0) Tl3 = Tl3 * Tl1 '[Tl3]: a1x1 S(26,13) = a1 S(16,13) * Padc (10,0) ' Tl1 = Sia0 'a0 S(16,3) Shift Tl1 , Left , 10 'a0 S(16,3)をa1x1 S(26,13)と小数点を合わせるため、10bit左シフト Tl3 = Tl1 + Tl3 '[Tl3]: y1 S(26,13) = a0 S(26,13) + a1x1 S(26,13) Shift Tl3 , Right , 10 , Signed '[Tl3]: 16bitに戻すため、10bit右シフト → y1 S(16,3) ' Tl4 = Tl4 * Tl2 '[Tl4]: a2x2 S(26,13) = a2 S(16,13) * Tadc (10,0) ' Shift Tl3 , Left , 10 'y1 S(16,3)をa2x2 S(26,13)と小数点を合わせるため、10bit左シフト Tl1 = Tl3 + Tl4 'Pcomp S(26,13) = y1 S(26,13) + a2x2 S(26,13) Shift Tl1 , Right , 13 , Signed '小数点以下を切り捨てて整数にするために、13bit右シフト ' ' * 気圧値の計算 * ' 気圧値 = ((65.0 / 1023.0) * 圧力値) + 50 [kPa] = (圧力値 * 65000 + 51150000) / 1023 [Pa] ' Tl2 = Tl1 * 65000 Tl2 = Tl2 + 51150000 Tl2 = Tl2 / 10230 '[Pa]を[XXXX.XhPa]に変換する。 Tempw1 = Tl2 '※整数値で下1桁が小数点以下 Return ' ' ****************************************** ' * 気圧値24時間偏差を求めて天気を予報する * ' ****************************************** ' Weatherreport: Tempw1 = Dbuf(dbufpoi) '24時間前のデータを読み出す。 Dbuf(dbufpoi) = Baropress '最新の気圧値を格納する。 Dbufpoi = Dbufpoi + 1 '24時間のデータバッファーポインターを更新する。 If Dbufpoi > 24 Then 'If ポインターが上限か? Then Dbufpoi = 1 End If ' Deviation = Baropress - Tempw1 '24時間の差分を求める。 ' Select Case Deviation Case Is > 50 : '[晴れ] Temp1 = 5 Case Is > 20 : '[晴れ+雲] Temp1 = 4 Case Is < -50 : '[雨] Temp1 = 2 Case Is < -20 : '[曇り] Temp1 = 3 Case Else : '[天候変化無し] Temp1 = Weather End Select Weather = Temp1 '天気予報値。 Return ' ' End