' ' *********************************************** ' * * ' * PWM サイン波 発生プログラム * ' * * ' * AVR is using ATtiny45-20PU * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2008.10.27 * ' *********************************************** ' ' Ver 3.01 初回公開バージョン ' ' Const Prgver = "03.01" 'プログラム・バージョン。 ' $regfile = "ATtiny45.DAT" '使用するAVRを設定。 $crystal = 8000000 'AVRクロックを設定。 ' ' Const Wav_frq = 1000 'Sin波形の発生周波数を設定。(1〜約5000Hz) ' ' ' Dim Wavpoi As Word 'Timer0割り込み用の波形ROMポインター。 Dim Poiadd As Word '波形ROMポインターの加算値。 Dim Wavdiv As Word '波形の分割数。(AVR動作クロック÷256÷256) ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Tempw1 As Word '汎用テンポラリ変数 Woed型 No.1 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Temps1 As Single '汎用テンポラリ変数 Single型 No.1 Dim Temps2 As Single '汎用テンポラリ変数 Single型 No.2 Dim Temps3 As Single '汎用テンポラリ変数 Single型 No.3 ' Dim Eepsum As Eram Word At $02 'EEPROM Sinデータのチェックサム。 Dim Wavrom(128) As Eram Byte At $80 'Sin波形 保存用。 ' ' ' ' * ポートの初期設定 * ' Config Portb = Output ' ' * タイマーの設定 * ' Config Timer0 = Pwm , Prescale = 1 , Clear Timer = 1 , Compare A Pwm = Clear Down 'Timer0 8bit高速PWM動作。 Ocr0a = 128 'パルス幅。(初期値) On Ovf0 Tm0int Nosave 'Timer0 オーバーフロー 割り込みルーチンを設定。 Enable Ovf0 'Timer0 オーバーフロー 割り込みを許可。 ' ' **************************** ' * サイン波形のデータを準備 * ' **************************** ' Tempw1 = 0 'EEPROM波形のチェックサムを計算。 For Temp1 = 1 To 128 Temp2 = Wavrom(temp1) Tempw1 = Tempw1 + Temp2 Next Temp1 ' If Eepsum <> Tempw1 Then 'If EEPROMへSinデータを書き込み済み? Else ' Tempw1 = 0 Temps1 = Deg2rad(180) '角度180°のラジアン(弧度)値を取得。 Temps1 = Temps1 / 128 '波形の分解能を計算。 Temps2 = 0 For Temp1 = 1 To 128 '波形のコサイン値を計算(波形の前半分のみ)。 Temps3 = Cos(temps2) Temps3 = Temps3 * 128 '0〜127の値に変換。 Temp2 = Int(temps3) '整数化。 Temp2 = Temp2 + 128 'オフセットを加算 Wavrom(temp1) = Temp2 'EEPROMへ格納。 Tempw1 = Tempw1 + Temp2 'EEPROM波形のチェックサムを計算。 Temps2 = Temps2 + Temps1 Next Temp1 Eepsum = Tempw1 'EEPROMへチェックサムを書き込み。 ' End If ' ' *********************************** ' * 波形ROMポインターの加算値を計算 * ' *********************************** ' Templ1 = _xtal '波形の分割数を算出。 Wavdiv = Highw(templ1) 'AVR動作クロック÷256÷256 ' Templ1 = Wav_frq * 256 'ポインターは16bitの内、上位8bitを使用する。 Templ1 = Templ1 / Wavdiv 'ポインターの加算値を算出。 Poiadd = Templ1 'ポインターの加算値(16bit)を格納。 Wavpoi = 0 'ポインターを初期化。 ' Enable Interrupts 'すべての割り込みを許可。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: ' Goto Main ' End ' ' ********************************************** ' * Timer0 オーバーフロー 割り込み処理ルーチン * ' ********************************************** ' Tm0int: $asm PUSH R1 IN R1,SREG 'ステータス・レジスタを待避。 PUSH R16 PUSH R17 PUSH R22 PUSH R23 'R23は、拡張I/Oレジスタへのアクセスに使用する。 ; CLR R16 'EEPROMアドレスの上位バイトを設定。 Out Eearh , R16 LDS R17,{wavpoi+1} 'ポインターの位置を確認(上位8bitのみ使用)。 CPI R17,&H80 BRCC Tm0int1 'If 波形の後半? Then ; LDI R16,&H80 'EEPROMアドレスにオフセットを加算。 OR R16,R17 Out Eearl , R16 'EEPROMアドレスの下位バイトを設定。 SBI EECR,EERE 'EEPROM読み出し開始。 IN R22,EEDR 'EEPROMデータを取得。 RJMP Tm0int2 ; Tm0int1: '波形の後半処理。 Out Eearl , R17 'EEPROMアドレスの下位バイトを設定。 SBI EECR,EERE 'EEPROM読み出し開始。 IN R22,EEDR 'EEPROMデータを取得。 COM R22 '波形を後半用に処理。 ; Tm0int2: Out Ocr0a , R22 'SinデータをTimer0の比較器Aにセット。 ' LDS R16,{wavpoi} 'ポインターに加算値を加える。(16bit + 16bit) LDS R22,{poiadd} LDS R23,{poiadd+1} ADD R16,R22 ADC R17,R23 STS {wavpoi},R16 '新しいポインター位置を格納。 STS {wavpoi+1},R17 ; POP R23 POP R22 POP R17 POP R16 Out Sreg , R1 'ステータス・レジスタを復帰 POP R1 $end Asm Return ' End