' ' ********************************************** ' * * ' * AVR & BASCOM-AVR トレーニング・ボード * ' * 初期設定 Ver.1.01 * ' * * ' * AVR is using ATmega88P * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2009. 7.25 * ' ********************************************** ' $regfile = "m88pdef.dat" '使用するAVRを設定。 $crystal = 16000000 'AVRクロックを設定。 ' $hwstack = 64 'ハードウェア・スタックの容量を設定。 $swstack = 8 'ソフトウェア・スタックの容量を設定。 $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コンバータに電源を供給。 ' ' ↓********************************************↓ ' ↓ これ以降に各自のプログラムを作成して下さい ↓ ' ↓********************************************↓ ' ' ' ************************************************ ' * 温度・湿度 センサー [SHT11] 制御プログラム * ' * 湿度変換係数は(V3) (Ver.1.01) * ' * Copyright By O-Family 2011. 5.30 * ' ************************************************ ' ' Sht11_sck Alias Portd.4 'SHT11の[SCK]接続ポート。 Sht11_do Alias Portd.3 'SHT11の[DATA]接続ポート(出力用)。 Sht11_di Alias Pind.3 'SHT11の[DATA]接続ポート(入力用)。 Const Sht11_vcc = 5 'SHT11の電源電圧。(5:5V, 33:3.3V) ' ' Dim Temperature As Integer '温度値。(温度値×100) Dim Humidity As Word '湿度値。(湿度値×100) Dim Sht11_sta As Byte 'SHT11の起動状態。(0:待機中, 1:測定中) Dim Sht11_err As Byte 'SHT11のエラー状態。 Dim Sht11_rxd(6) As Byte 'SHT11からの受信データ。 Dim Rh As Long '湿度の補正値保管用。 Dim Tso As Long '湿度の補正値保管用。 Dim Trh As Long '湿度の補正値保管用。 ' Dim Tim1sf As Byte '1秒経過フラグ。 Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Temp3 As Byte '汎用テンポラリ変数 Byte型 No.3 Dim Tempi1 As Integer '汎用テンポラリ変数 Integer型 No.1 Dim Tempstr As String * 20 '汎用テンポラリ変数 String型 No.1 ' Cursor Off 'LCDのカーソルをオフにする。 ' ' * Timerの設定 * ' Config Timer1 = Timer , Prescale = 256 , Clear Timer = 1 'Timer1の設定。16,000,000Hz / 256 = 62,500Hz Compare1a = 62500 - 1 '62,500Hz / 1Hz(1秒) = 62,500カウント On Compare1a Tint1sec 'TIMER1比較一致A割り込みルーチンのラベルを設定。 Enable Compare1a 'TIMER1比較一致A割り込みを許可。 ' ' * 初期設定 * ' Config Sht11_sck = Output 'SHT11のSCKポートを出力に設定する。 Reset Sht11_sck 'SHT11のSCKを[L]にする。 Reset Sht11_do '出力時のDATAを[L]にする。 Sht11_rxd(1) = 0 'ステータスレジスタのデフォルト値。 Sht11_rxd(2) = &B0000_0101 '測定コマンドの初期値。(湿度) Sht11_sta = 0 'SHT11の起動状態。(待機中) Enable Interrupts 'すべての割り込みを許可。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: Gosub Sht11_measure 'SHT11の温度・湿度 測定処理。 Goto Main ' ' ************************************* ' * Timer1 [1秒]割り込み 処理ルーチン * ' ************************************* ' Tint1sec: Tim1sf = 1 '1秒経過フラグを立てる。 Return ' ' ****************************** ' * SHT11の温度・湿度 測定処理 * ' ****************************** ' Sht11_measure: If Sht11_sta <> 0 Then Goto Sht11_mea1 'If SHT11の測定中か? Then If Tim1sf = 0 Then Return 'If 1秒経過していないか? Then ' Tim1sf = 0 Gosub Sht11_start 'SHT11に[Tr Start]通信開始シーケンスを送信する。 If Sht11_rxd(2) = &B0000_0101 Then 'If 前回の測定が(湿度)か? Then Temp1 = &B0000_0011 '温度測定コマンド。 Else Temp1 = &B0000_0101 '湿度測定コマンド。 End If Gosub Sht11_comtx 'SHT11にコマンドを送信する。 ' If Sht11_err <> 0 Then Goto Sht11_mea21 'If 通信エラー(ACKが返らない)か? Then Sht11_sta = 1 'SHT11の起動状態を[測定中]に変更する。 Return ' ' * SHT11 測定中の処理 * ' Sht11_mea1: If Tim1sf <> 0 Then Goto Sht11_mea23 'If 測定開始から1秒経過したか(タイムアウト)? Then If Sht11_di = 1 Then Return 'If SHT11が測定中か? Then ' ' * SHT11 測定終了で温度・湿度データを受信する * ' Gosub Sht11_datarx 'SHT11からデータを3バイト受信する。 Gosub Sht11_crc 'SHT11用のCRC8を計算する。 If Sht11_rxd(5) <> Sht11_rxd(6) Then Goto Sht11_mea22 'If CRCエラーか? Then ' Tempi1 = Makeint(sht11_rxd(4) , Sht11_rxd(3)) '2バイトの受信データを1ワードに変換する。 If Sht11_rxd(2) = &B0000_0011 Then 'If 測定結果は(温度)か? Then ' ' * 温度値の変換と電源電圧補正 * (T = d1 + d2 * SOT) (T = (d1*100) + (0.01*100) * SOT) ' #if Sht11_vcc = 5 'SHT11の電源電圧により係数を選択する。(14bit) Const D1 = -4010 'Vdd = 5V (-40.1 * 100) #else Const D1 = -3966 'Vdd = 3.3V (-39.66 * 100) #endif ' Temperature = D1 + Tempi1 'T = (d1*100) + (0.01*100) * SOT Else ' ' * 湿度センサーの非線形性を補正する (V3) * (SORH = Tempi1) ' Const C1 = -40000 'C1 = -4.0 * 10000 Const C2 = 405 'C2 = 0.0405 * 10000 Const C3 = -28 'C3 = 0.0000028 * 10000000 ' Rh = C2 * Tempi1 'RH = C1 + C2 * SO + C3 * (SO * SO) Rh = C1 + Rh Tso = Tempi1 * Tempi1 Tso = C3 * Tso Tso = Tso / 1000 Rh = Rh + Tso Rh = Rh / 100 'RH = RH * 100 (XX.XX = XXXX) ' ' * 湿度値の温度補償をする * ' Const T1 = 1000 'T1 = 0.01 * 1000 Const T2 = 8 'T2 = 0.00008 * 100000 ' Trh = Temperature - 2500 'RH = (Temperature - 25) * (T1 + T2 * SO) + RH Trh = Trh / 100 Tso = T2 * Tempi1 Tso = T1 + Tso Trh = Trh * Tso Trh = Trh / 1000 Humidity = Trh + Rh End If ' Sht11_mea3: Gosub Lcddisp '温度・湿度データをLCDに表示する。 Sht11_sta = 0 'SHT11の起動状態を[待機中]に戻す。 Return ' ' Sht11_mea21: '通信エラー(ACKが返らない)処理。 Gosub Sht11_rst 'SHT11との通信をリセットする。 Goto Sht11_mea3 ' ' Sht11_mea22: 'チェックサム(CRC)エラー。 Sht11_err = 2 Goto Sht11_mea21 ' ' Sht11_mea23: 'タイムアウト・エラー。 Sht11_err = 3 Tim1sf = 0 Goto Sht11_mea21 ' ' * SHT11に、[Tr Start] 通信開始シーケンスを送信する * ' Sht11_start: Gosub Sht11_dh 'SHT11のDATAを[H]にする。 Gosub Sht11_ch 'SHT11のSCKを[H]にする。 Gosub Sht11_dl 'SHT11のDATAを[L]にする。 Gosub Sht11_cl 'SHT11のSCKを[L]にする。 Gosub Sht11_ch 'SHT11のSCKを[H]にする。 Gosub Sht11_dh 'SHT11のDATAを[H]にする。 Gosub Sht11_cl 'SHT11のSCKを[L]にする。 Return ' ' * SHT11に、コマンドを送信する * [Temp1 = コマンド] ' Sht11_comtx: Sht11_rxd(2) = Temp1 'CRC計算にコマンドを追加する。 For Temp2 = 0 To 7 '1バイトのコマンドを送信する。 If Temp1.7 = 0 Then 'If 送信するビットが[0]か ? Then Gosub Sht11_dl 'SHT11のDATAを[L]にする。 Else '送信するビットが[1]。 Gosub Sht11_dh 'SHT11のDATAを[H]にする。 End If Gosub Sht11_ch 'SHT11のSCKを[H]にする。 Reset Sht11_sck 'SHT11のSCKを[L]にする。 Temp1 = Temp1 + Temp1 'Shift Temp1 , Left , 1 Next Temp2 Gosub Sht11_dh 'SHT11のDATAを[H]にする。 ' '[ACK]の受信。 Gosub Sht11_ch 'SHT11のSCKを[H]にする。 If Sht11_di = 0 Then 'If [ACK]が返ったか? Then Sht11_err = 0 Else Sht11_err = 1 '[ACK]エラー。 End If Gosub Sht11_cl 'SHT11のSCKを[L]にする。 Return ' ' * SHT11から、データを3バイト受信する * [Sht11_rxd(3,4,5) = 受信データ] ' Sht11_datarx: For Temp3 = 1 To 3 '3バイトのデータを受信する。 Temp1 = 0 For Temp2 = 0 To 7 '8ビットのデータを受信する。 Temp1 = Temp1 + Temp1 'Shift Temp1 , Left , 1 Gosub Sht11_ch 'SHT11のSCKを[H]にする。 If Sht11_di = 1 Then 'If [DATA]が[1]か? Then Set Temp1.0 End If Gosub Sht11_cl 'SHT11のSCKを[L]にする。 Next Temp2 Sht11_rxd(temp3 + 2) = Temp1 '受信データをバッファに格納する。 ' If Temp3 < 3 Then 'If [ACK]の送信か? Then Gosub Sht11_dl 'SHT11のDATAを[L]にする。 Else '[ACK]をスキップする。 Gosub Sht11_dh 'SHT11のDATAを[H]にする。 End If Gosub Sht11_ch 'SHT11のSCKを[H]にする。 Reset Sht11_sck 'SHT11のSCKを[L]にする。 Gosub Sht11_dh 'SHT11のDATAを[H]にする。 Next Temp3 Return ' ' * SHT11との通信をリセットする * ' Sht11_rst: Gosub Sht11_dh 'SHT11のDATAを[H]にする For Temp1 = 1 To 10 Gosub Sht11_ch 'SHT11のSCKを[H]にする。 Gosub Sht11_cl 'SHT11のSCKを[L]にする。 Next Temp1 Return ' ' * SHT11の[SCK]を[L]にする * ' Sht11_cl: Reset Sht11_sck 'SHT11のSCKを[L]にする。 Sht11_wait: Waitus 1 Return ' ' * SHT11の[SCK]を[H]にする * ' Sht11_ch: Set Sht11_sck 'SHT11のSCKを[H]にする。 Goto Sht11_wait ' ' * SHT11の[DATA]を[L]にする * ' Sht11_dl: Config Sht11_do = Output 'SHT11のDATAを[L]にする。 Goto Sht11_wait ' ' * SHT11の[DATA]を[H]にする * ' Sht11_dh: Config Sht11_do = Input 'SHT11のDATAを[H]にする。 Goto Sht11_wait ' ' * SHT11用のCRC8を計算する * ' Sht11_crc: Loadadr Sht11_rxd(1) , Z $asm LDI R24,$04 '計算するバイト数。 CLR R16 LDI R22,$8C Sht11_crc1: LD R23,Z+ LDI R25,$08 Sht11_crc2: LSR R16 ROL R23 SBRS R23,0 BRCC Sht11_crc3 ; SBRC R23,0 BRCS Sht11_crc3 ; EOR R16,R22 Sht11_crc3: DEC R25 BRNE Sht11_crc2 ; DEC R24 BRNE Sht11_crc1 ADIW R30,1 '受信CRCバイトの次に計算CRC値を格納する。 ST Z,R16 $end Asm Return ' ' *********************************** ' * 温度・湿度データをLCDに表示する * (Temperature = 温度データ , Humidity = 湿度データ) ' *********************************** (Sht11_err = [SHT11]の通信状態) ' Lcddisp: Locate 1 , 1 Select Case Sht11_err Case 0 : 'エラー無し。 Tempstr = Str(temperature) '数値変数を文字変数に変換する。 If Temperature < 0 Then 'If マイナス値か? Then Lcd Format(tempstr , " 0.00") ; "゚C"; 'LCDにマイナスの温度を表示する。 Else Lcd Format(tempstr , " 0.00") ; "゚C"; 'LCDにプラスの温度を表示する。 End If ' Tempstr = Str(humidity) '数値変数を文字変数に変換する。 Lcd " " ; Format(tempstr , " 0.00") ; "%" 'LCDに湿度を表示する。 ' Case 1 : 'ACK(応答)が返らないエラー。 Lcd "Error: no ACK " ' Case 2 : 'チェックサム(CRC)エラーが発生した。 Lcd "Error: CRC error" ' Case 3 : 'タイムアウトエラーが発生した。 Lcd "Error: Time out " End Select ' Locate 2 , 1 '受信データのテスト表示。 Lcd Hex(sht11_rxd(3)) ; " " ; Hex(sht11_rxd(4)) ; " " ; Hex(sht11_rxd(5)) Locate 2 , 11 Lcd "CRC=" ; Hex(sht11_rxd(6)) Return ' ' End