' ' ********************************************** ' * * ' * 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 = &B0010_0011 'デジタル入力禁止レジスタの設定。 ' ' * 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コンバータに電源を供給。 ' ' ↓********************************************↓ ' ↓ これ以降に各自のプログラムを作成して下さい ↓ ' ↓********************************************↓ ' '-------------------------------------------------------------------------------------------------- ' ************************************ ' * AVRトレーニング・ボード * ' * 照度センサー TSL2561の接続 * ' * Copyright O-Family 2017. 5.12 * ' ************************************ ' ' Ver. 1.01 初回公開バージョン。 2017. 5.12 ' Const Tsl2561_adr = &H72 'TSL2561のI2Cアドレス。(ADDR SEL = GND:52h , Open:72h , VDD:92h) ' ' * 変数の宣言 * ' Dim Igain As Byte '利得 (0: 1X , 1: 16X) Dim Tint As Byte '積分時間 (0: 13.7mS , 1: 101mS , 2: 402mS , 3: 手動) Dim Ch0 As Word 'ADCチャンネル(0)のデータ値。 Dim Ch1 As Word 'ADCチャンネル(1)のデータ値。 Dim Itype As Byte 'TSL2561のPARTNO(部品の識別番号)。(&B0001_0000: TSL2561CS , &B0101_0000: TSL2561T/FN/CL) Dim Lux As Dword '照度値。(Lux: 0〜64,000) Dim Temp As Dword '照度値の全桁を保管。(Lux * 16,384) ' Dim I2cbuff(20) As Byte 'I2Cの送受信バッファー。 Dim Tempstr As String * 16 '汎用テンポラリ変数 String型 ' Dim Dummy As Eram Long 'EEPROM 4バイトのダミーエリア。 Dim Eepigain As Eram Byte 'EEPROM 利得 (0: 1X , 1: 16X) Dim Eeptint As Eram Byte 'EEPROM 積分時間 (0: 13.7mS , 1: 101mS , 2: 402mS , 3: 手動) Cursor Off 'LCDのカーソルをオフにする。 ' ' * I2Cの初期設定 * ' Config Scl = Portc.2 'I2CバスのSCLラインを接続するポートピンを設定。 Config Sda = Portc.3 'I2CバスのSDAラインを接続するポートピンを設定。 I2cinit 'I2Cバスを初期化する。 ' ' * Timerの設定 * ' Config Timer1 = Timer , Prescale = 1024 , Clear Timer = 1 'Timer1の設定。16,000,000Hz / 1024 = 15,625Hz Compare1a = 6250 - 1 '15,625Hz / 2.5Hz(400ms) = 6250カウント ' ' * EEPROMのデータを確認する * ' If Eepigain > 1 Then 'If EEPROMが初期値か? Then Eepigain = 0 'EEPROM 利得 (0: 1X , 1: 16X) Eeptint = 2 'EEPROM 積分時間 (0: 13.7mS , 1: 101mS , 2: 402mS , 3: 手動) End If Igain = Eepigain Tint = Eeptint ' ' * TSL2561の電源を入れる * ' I2cbuff(1) = &H80 'CONTROLレジスター[0]のアドレスを指定する。 I2cbuff(2) = &B0000_0011 'POWERビットを[11]パワーアップにする。 I2csend Tsl2561_adr , I2cbuff(1) , 2 'I2Cバスで、2バイトのデータを送信する。 ' If Err <> 0 Then 'If TSL2561の応答が無いか? Then Locate 2 , 1 Lcd "# TSL2561 Error!" '[TSL2561]のエラーを表示する。 Sound Sp_out , 100 , 6666 '200Hzの音を500mS鳴らす。 Stop End If ' ' * TSL2561の部品の識別番号を確認する * ' I2cbuff(1) = &H8A 'IDレジスター[A]のアドレスを指定する。 I2creceive Tsl2561_adr , I2cbuff(1) , 1 , 1 'I2Cバスで、1バイトのコマンドを送信し、1バイトのデータを受信する。 Itype = I2cbuff(1) And &B1111_0000 'PARTNO(部品の識別番号)ビットを取り出す。 ' ' * TSL2561の利得と積分時間を設定する * ' Gosub Tsl2561set 'TSL2561の利得と積分時間を設定しLCDに表示する。 Locate 1 , 11 Lcd "Lux" '単位を表示する。 ' Sound Sp_out , 50 , 1333 '1000Hzの音を50mS鳴らす。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: ' ' * 照度の表示 * ' If Tifr1.ocf1a = 1 Then 'If 400ms経過したか? Then Set Tifr1.ocf1a 'Timer1の比較A一致フラグをリセット。 ' ' * ADCチャンネル(0),(1)のデータ値を読み出す * ' I2cbuff(1) = &H8C 'ADCチャンネル(0)のデータ・レジスター[C]のアドレスを指定する。 I2creceive Tsl2561_adr , I2cbuff(1) , 1 , 2 'I2Cバスで、1バイトのコマンドを送信し、2バイトのデータを受信する。 Ch0 = Makeint(i2cbuff(1) , I2cbuff(2)) '2バイトを1ワードに変換する。 ' I2cbuff(1) = &H8E 'ADCチャンネル(1)のデータ・レジスター[E]のアドレスを指定する。 I2creceive Tsl2561_adr , I2cbuff(1) , 1 , 2 'I2Cバスで、1バイトのコマンドを送信し、2バイトのデータを受信する。 Ch1 = Makeint(i2cbuff(1) , I2cbuff(2)) '2バイトを1ワードに変換する。 ' ' * 照度(Lux)を計算してLCDに表示する * ' I2cbuff(1) = 0 Select Case Tint 'オーバーフローを確認する。 Case 0 : '[0]: 13.7mS If Ch0 >= 5047 Then 'If オーバーフローか? Then I2cbuff(1) = 1 End If Case 1 : '[1]: 101mS If Ch0 >= 37177 Then 'If オーバーフローか? Then I2cbuff(1) = 1 End If Case 2 : '[2]: 402mS If Ch0 = 65535 Then 'If オーバーフローか? Then I2cbuff(1) = 1 End If End Select ' Locate 1 , 4 If I2cbuff(1) = 0 Then 'If オーバーフローしていないか? Then Gosub Tsl2561lux 'TSL2561 浮動小数点計算なしのlux(ルクス)近似方程式。 Tempstr = Str(lux) '照度値を文字列に変換。 Lcd Format(tempstr , " ") Else 'オーバー・フローの場合。 Lcd "-OVER-" End If End If ' ' * スイッチの確認 * ' Debounce Sw_3 , 0 , Sw3on 'スイッチ[3]の検出。 Debounce Sw_4 , 0 , Sw4on 'スイッチ[4]の検出。 ' Goto Main '-------------------------------------------------------------------------------------------------- ' ' * スイッチ[3]が押された場合 (利得の切り替え) * ' Sw3on: Igain = Igain + 1 '利得を変更する。 If Igain > 1 Then 'If 上限か? Then Igain = 0 End If Eepigain = Igain 'EEPROMに保管する。 Gosub Tsl2561set 'TSL2561の利得と積分時間を設定しLCDに表示する。 Goto Main ' ' * スイッチ[4]が押された場合 (積分時間の切り替え) * ' Sw4on: Tint = Tint - 1 '積分時間を変更する。 If Tint > 2 Then 'If 下限か? Then Tint = 2 End If Eeptint = Tint 'EEPROMに保管する。 Gosub Tsl2561set 'TSL2561の利得と積分時間を設定しLCDに表示する。 Goto Main ' ' * TSL2561の利得と積分時間を設定しLCDに表示する * ' Tsl2561set: I2cbuff(2) = Tint '積分時間 (0: 13.7mS , 1: 101mS , 2: 402mS , 3: 手動) Locate 2 , 2 If Igain = 0 Then 'If 利得が[0]:1X か? Then Lcd "G: 1X" Else '[1]:16Xの場合。 Set I2cbuff(2).4 'GAINビットを[1]にする。 Lcd "G:16X" End If ' Locate 2 , 9 Select Case Tint '積分時間を表示する。 Case 0 : Lcd "T:13.7ms" Case 1 : Lcd "T: 101ms" Case 2 : Lcd "T: 402ms" End Select ' I2cbuff(1) = &H81 'TIMINGレジスター[1]のアドレスを指定する。 I2csend Tsl2561_adr , I2cbuff(1) , 2 'I2Cバスで、2バイトのデータを送信する。 Return '################################################################################################## ' ' ***************************************************** ' * TSL2561 浮動小数点計算なしのlux(ルクス)近似方程式 * ' ***************************************************** ' Lux_scale Alias 14 ' 2^14でスケールする。 Ratio_scale Alias 9 ' スケール比は2^9。 '--------------------------------------------------- ' * 積分時間のスケーリング係数 * '--------------------------------------------------- Ch_scale Alias 10 ' チャンネルのスケール値を2^10倍にする。 Chscale_tint0 Alias &H7517 ' 322 / 11 * 2^CH_SCALE Chscale_tint1 Alias &H0FE7 ' 322 / 81 * 2^CH_SCALE '--------------------------------------------------- ' * T、FN、CLパッケージ係数 * '--------------------------------------------------- K1t Alias &H0040 ' 0.125 * 2^RATIO_SCALE B1t Alias &H01F2 ' 0.0304 * 2^LUX_SCALE M1t Alias &H01BE ' 0.0272 * 2^LUX_SCALE K2t Alias &H0080 ' 0.250 * 2^RATIO_SCALE B2t Alias &H0214 ' 0.0325 * 2^LUX_SCALE M2t Alias &H02D1 ' 0.0440 * 2^LUX_SCALE K3t Alias &H00C0 ' 0.375 * 2^RATIO_SCALE B3t Alias &H023F ' 0.0351 * 2^LUX_SCALE M3t Alias &H037B ' 0.0544 * 2^LUX_SCALE K4t Alias &H0100 ' 0.50 * 2^RATIO_SCALE B4t Alias &H0270 ' 0.0381 * 2^LUX_SCALE M4t Alias &H03FE ' 0.0624 * 2^LUX_SCALE K5t Alias &H0138 ' 0.61 * 2^RATIO_SCALE B5t Alias &H016F ' 0.0224 * 2^LUX_SCALE M5t Alias &H01FC ' 0.0310 * 2^LUX_SCALE K6t Alias &H019A ' 0.80 * 2^RATIO_SCALE B6t Alias &H00D2 ' 0.0128 * 2^LUX_SCALE M6t Alias &H00FB ' 0.0153 * 2^LUX_SCALE K7t Alias &H029A ' 1.3 * 2^RATIO_SCALE B7t Alias &H0018 ' 0.00146 * 2^LUX_SCALE M7t Alias &H0012 ' 0.00112 * 2^LUX_SCALE K8t Alias &H029A ' 1.3 * 2^RATIO_SCALE B8t Alias &H0000 ' 0.000 * 2^LUX_SCALE M8t Alias &H0000 ' 0.000 * 2^LUX_SCALE '--------------------------------------------------- ' * CSパッケージ係数 * '--------------------------------------------------- K1c Alias &H0043 ' 0.130 * 2^RATIO_SCALE B1c Alias &H0204 ' 0.0315 * 2^LUX_SCALE M1c Alias &H01AD ' 0.0262 * 2^LUX_SCALE K2c Alias &H0085 ' 0.260 * 2^RATIO_SCALE B2c Alias &H0228 ' 0.0337 * 2^LUX_SCALE M2c Alias &H02C1 ' 0.0430 * 2^LUX_SCALE K3c Alias &H00C8 ' 0.390 * 2^RATIO_SCALE B3c Alias &H0253 ' 0.0363 * 2^LUX_SCALE M3c Alias &H0363 ' 0.0529 * 2^LUX_SCALE K4c Alias &H010A ' 0.520 * 2^RATIO_SCALE B4c Alias &H0282 ' 0.0392 * 2^LUX_SCALE M4c Alias &H03DF ' 0.0605 * 2^LUX_SCALE K5c Alias &H014D ' 0.65 * 2^RATIO_SCALE B5c Alias &H0177 ' 0.0229 * 2^LUX_SCALE M5c Alias &H01DD ' 0.0291 * 2^LUX_SCALE K6c Alias &H019A ' 0.80 * 2^RATIO_SCALE B6c Alias &H0101 ' 0.0157 * 2^LUX_SCALE M6c Alias &H0127 ' 0.0180 * 2^LUX_SCALE K7c Alias &H029A ' 1.3 * 2^RATIO_SCALE B7c Alias &H0037 ' 0.00338 * 2^LUX_SCALE M7c Alias &H002B ' 0.00260 * 2^LUX_SCALE K8c Alias &H029A ' 1.3 * 2^RATIO_SCALE B8c Alias &H0000 ' 0.000 * 2^LUX_SCALE M8c Alias &H0000 ' 0.000 * 2^LUX_SCALE '-------------------------------------------------------------------------------------- ' 説明: TSL2560のADCチャンネル値から与えられる、おおよその照度(ルクス)を計算します。 ' 方程式は、区分的線形近似として実装されている場合。 ' ' iGain - 利得 (0: 1X , 1: 16X) ' tInt - 積分時間 (0: 13.7mS , 1: 101mS , 2: 402mS , 3: 手動) ' ch0 - TSL2560のチャネル(0)からのADC値 ' ch1 - TSL2560のチャネル(1)からのADC値 ' iType - パッケージ・タイプ (&B0001_0000: TSL2561CS , &B0101_0000: TSL2561T/FN/CL) ' ' Lux - 照度の概算値 (Lux: 0〜64,000) '-------------------------------------------------------------------------------------- ' 最初に、利得と積分時間に応じてチャネル値をスケーリングする。 ' 16X、402mS は標準値です。 ' もし、積分時間が402msecでない場合はスケールする。 Dim Chscale As Dword , Channel1 As Dword , Channel0 As Dword Tsl2561lux: Select Case Tint Case 0 : ' 13.7 msec Chscale = Chscale_tint0 ' Case 1 : ' 101 msec Chscale = Chscale_tint1 ' Case Else : ' スケーリングを行わない。 Chscale = 1 ' chScale = (1 << CH_SCALE); Shift Chscale , Left , Ch_scale End Select ' もし、利得が16Xでない場合はスケールする。 If Igain = 0 Then ' If 利得が (0: 1X) か? Then Shift Chscale , Left , 4 ' chScale = chScale << 4; (16倍する) End If ' チャンネルの値をスケールする。 Channel0 = Ch0 * Chscale ' Channel0 =(ch0 * Chscale) >> Ch_scale; Shift Channel0 , Right , Ch_scale Channel1 = Ch1 * Chscale ' Channel1 =(ch1 * Chscale) >> Ch_scale; Shift Channel1 , Right , Ch_scale '-------------------------------------------------------------------------------------- ' チャンネル値の比 (Channel1 / Channel0)を求める。 ' ゼロ除算から保護する。 Dim Ratio1 As Dword ' unsigned long ratio1 = 0; Ratio1 = 0 ' If Channel0 <> 0 Then ' if (channel0 != 0) ratio1 = (channel1 << (RATIO_SCALE+1)) / channel0; Temp = Channel1 Shift Temp , Left , Ratio_scale + 1 Ratio1 = Temp / Channel0 End If ' ' 比率値を丸める。 Dim Ratio As Dword ' unsigned long ratio = (ratio1 + 1) >> 1; Ratio1 = Ratio1 + 1 Shift Ratio1 , Right , 1 Ratio = Ratio1 ' ' パッケージごとの比率を選択する。 Dim B As Dword , M As Dword ' unsigned int b, m; ' If Itype = &B0101_0000 Then ' If T,FN,CLパッケージか? Then。 Select Case Ratio Case Is <= K1t : B = B1t : M = M1t Case Is <= K2t : B = B2t : M = M2t Case Is <= K3t : B = B3t : M = M3t Case Is <= K4t : B = B4t : M = M4t Case Is <= K5t : B = B5t : M = M5t Case Is <= K6t : B = B6t : M = M6t Case Is <= K7t : B = B7t : M = M7t Case Is > K8t : B = B8t : M = M8t End Select Else ' CSパッケージ。 Select Case Ratio Case Is <= K1c : B = B1c : M = M1c Case Is <= K2c : B = B2c : M = M2c Case Is <= K3c : B = B3c : M = M3c Case Is <= K4c : B = B4c : M = M4c Case Is <= K5c : B = B5c : M = M5c Case Is <= K6c : B = B6c : M = M6c Case Is <= K7c : B = B7c : M = M7c Case Is > K8c : B = B8c : M = M8c End Select End If ' Channel0 = Channel0 * B ' temp = ((channel0 * b) - (channel1 * m)); Channel1 = Channel1 * M ' ' 負のlux値を許可しない。 If Channel0 < Channel1 Then ' If マイナスの値になるか? Then Temp = 0 Else Temp = Channel0 - Channel1 End If ' ' 最下位を丸める。 (2^(LUX_SCALE-1)) Ratio1 = 1 ' temp += (1 << (LUX_SCALE-1)); Shift Ratio1 , Left , Lux_scale - 1 Lux = Temp + Ratio1 ' ' 小数点以下を切り捨てる。 Shift Lux , Right , Lux_scale ' lux = temp >> LUX_SCALE; Return '################################################################################################## End