$programmer = 22 'ARDUINO (using stk500v1 protocol) ' ' ***************************************** ' * AD9833 DDSモジュール コントローラ * ' * [MCLK:25MHz , OUT:0-12,499,999Hz] * ' * * ' * Copyright O-Family 2020. 2. 7 * ' ***************************************** ' ' Ver 0.01 初回公開バージョン。 2020. 2. 7 ' Const Board_version = 10 'DFROBOT社のボード・バージョン。[1.0] = 10 or [1.1] = 11 $regfile = "m328pdef.dat" '使用するAVRを設定。 $crystal = 16000000 'AVRクロックを設定。 ' $hwstack = 64 'ハードウェア・スタックの容量を設定。 $swstack = 10 'ソフトウェア・スタックの容量を設定。 $framesize = 24 'フレーム領域の容量を設定。 ' ' * ポート名の定義 * ' Lcd_bkl Alias Portb.2 'LCDのバックライト制御の接続ポート。 ' Dds_fsync Alias Portd.2 'DDSモジュールの[FSYNC]接続ポート。 Dds_sclk Alias Portd.3 'DDSモジュールの[SCLK]接続ポート。 Dds_sdata Alias Portb.3 'DDSモジュールの[SDATA]接続ポート。 ' ' * 変数の宣言 * ' Dim Keydata As Byte 'キー(スイッチ)の入力データ。(押された場合にコードが入る) Dim Keyadcode As Byte 'キー(スイッチ)をA/D変換したコード。(押されている状態のコードが入る) Dim Keystat As Byte , Keyw1 As Word 'キー(スイッチ)の検出状態フラグ。内部で使用する変数。 ' Dim Frequency As Long 'DDSに設定する周波数データ値。 Dim Freq1 As Long 'Ch.1の周波数。 Dim Freq2 As Long 'Ch.2の周波数。 Dim Ddscontreg As Word 'DDSのコントロール・レジスタの設定値。 Dim Waveselect As Byte '出力波形の選択。(0:正弦波, 1:三角波, 2:方形波) Dim Channel As Byte '出力のチャンネル選択。(0:Ch.1, 1:Ch.2) Dim Curx As Byte '設定カーソルの[X]位置。 ' 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 Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Temps1 As Single '汎用テンポラリ変数 Single型 No.1 Dim Tempstr As String * 20 '汎用テンポラリ変数 String型 No.1 Dim Tempstr2 As String * 20 '汎用テンポラリ変数 String型 No.2 ' Dim Eepdummy As Eram Long 'EEPROM 4バイトのダミーエリア。 Dim Eepprgid As Eram Long 'EEPROM プログラムのID。 Dim Eepfreq1 As Eram Long 'EEPROM Ch.1の周波数。 Dim Eepfreq2 As Eram Long 'EEPROM Ch.2の周波数。 Dim Eepwaveselect As Eram Byte 'EEPROM 出力波形の選択。(0:正弦波, 1:三角波, 2:方形波) '-------------------------------------------------------------------------------------------------- ' ' * ポートの初期設定 * ' Config Lcd_bkl = Output 'LCDのバックライト制御の接続ポートを出力に設定する。 Set Lcd_bkl 'LCDのバックライトを点灯する。 ' Config Dds_fsync = Output 'DDSの[FSYNC]接続ポートを出力に設定する。 Set Dds_fsync 'DDSの[FSYNC]を[H]にする。 Config Dds_sclk = Output 'DDSの[SCLK]接続ポートを出力に設定する。 Set Dds_sclk 'DDSの[SCLK]を[H]にする。 Config Dds_sdata = Output 'DDSの[SDATA]接続ポートを出力に設定する。 ' Set Portb.4 '未使用ポートをプルアップする。 Set Portb.5 '未使用ポートをプルアップする。 ' Set Portd.0 '未使用ポートをプルアップする。 Set Portd.1 '未使用ポートをプルアップする。 ' ' * A/Dコンバータの初期設定 * ' Config Adc = Single , Prescaler = Auto , Reference = Avcc 'A/Dコンバータの設定。 Start Adc 'A/Dコンバータに電源を供給する。 Didr0 = &B0011_1111 'デジタル入力禁止レジスタの設定。(アナログ入力ピンをデジタル入力禁止にする) ' ' * LCDの初期設定 * ' Config Lcdmode = Port 'LCDを4ビットのポートモードに設定。 Config Lcdbus = 4 'LCDデータバスを4bitに設定。 Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 'LCDのポート割り当て。 Config Lcdpin = Pin , Db6 = Portd.6 , Db7 = Portd.7 Config Lcdpin = Pin , E = Portb.1 , Rs = Portb.0 Config Lcd = 16 * 2 'LCD表示を16文字2行に設定。 Cls 'LCD表示をすべて消去。 ' ' * カスタム文字をLCDに設定する * ' Deflcdchar 0 , &H04 , &H0A , &H11 , &H00 , &H00 , &H11 , &H0A , &H04 'カスタム文字[上下矢印]をLCDへ書き込む。 Deflcdchar 1 , &H00 , &H08 , &H14 , &H14 , &H05 , &H05 , &H02 , &H00 'カスタム文字[サイン波]をLCDへ書き込む。 Deflcdchar 2 , &H00 , &H08 , &H08 , &H15 , &H15 , &H02 , &H02 , &H00 'カスタム文字[三角波]をLCDへ書き込む。 Deflcdchar 3 , &H00 , &H1C , &H14 , &H14 , &H05 , &H05 , &H07 , &H00 'カスタム文字[方形波]をLCDへ書き込む。 ' ' * EEPROMのデータを確認する * ' If Eepprgid <> &H33333839 Then 'If EEPROMが初期値か? Then Eepprgid = &H33333839 'EEPROM プログラムのID。[9833] Eepfreq1 = 0 'EEPROM Ch.1の周波数。 Eepfreq2 = 0 'EEPROM Ch.2の周波数。 Eepwaveselect = 0 'EEPROM 出力波形の選択。(0:正弦波, 1:三角波, 2:方形波) End If Freq1 = Eepfreq1 'Ch.1の周波数。 Freq2 = Eepfreq2 'Ch.2の周波数。 Waveselect = Eepwaveselect '出力波形の選択。(0:正弦波, 1:三角波, 2:方形波) ' ' * AD9833の初期設定 * ' Tempw1 = &B0010_0001_0000_1000 'DDSのコントロール・レジスタに[RESET]を送信する。 Gosub Ddsset 'DDSにワード・データを送信する。 ' Tempw1 = &B0100_0000_0000_0000 'DDSの[FREQ0]に初期値を送信する。 Gosub Ddsset 'DDSにワード・データを送信する。 Gosub Ddsset 'DDSにワード・データを送信する。 Tempw1 = &B1000_0000_0000_0000 'DDSの[FREQ1]に初期値を送信する。 Gosub Ddsset 'DDSにワード・データを送信する。 Gosub Ddsset 'DDSにワード・データを送信する。 ' Tempw1 = &B1100_0000_0000_0000 'DDSの[PHASE0]に初期値を送信する。 Gosub Ddsset 'DDSにワード・データを送信する。 Tempw1 = &B1110_0000_0000_0000 'DDSの[PHASE1]に初期値を送信する。 Gosub Ddsset 'DDSにワード・データを送信する。 ' Gosub Waveset 'DDSに出力波形を設定して[RESET]解除を送信する。 ' ' * LCDの初期表示 * ' Locate 1 , 15 Lcd "Hz" Locate 2 , 5 Lcd Chr(0) ; ", , cM" ' Channel = 0 '出力を[Ch.1]にする。 Gosub Modedisp 'LCDに設定項目を表示する。 ' Frequency = Freq1 '初期値を[Ch.1]にする。 Gosub Freqdisp 'LCDに設定周波数を表示する。 Gosub Freqset 'DDSの[FREQ0]レジスタに周波数データを送信する。 ' Curx = 5 '設定カーソルの初期位置。 Gosub Curdisp 'LCDに設定カーソルを表示する。 Cursor Off , Blink 'LCDのカーソルをオフ・点滅にする。 '================================================================================================== ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: Gosub Getkey 'キー(スイッチ)を検出する。 If Keydata = 0 Then Goto Main 'If キー入力がないか? Then ' ' * スイッチが押された処理 * ' Select Case Keydata Case 1 : '[SELECT]キーが押された場合。 If Channel = 0 Then 'If 現在の出力チャンネルが[Ch.1]か? Then Channel = 1 '出力を[Ch.2]にする。 Frequency = Freq2 '周波数を[Ch.2]にする。 Else '[Ch.2]の場合。 Channel = 0 '出力を[Ch.1]にする。 Frequency = Freq1 '周波数を[Ch.1]にする。 End If Gosub Modedisp 'LCDに設定項目を表示する。 Gosub Freqdisp 'LCDに設定周波数を表示する。 Gosub Freqset 'DDSの[FREQ0]レジスタに周波数データを送信する。 ' Case 2 : '[LEFT]キーが押された場合。 If Curx < 14 Then 'If 設定カーソルが[c][M]以外か? Then Lcd " " '[上下矢印]を消す。 End If ' Curx = Curx - 1 '設定カーソルを左へ移動させる。 Select Case Curx 'カーソルの位置調整。 Case 14 : Curx = 13 Case 10 : Curx = 9 Case 6 : Curx = 5 Case 3 : Curx = 2 Case 1 : Curx = 2 End Select ' Case 5 : '[RIGHT]キーが押された場合。 If Curx < 14 Then 'If 設定カーソルが[c][M]以外か? Then Lcd " " '[上下矢印]を消す。 End If ' Curx = Curx + 1 '設定カーソルを右へ移動させる。 Select Case Curx 'カーソルの位置調整。 Case 14 : Curx = 15 Case 10 : Curx = 11 Case 6 : Curx = 7 Case 3 : Curx = 4 Case 17 : Curx = 16 End Select ' Case 4 : '[UP]キーが押された場合。 Select Case Curx 'カーソルの位置による処理。 Case 2 : '出力波形を選択する。 Waveselect = Waveselect + 1 '出力波形を変更する。 If Waveselect > 2 Then 'If 上限か? Then Waveselect = 0 End If Eepwaveselect = Waveselect '出力波形選択をEEPROMに記憶する。 Gosub Modedisp 'LCDに設定項目を表示する。 Gosub Waveset 'DDSに出力波形を送信する ' Case 4 : '周波数[X0,000,000]位置の加算。 Frequency = Frequency + 10000000 Gosub Freqchg '出力周波数を変更する。 ' Case 5 : '周波数[0X,000,000]位置の加算。 Frequency = Frequency + 1000000 Gosub Freqchg '出力周波数を変更する。 ' Case 7 : '周波数[00,X00,000]位置の加算。 Frequency = Frequency + 100000 Gosub Freqchg '出力周波数を変更する。 ' Case 8 : '周波数[00,0X0,000]位置の加算。 Frequency = Frequency + 10000 Gosub Freqchg '出力周波数を変更する。 ' Case 9 : '周波数[00,00X,000]位置の加算。 Frequency = Frequency + 1000 Gosub Freqchg '出力周波数を変更する。 ' Case 11 : '周波数[00,000,X00]位置の加算。 Frequency = Frequency + 100 Gosub Freqchg '出力周波数を変更する。 ' Case 12 : '周波数[00,000,0X0]位置の加算。 Frequency = Frequency + 10 Gosub Freqchg '出力周波数を変更する。 ' Case 13 : '周波数[00,000,00X]位置の加算。 Frequency = Frequency + 1 Gosub Freqchg '出力周波数を変更する。 ' Case 15 : '[C]周波数の全クリア処理。 Frequency = 0 Gosub Freqchg '出力周波数を変更する。 ' Case 16 : '設定周波数のメモリー操作。 Eepfreq1 = Frequency '現在の周波数を[Ch.1]のEEPROMに記憶する。 End Select ' Case 3 : '[DOWN]キーが押された場合。 Select Case Curx 'カーソルの位置による処理。 Case 2 : '出力波形を選択する。 Waveselect = Waveselect - 1 '出力波形を変更する。 If Waveselect > 2 Then 'If 下限か? Then Waveselect = 2 End If Eepwaveselect = Waveselect '出力波形選択をEEPROMに記憶する。 Gosub Modedisp 'LCDに設定項目を表示する。 Gosub Waveset 'DDSに出力波形を送信する ' Case 4 : '周波数[X0,000,000]位置の減算。 Frequency = Frequency - 10000000 Gosub Freqchg '出力周波数を変更する。 ' Case 5 : '周波数[0X,000,000]位置の減算。 Frequency = Frequency - 1000000 Gosub Freqchg '出力周波数を変更する。 ' Case 7 : '周波数[00,X00,000]位置の減算。 Frequency = Frequency - 100000 Gosub Freqchg '出力周波数を変更する。 ' Case 8 : '周波数[00,0X0,000]位置の減算。 Frequency = Frequency - 10000 Gosub Freqchg '出力周波数を変更する。 ' Case 9 : '周波数[00,00X,000]位置の減算。 Frequency = Frequency - 1000 Gosub Freqchg '出力周波数を変更する。 ' Case 11 : '周波数[00,000,X00]位置の減算。 Frequency = Frequency - 100 Gosub Freqchg '出力周波数を変更する。 ' Case 12 : '周波数[00,000,0X0]位置の減算。 Frequency = Frequency - 10 Gosub Freqchg '出力周波数を変更する。 ' Case 13 : '周波数[00,000,00X]位置の減算。 Frequency = Frequency - 1 Gosub Freqchg '出力周波数を変更する。 ' Case 15 : '[C]周波数の下位3桁クリア処理。 Frequency = Frequency / 1000 Frequency = Frequency * 1000 Gosub Freqchg '出力周波数を変更する。 ' Case 16 : '設定周波数のメモリー操作。 Eepfreq2 = Frequency '現在の周波数を[Ch.2]のEEPROMに記憶する。 End Select ' End Select Gosub Curdisp 'LCDに設定カーソルを表示する。 Keydata = 0 'キー(スイッチ)の入力をクリアする。 Goto Main '################################################################################################## ' ' ***************************************** ' * LCDに設定周波数を表示するサブルーチン * (Frequency = 周波数値) ' ***************************************** ' Freqdisp: Locate 1 , 4 Tempstr = Str(frequency) '周波数を文字列に変換する。 Temp1 = Len(tempstr) '文字列の桁数を調べる。 Select Case Temp1 Case Is < 4 : '[3桁以下の場合] Lcd Spc(7); Lcd Format(tempstr , " ") '下位3桁を表示する。 Case Is < 7 : '[6桁以下の場合] Lcd Spc(3); Temp2 = Temp1 - 3 '上位3桁を表示する。 Tempstr2 = Left(tempstr , Temp2) Lcd Format(tempstr2 , " "); Tempstr2 = Right(tempstr , 3) '下位3桁を表示する。 Lcd "," ; Tempstr2 Case Else : '[7桁以上の場合] Temp2 = Temp1 - 6 '上位2桁を表示する。 Tempstr2 = Left(tempstr , Temp2) Lcd Format(tempstr2 , " "); Temp2 = Temp1 - 5 '中間の3桁を表示する。 Tempstr2 = Mid(tempstr , Temp2 , 3) Lcd "," ; Tempstr2; Tempstr2 = Right(tempstr , 3) '下位3桁を表示する。 Lcd "," ; Tempstr2 End Select Return ' ' *************************************** ' * LCDに設定項目を表示するサブルーチン * ' *************************************** ' Modedisp: Locate 1 , 1 If Channel = 0 Then 'If 出力チャンネルが[Ch.1]か? Then Lcd "1" Else '[Ch.2]の場合。 Lcd "2" End If ' Select Case Waveselect '出力波形を表示する。 Case 0 : Lcd Chr(1) '正弦波の場合。 Case 1 : Lcd Chr(2) '三角波の場合。 Case 2 : Lcd Chr(3) '方形波の場合。 End Select Return ' ' ******************************************* ' * LCDに設定カーソルを表示するサブルーチン * ' ******************************************* ' Curdisp: If Curx < 14 Then 'If 設定カーソルが[c][M]以外か? Then Locate 2 , Curx Lcd Chr(0) '[上下矢印]を表示する。 End If ' Locate 2 , Curx Return ' ' ************************************ ' * 出力周波数を変更するサブルーチン * ' ************************************ ' Freqchg: If Frequency > 12499999 Then 'If 動作周波数の上限か? Then Frequency = 12499999 '上限値に設定する。 End If ' If Frequency < 0 Then 'If 動作周波数の下限か? Then Frequency = 0 '下限値に設定する。 End If ' If Channel = 0 Then 'If 出力チャンネルが[Ch.1]か? Then Freq1 = Frequency Else '[Ch.2]の場合。 Freq2 = Frequency End If ' Gosub Freqdisp 'LCDに設定周波数を表示する。 Gosub Freqset 'DDSの[FREQ0]レジスタに周波数データを送信する。 Return '================================================================================================== ' ' ************************************************************ ' * DDSの[FREQ0]レジスタに周波数データを送信するサブルーチン * (Frequency = 周波数値) ' * (AD9833 25MHz) * ' ************************************************************ ' Freqset: Tempw1 = Ddscontreg 'DDSのコントロール・レジスタに[RESET]を送信する。 Set Tempw1.8 '[D8=1] RESET = 1 Gosub Ddsset 'DDSにワード・データを送信する。 ' Temps1 = Frequency / 25000000 '[FREQ0] REG = Fout0 / fMCLK * 2^28 Temps1 = Temps1 * 268435456 Templ1 = Temps1 ' Tempw1 = Templ1 '[FREQ0]レジスタの下位14ビットを送信する。 Reset Tempw1.15 '[D15=0] Set Tempw1.14 '[D14=1] Gosub Ddsset 'DDSにワード・データを送信する。 ' Shift Templ1 , Left , 2 '[FREQ0]レジスタの上位14ビットを送信する。 Tempw1 = Highw(templ1) Reset Tempw1.15 '[D15=0] Set Tempw1.14 '[D14=1] Gosub Ddsset 'DDSにワード・データを送信する。 ' Tempw1 = Ddscontreg 'DDSのコントロール・レジスタに[RESET]解除を送信する。 Gosub Ddsset 'DDSにワード・データを送信する。 Return ' ' *************************************** ' * DDSに出力波形を送信するサブルーチン * (Waveselect = 0:正弦波, 1:三角波, 2:方形波) ' *************************************** ' Waveset: Ddscontreg = &B0010_0000_0000_1000 'DDSのコントロール・レジスタ値。 ' Select Case Waveselect '出力波形を設定する。 Case 0: '正弦波の場合。 Reset Ddscontreg.5 '[D5=0] OPBITEN = 0 Reset Ddscontreg.1 '[D1=0] MODE = 0 Case 1: '三角波の場合。 Reset Ddscontreg.5 '[D5=0] OPBITEN = 0 Set Ddscontreg.1 '[D1=1] MODE = 1 Case 2: '方形波の場合。 Set Ddscontreg.5 '[D5=1] OPBITEN = 1 Reset Ddscontreg.1 '[D1=0] MODE = 0 End Select ' Tempw1 = Ddscontreg Gosub Ddsset 'DDSにワード・データを送信する。 Return ' ' ********************************************* ' * DDSにワード・データを送信するサブルーチン * (Tempw1 = 送信データ) ' ********************************************* ' Ddsset: Reset Dds_fsync 'DDSの[FSYNC]を[L]にする。 Shiftout Dds_sdata , Dds_sclk , Tempw1 , 0 , 16 Set Dds_fsync 'DDSの[FSYNC]を[H]にする。 Return '================================================================================================== ' ' *********************************************************** メイン・ルーチンで定期的に呼び続けること。 ' * キー(スイッチ)を検出するサブルーチン (抵抗値のA/D変換) * Keydata = キー(スイッチ)の入力データ。(押された場合にコードが入る) ' *********************************************************** Keyadcode = キー(スイッチ)をA/D変換したコード。(押されている状態のコードが入る) ' (0:押されていない, 1:[SELECT] , 2:[LEFT], 3:[DOWN], 4:[UP], 5:[RIGHT]キー) Getkey: Gosub Keyadconv 'キー(スイッチ)の分圧抵抗値をA/D変換する。 If Keyadcode <> 0 Then 'If いずれかのキーが押されているか? Then If Keystat = 0 Then 'If キー入力の検出中か? Then Waitms 30 'チャタリングを除去する待ち時間。 Gosub Keyadconv 'キー(スイッチ)の分圧抵抗値をA/D変換する。 If Keyadcode <> 0 Then 'If いずれかのキーが押されているか? Then Keydata = Keyadcode 'キーが押されたことを通知する。 Keystat = 1 'キーの解放待ちにする。 End If End If Else 'キーが押されていない場合。 If Keystat <> 0 Then 'If キーの解放待ちか? Then Waitms 30 'チャタリングを除去する待ち時間。 Gosub Keyadconv 'キー(スイッチ)の分圧抵抗値をA/D変換する。 If Keyadcode = 0 Then 'If キーが離されているか? Then Keystat = 0 'キー入力の検出中にする。 End If End If End If Return ' ' * キー(スイッチ)の分圧抵抗値をA/D変換するサブルーチン * ' Keyadconv: Keyw1 = Getadc(0) 'キー(スイッチ)の分圧抵抗値をA/D変換する。 #if Board_version = 10 'If DFROBOT社のボード・バージョンが1.0か? Then Select Case Keyw1 '分圧抵抗のA/D値から押されたキーを判別する。 Case Is > 950 : Keyadcode = 0 'キーが押されていない場合。 Case Is < 50 : Keyadcode = 5 '[RIGHT] キー。 Case Is < 195 : Keyadcode = 4 '[UP] キー。 Case Is < 380 : Keyadcode = 3 '[DOWN] キー。 Case Is < 555 : Keyadcode = 2 '[LEFT] キー。 Case Else : Keyadcode = 1 '[SELECT] キー。 End Select #else 'DFROBOT社のボード・バージョンが1.1の場合。 Select Case Keyw1 '分圧抵抗のA/D値から押されたキーを判別する。 Case Is > 950 : Keyadcode = 0 'キーが押されていない場合。 Case Is < 50 : Keyadcode = 5 '[RIGHT] キー。 Case Is < 250 : Keyadcode = 4 '[UP] キー。 Case Is < 450 : Keyadcode = 3 '[DOWN] キー。 Case Is < 650 : Keyadcode = 2 '[LEFT] キー。 Case Else : Keyadcode = 1 '[SELECT] キー。 End Select #endif Return ' ' End