' ' ********************************************** ' * * ' * 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コンバータに電源を供給。 ' ' ↓********************************************↓ ' ↓ これ以降に各自のプログラムを作成して下さい ↓ ' ↓********************************************↓ ' ' ' ******************************************* ' * SHT21 , HDC1000 * ' * 温度・湿度センサー テスト・プログラム * ' * Ver. 0.02 2016. 1.20 * ' ******************************************* ' ' ' ' * 変数の宣言 * ' Dim I2cbuff(20) As Byte 'I2C送受信バッファー。 Dim Sht21comsel As Byte 'SHT21測定コマンドの選択。 Dim Temperature1 As Integer 'SHT21温度値。(x0.01) Dim Humidity1 As Integer 'SHT21湿度値。(x0.01) Dim Temperature2 As Integer 'HDC1000温度値。(x0.01) Dim Humidity2 As Integer 'HDC1000湿度値。(x0.01) ' Dim Tempw1 As Word '汎用テンポラリ変数 Word型 No.1 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Tempstr As String * 20 '汎用テンポラリ変数 String型 ' ' * I2Cの初期設定 * ' Config I2cbus = 0 , Scl = Portd.0 , Sda = Portd.1 'I2Cバス[0]HDC1000のSCL,SDAラインを接続するポートピンを設定。 Config I2cbus = 1 , Scl = Portd.3 , Sda = Portd.2 'I2Cバス[1]SHT21のSCL,SDAラインを接続するポートピンを設定。 I2cbus = 0 'I2Cバス[0]HDC1000を選択する。 I2cinit 'I2Cバス[0]HDC1000のSCL,SDAラインを初期化する。 I2cbus = 1 'I2Cバス[1]SHT21を選択する I2cinit 'I2Cバス[1]SHT21のSCL,SDAラインを初期化する。 ' Deflcdchar 0 , &H08 , &H14 , &H08 , &H06 , &H09 , &H08 , &H09 , &H06 'カスタム文字[℃]をLCDへ書き込む。 Cursor Off 'LCDのカーソルをオフにする。 ' Waitms 50 'SHT21,HDC1000の起動待ち時間。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: ' ' *************** ' * SHT21の測定 * ' *************** ' ' ' * SHT21へ測定コマンドを送信する * ' I2cbus = 1 'I2Cバス[1]SHT21を選択する If Sht21comsel = 0 Then 'If 温度測定か? Then I2cbuff(5) = &B1111_0011 '[温度]測定トリガ(非ホールド)コマンドを送信する。 Sht21comsel = 1 Else I2cbuff(5) = &B1111_0101 '[湿度]測定トリガ(非ホールド)コマンドを送信する。 Sht21comsel = 0 End If ' I2cstart '[スタート・コンディション] の状態にする。 I2cwbyte &H80 'スレーブ・アドレス(書き込み)を送信する。 If Err <> 0 Then Goto Sht21error1 'If ACKが返ってこないか? Then I2cwbyte I2cbuff(5) '測定コマンドを送信する。 Waitus 20 '[非ホールド]時の待ち時間。(20μS) I2cstop '[ストップ・コンディション] の状態にする。 ' Waitms 100 '測定時間の待機。(プログラム上の設定値) ' ' * SHT21から測定データを受信する * ' I2cstart '[スタート・コンディション] の状態にする。 I2cwbyte &H81 'スレーブ・アドレス(読み出し)を送信する。 If Err <> 0 Then Goto Sht21error2 'If 測定が終了していないか? Then I2crbyte I2cbuff(1) , Ack '上位データを読み込む。 I2crbyte I2cbuff(2) , Ack '下位データを読み込む。 I2crbyte I2cbuff(3) , Nack 'チェックサムを読み込む。 I2cstop '[ストップ・コンディション] の状態にする。 ' Gosub Sht21crc 'SHT21用のCRC8を計算する。 If I2cbuff(3) <> I2cbuff(4) Then Goto Sht21error3 'If CRCエラーか? Then ' ' * 測定データをLCDに表示する * ' If I2cbuff(2).1 = 0 Then 'If 温度データか? Then I2cbuff(2) = I2cbuff(2) And &B1111_1100 'ステータス・ビットをマスクする。 Tempw1 = Makeint(i2cbuff(2) , I2cbuff(1)) '2バイトを1ワードに変換する。 Templ1 = 17572 * Tempw1 '温度変換の計算。(小数点演算を使わないために100倍した値) Temperature1 = Highw(templ1) '1 / 2^16 Temperature1 = -4685 + Temperature1 ' Locate 1 , 1 '温度値をLCDに表示する。 Tempstr = Str(temperature1) '数値変数を文字変数に変換する。 If Temperature1 < 0 Then 'If マイナスの値か? Then Lcd Format(tempstr , " 0.00") ; " " ; Chr(0) Else 'プラス値の場合。 Lcd Format(tempstr , " 0.00") ; " " ; Chr(0) End If Else '湿度データの場合。 I2cbuff(2) = I2cbuff(2) And &B1111_0000 'ステータス・ビットをマスクする。 Tempw1 = Makeint(i2cbuff(2) , I2cbuff(1)) '2バイトを1ワードに変換する。 Templ1 = 12500 * Tempw1 '湿度変換の計算。(小数点演算を使わないために100倍した値) Humidity1 = Highw(templ1) '1 / 2^16 Humidity1 = -600 + Humidity1 ' Locate 2 , 1 '湿度値をLCDに表示する。 Tempstr = Str(humidity1) '数値変数を文字変数に変換する。 Lcd Format(tempstr , " 0.00") ; " %" End If Main1: ' ' ***************** ' * HDC1000の測定 * ' ***************** ' ' ' * HDC1000へ測定コマンドを送信する * ' I2cbus = 0 'I2Cバス[0]HDC1000を選択する。 I2cbuff(1) = &H00 'ポインター[00]、測定を起動する。 I2csend &H80 , I2cbuff(1) , 1 'I2Cバスで、1バイトのデータを送信する。 If Err <> 0 Then Goto Hdc1000error1 'If ACKが返ってこないか? Then ' Waitms 100 '測定時間の待機。(プログラム上の設定値) ' ' * HDC1000から測定データを受信する * ' I2cstart '[スタート・コンディション] の状態にする。 I2cwbyte &H81 'スレーブ・アドレス(読み出し)を送信する。 If Err <> 0 Then Goto Hdc1000error2 'If 測定が終了していないか? Then I2crbyte I2cbuff(1) , Ack '温度の上位データを読み込む。 I2crbyte I2cbuff(2) , Ack '温度の下位データを読み込む。 I2crbyte I2cbuff(3) , Ack '湿度の上位データを読み込む。 I2crbyte I2cbuff(4) , Nack '湿度の下位データを読み込む。 I2cstop '[ストップ・コンディション] の状態にする。 ' Tempw1 = Makeint(i2cbuff(2) , I2cbuff(1)) '2バイトを1ワードに変換する。 Templ1 = Tempw1 * 16500 '温度変換の計算。(小数点演算を使わないために100倍した値) Temperature2 = Highw(templ1) '1 / 2^16 Temperature2 = Temperature2 - 4000 ' Tempw1 = Makeint(i2cbuff(4) , I2cbuff(3)) '2バイトを1ワードに変換する。 Templ1 = Tempw1 * 10000 '湿度変換の計算。(小数点演算を使わないために100倍した値) Humidity2 = Highw(templ1) '1 / 2^16 ' ' * 測定データをLCDに表示する * ' Locate 1 , 9 '温度値をLCDに表示する。 Tempstr = Str(temperature2) '数値変数を文字変数に変換する。 If Temperature2 < 0 Then 'If マイナスの値か? Then Lcd Format(tempstr , " 0.00") ; " " ; Chr(0) Else 'プラス値の場合。 Lcd Format(tempstr , " 0.00") ; " " ; Chr(0) End If ' Locate 2 , 9 '湿度値をLCDに表示する。 Tempstr = Str(humidity2) '数値変数を文字変数に変換する。 Lcd Format(tempstr , " 0.00") ; " %" ' Main2: Waitms 800 '1秒サイクルの待ち時間。 Goto Main ' ' * SHT21エラー (ACKが返ってこない) * ' Sht21error1: Locate 2 , 1 Lcd "ACKerror" Sht21error11: Locate 1 , 1 Lcd "#SHT21 " Goto Main1 ' ' * SHT21エラー (測定が終了していない) * ' Sht21error2: I2cstop '[ストップ・コンディション] の状態にする。 Locate 2 , 1 Lcd "NACK Ret" Goto Sht21error11 ' ' * SHT21エラー (CRCエラー) * ' Sht21error3: Locate 2 , 1 Lcd "CRC Err." Goto Sht21error11 ' ' * SHT21用のCRC8を計算する * ' Sht21crc: Loadadr I2cbuff(1) , Z $asm LDI R16,$02 '計算するバイト数。 CLR R24 'CRC値。 LDI R22,$31 'POLYNOMIAL = 0x131 P(x)=x^8+x^5+x^4+1 = 1_0011_0001 Sht21crc1: LD R25,Z+ '計算するバイトを読み出す。 EOR R24,R25 'CRC = CRC EXOR I2cbuff(x) LDI R17,$08 Sht21crc2: LSL R24 'CRCを左へ1bitシフトする。 BRcc Sht21crc3 'If シフト前のCRCのbit7が[1]か? Else EOR R24,R22 'CRC = CRC EXOR &H31 Sht21crc3: DEC R17 BRNE Sht21crc2 'If 8ビット終了か? Else DEC R16 BRNE Sht21crc1 'If 計算するバイト数が終わったか? Else ADIW R30,1 '受信CRCバイトの次に計算CRC値を格納する。 ST Z,R24 $end Asm Return ' ' * HDC1000エラー (ACKが返ってこない) * ' Hdc1000error1: Locate 2 , 9 Lcd "ACKerror" Hdc1000error11: Locate 1 , 9 Lcd "#HDC1000" Goto Main2 ' ' * HDC1000エラー (測定が終了していない) * ' Hdc1000error2: I2cstop '[ストップ・コンディション] の状態にする。 Locate 2 , 9 Lcd "NACK Ret" Goto Hdc1000error11 ' ' End