/************************************************************************* * easy_fra_v4 プログラム * * <easy_fra_v3からの、変更点> * @ DDS部と、LOG AMP+AD変換(PIC内部)を一体化する。 * A MPUを、dsPIC33FJ64GP802から、PIC24FJ64GA004に変更する。 * B CAL/MESモード切替スライドSWを追加し、各モード毎のループ処理を行う。 *   START SW 読込み待ちから開始し、各処理に分岐。 *   中断は、RESET SWによる簡単なものにする。 *   尚、START SW 読込み待ちの間に、STEP SWが押されたら、メインループ頭の *   モード切替SW読込み処理に戻る。(STEP SWを、MAIN RET SWと兼用) * * 2.4インチ・カラーQVGA液晶モジュール(aitendo): UL024TF * DDSモジュール:GAOHOU_AD9833 * * Condition: * 8MHz Internal RC oscillator, 4x PLL (8MHzx4= 32MHz) * Fcy=32MHz/2=16MHz, Tcy=62.5ns * * MPU: 、PIC24FJ64GA004 *    ・フラッシュ:64kバイト(PIC24F・・・002も同じ。) *    ・RAM:8kバイト(PIC24F・・・002も同じ。) * * 初期作成日: N.Ishii 2018.11.25 * N.Ishii 2018.12.23 **************************************************************************/ #include "p24FJ64GA004.h" #include "colorlcd_libPIC24FVH_v2.h" #include // Set Configuration Word 1 _CONFIG1 ( JTAGEN_OFF & // JTAG Port: OFF GCP_OFF & // Code Protect: OFF GWRP_OFF & // Write Protect:OFF BKBUG_OFF & // Background Debug: OFF COE_OFF & // Clip On Emulation: OFF ICS_PGx1 & // Select ICD Pin: EMUC/EMUD-> PGC1/PGD1 For Common Use FWDTEN_OFF // WDT: OFF ) // Set Configuration Word 2 _CONFIG2 ( IESO_OFF & // 2 Speed Start Up: OFF FNOSC_FRCPLL & // 8MHz Internal RC oscillator, 4x PLL-> 8MHzx4=32MHz FCKSM_CSDCMD & // Change Clock Control: OFF Clock Monitor: OFF OSCIOFNC_ON & // OSCO/RA3 function: Used RA3(外部OSCを使う時は、OSCIOFNC_OFFと記述) IOL1WAY_OFF & // RP Register Protection: Unlimited Writes To RP Registers I2C1SEL_PRI & // I2C1 pins Select: Use Primary I2C1 pins POSCMOD_NONE // Oscillator Selection: Primary disabled ) #define MoveRightCur_SW PORTCbits.RC3 #define MoveLeftCur_SW PORTCbits.RC4 #define START_SW PORTCbits.RC7 // 181217 #define STEP_SW PORTCbits.RC2 #define MODE_SW PORTCbits.RC6 #define LED PORTBbits.RB2 /// ロータリエンコーダー #define RE_A PORTCbits.RC0 #define RE_B PORTCbits.RC1 /// DDSコントロールポート定義 #define DDS_FSYNC LATAbits.LATA10 // AD9833 FSYNC #define DDS_SCLK LATAbits.LATA8 // AD9833 SCLK #define DDS_SDATA LATAbits.LATA9 // AD9833 SDATA /// メッセージ・テーブル char str_MODE1[] = "CAL MODE START"; char str_MODE2[] = "MES MODE START"; char str_WAIT[] = "WAIT START SW ON"; char str_Hz1[] = "Hz(FRQ)"; char str_Hz2[] = "Hz(STEP)"; // 計測画面用 char str_xHz[] = "xxxxxxHz"; char str_xdB[] = "xx.xxdB"; /// A Variable (Global) unsigned long FrqSet= 1000; unsigned long StepSet= 1; char ChangeFlag= 0; char SwCount= 1; char EndFlag= 0; // 画面の描画終了フラグ char MainRetFlag= 0; int x= 0; // 周波数軸のX座標 int y; // dB軸のY座標 int Xcur= 0; // カーソル座標 int Ycur= 224; int X_log; int X_log_temp; int x_temp; int y_temp; unsigned long fx; float db; /// 計測値バッファ float Buffer_db[181]; // 各周波数の、dB値が格納されている。 char Buffer_pol[181]; // dB値の極性が格納されている。0:なし、1:+、-1:− /// スイープ機能用変数 unsigned long F_Start= 10; unsigned int F_Step= 2; int Step_Count; /// Function Prottypes void DDS_SCAN(void); // CAL用 void DdsSweep_And_DrawFRA(void); void AxisDraw_CAL(void); void AxisDraw_MES(void); void dds_dataset(unsigned long data, unsigned int bt); void freq_to_serial(unsigned long f); void ltostring(char digit, unsigned long data, char *buffer); void ftostring(long seisu, long shousu, float data, char *buffer); /**************************************************************** * 割込み処理関数(RE_A状態変化割込み) * A相の立下りを基準に、B相のレベルを読込んで回転方向を判断 * *<説明> * 電源ON時に、何もしなくてもRE出力が、立上る(両接点オープン時) * ことがあるので、A相の立上りで割込みが入ってしまう。 * 電源ON時に、何もしなくてもRE出力が、Lo(両接点クローズ時) * の場合は、立下がることはないので余分な割込みは入らない。 * そのために、A相の立下りを基準に、判断している。 *****************************************************************/ void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void) { IFS1bits.CNIF = 0; // Clear CN Interrupt Flag /// RE読込み delay_ms(5); if (!RE_A) { // A相の割込みが入った時、A相が、Loか?(つまり立下りか?) if(RE_B) { // 時計回り(B相が、Hi)だったら、インクリメント FrqSet += StepSet; if(FrqSet > 10000000) FrqSet= 10000000; } else { /// 反時計回り(B相が、Lo)だったら、ディクリメント FrqSet -= StepSet; if(FrqSet < StepSet) FrqSet= StepSet; } ChangeFlag= 1; } } /************************************************ * Function Main ************************************************/ int main(void){ CLKDIV= 0; // クロック分周 1:1 AD1PCFG= 0xFFFE; // ANO以外は、ディジタルに指定 /// ポートの入出力モード設定 TRISA = 0xF8EF; // **** // *RA10:0_FSYNC, RA9:SDATA_ RA8:0_SCLK // RA7:1_未使用, **RA4:0_RST/ // RA3:1_未使用, RA2:1_未使用, RA1:1_未使用, RA0:1_AN0 TRISB = 0x001B; // RB15-12:0_DB7-4 // RB11-8:0_DB3-0 // RB7:0_WR/, RB6:0_RS, RB5:0_CS/, RB4:1_未使用 // RB3:1_未使用, RB2:0_LED, RB1:1_PGC, RB0:1_PGD TRISC = 0xFFFF; // **** // **RC9:1_未使用, RC8:1_未使用 // RC7:1_START_SW, RC6:1_MODE_SW, RC5:1_未使用, RC4:1_LEFT_SW // RC3:1_RIGHT_SW, RC2:1_STEP_SW, RC1:1_RE-B, RC0:1_RE-A /// LED消灯 LED= 0; // 赤 /// 内部プルアップ設定 CNPU1= 0x0700; // CN10(RC2):STEP_SW, CN9(RC1):RE-B, CN8(RC0):RE-A CNPU2= 0x1206; // CN28(RC3):RIGHT_SW, CN25(RC4):LEFT_SW, CN18(RC6):MODE_SW, CN17(RC7):START_SW /// 状態変化割込み設定 CNEN1 = 0x100; // Valid RE-A:CN8→ b8 IPC4bits.CNIP = 5; /// DDS初期化の前に、MCLKが安定するまでの待機時間を追加 delay_ms(100); /// DDS制御信号レベル初期化と、DDSリセットコマンド転送 DDS_FSYNC= 1; // FSYNC(CS)は、アクティブローなので、待機時は、'1' DDS_SCLK= 1; // AD9834は、立下りエッジ読込みなので、待機時は、'1' DDS_SDATA= 0; // DATAは、'0'待機 /// DDS RESET dds_dataset(0x0100, 16); // RESET ON freq_to_serial(1000); // デフォルトDDS出力= 1000Hz /// Initialize ADC AD1CON1= 0x0000; // SAMP bit= 0 ends sampling... and starts converting(手動AD変換) AD1CHS= 0x0000; // Connect AN0 as CH0 input AD1CSSL= 0x0000; // 自動スキャンしない AD1CON3= 0x0002; // 手動サンプル、Tad= internal 2Tcy AD1CON2= 0x0000; // Vref=AVdd-AVss,入力スキャンしない、CH0を変換 AD1CON1bits.ADON = 1; // ADC Start /// QVGA初期化 lcd_Init(); /// Main Loop while(1){ if(!MODE_SW) { /// CAL(DDS) MODE(CAL時:IN-OUT 折り返し/ DDS時:OUTのみ使用) lcd_Clear(BLACK); lcd_Str(0, 0, str_MODE1, CYAN, BLACK); // "CAL MODE START" delay_ms(1000); lcd_Clear(BLACK); IEC1bits.CNIE = 1; //Enable SW INT /// DDS初期画面表示:FRQ:1000Hz/ STEP:1Hz Draw7seg(0, 4, 1000, 8, WHITE, BLACK); // 周波数設定値 lcd_Str(12, 1, str_Hz1, WHITE, BLACK); // "Hz (FRQ)" Draw7seg(126, 36, 1, 1, GREEN, BLACK); // ステップ設定値 lcd_Str(12, 3, str_Hz2, GREEN, BLACK); // "Hz (STEP)" do { /// STEP SW 読込み delay_ms(10); // チャッタ回避 if(!STEP_SW) { ++SwCount; if(SwCount > 7) SwCount= 1; Draw7seg(18, 36, 8888888, 7, BLACK, BLACK); // ステップ表示前に、7桁分の表示エリアクリア switch(SwCount){ case 1: StepSet= 1; Draw7seg(126, 36, 1, 1, GREEN, BLACK); break; case 2: StepSet= 10; Draw7seg(108, 36, 10, 2, GREEN, BLACK); break; case 3: StepSet= 100; Draw7seg(90, 36, 100, 3, GREEN, BLACK); break; case 4: StepSet= 1000; Draw7seg(72, 36, 1000, 4, GREEN, BLACK); break; case 5: StepSet= 10000; Draw7seg(54, 36, 10000, 5, GREEN, BLACK); break; case 6: StepSet= 100000; Draw7seg(36, 36, 100000, 6, GREEN, BLACK); break; case 7: StepSet= 1000000; Draw7seg(18, 36, 1000000, 7, GREEN, BLACK); break; default:; break; } while(!STEP_SW); // SWリリース待ち(Hiになるまで待つ) } if(ChangeFlag) { /// DDS出力 freq_to_serial(FrqSet); /// 変数FrqSetの値を、液晶に表示 Draw7seg(0, 4, FrqSet, 8, WHITE, BLACK); ChangeFlag= 0; } }while(START_SW); // Start SW ON 待ち(ONするまで上記を繰返す-> DDSモード) // この後、CALする時は、基本、Fc/10の周波数に合わせる。 while(1) { DDS_SCAN(); // DDS SCAN動作開始〜終了 RESET SWで中断 do { delay_ms(5); // チャッタ回避 /// STEP_SWを、MAIN RET SWと兼用→ 押されたらフラグをセットして、このループを抜ける。 if(!STEP_SW) { MainRetFlag= 1; break; } }while(START_SW); // Start SW ON 待ち /// SW ON待機中に、STEP SWが押されたら、この関数のループを抜け、メインループの頭に戻る。 /// 尚、CALモード中の中断は、RESET SWを押す。 if(MainRetFlag) { MainRetFlag= 0; break; } } } else { /// MESモード while(1) { lcd_Clear(BLACK); lcd_Str(0, 0, str_MODE2, CYAN, BLACK); // "MES MODE START" lcd_Str(0, 1, str_WAIT, CYAN, BLACK); // "WAIT START SW ON" do { delay_ms(5); // チャッタ回避 /// STEP_SWを、MAIN RET SWと兼用→ 押されたらフラグをセットして、このループを抜ける。 if(!STEP_SW) { MainRetFlag= 1; break; } }while(START_SW); // Start SW ON 待ち /// SW ON待機中に、STEP SWが押されたら、whileループを抜け、メインループの頭に戻る。 /// 尚、MESモード中の中断は、RESET SWを押す。 if(MainRetFlag) { MainRetFlag= 0; /// STEP SWによる、MESから、CAL移行時、MES終了後の、F出力=100kになっているので、デフォルトDDS出力= 1000Hz /// に初期化    181222 freq_to_serial(1000); // デフォルトDDS出力= 1000Hz break; } DdsSweep_And_DrawFRA(); // 押されなければ、測定モード実行 } } } } /****************************************** * DDS SCAN (CAL動作用) *******************************************/ void DDS_SCAN(void){ IEC1bits.CNIE = 0; // Desable SW INT AxisDraw_CAL(); // 座標表示(CAL用) lcd_Str(0, 0, "CAL START", WHITE, BLACK); ltostring(6, FrqSet, str_xHz); // バイナリ→ 文字列変換 lcd_Str(18, 2, str_xHz, WHITE, BLACK); // 周波数表示 /// 181回、x座標をずらしながら、サンプル→ 変換→ ドット描画を繰返し、 /// 1画面分のグラフを描画 for(x= 0; x < 181; ++x) { AD1CON1bits.SAMP= 1; // サンプリング開始 delay_ms(100); // 確実なサンプルを確保するための時間 AD1CON1bits.SAMP= 0; // AD変換開始 while(!AD1CON1bits.DONE); // AD変換終了待ち /// 変換値をドット描画の、Y座標(レベル)に変換、そこにドット描画する。 y= (ADC1BUF0)*5/22; // ADC1BUF0)*5/22は、数学的なy座標になる→ 下が0で上に行くほど増える) if(x == 0) lcd_Pixel(x,239-y,WHITE); // 最初は無条件でドット描画 else { // 2回目からは、ライン描画 lcd_Line(x_temp, y_temp, x, y, WHITE); } /// 現在の座標データを、テンポラリに退避(次回描画時の始点座標になる) x_temp= x; y_temp= y; /// dB値を求め、液晶に表示する。 if(y == 177) { // 0db db= 0; lcd_Char(18, 3, 0x20, WHITE, BLACK); // 極性部をブランク表示にする。 } if(y < 177) { // −dB領域 db= (177-y)*0.25; lcd_Char(18, 3, 0x2D, WHITE, BLACK); // '-'表示 } if(y > 177) { // +dB領域 db= (y-177)*0.25; lcd_Char(18, 3, 0x2B, WHITE, BLACK); // '+'表示 } ftostring(2, 2, db, str_xdB); // 浮動小数点→ 文字列変換 lcd_Str(19, 3, str_xdB, WHITE, BLACK); // dB表示 delay_ms(900); } lcd_Str(0, 0, "CAL END ", WHITE, BLACK); /// CAL ENDから、MODE SWを、MES側に切替え、STEP SWでを押すと、再び、MODE SW読込みに戻り /// MESモードに移行。ここから、MESモードをスタートさせた時、以下の初期化が抜けていると、スイープ中の /// 周波数表示ステップが、おかしくなる。また、ドットも座標外になって表示しなくなる。 181222 x= 0; // スイープ中の、周波数値を求める時、使っている、座標変数:xを初期化 181222 } /************************************************* * DDS SWEEP (MES動作用)しながら、F特グラフ描画 **************************************************/ void DdsSweep_And_DrawFRA(void){ IEC1bits.CNIE = 0; // Desable SW INT fx= 8; Xcur= 0; AxisDraw_MES(); // 座標表示 while(F_Start != 100000) { /// スイープ中だったら実行(1つ手前の、98000Hzまで実行) /// 各周波数帯での、DDSステップ出力 for(Step_Count= 0; Step_Count < 45; ++Step_Count) { freq_to_serial(F_Start); // 初回10Hz・次の、F出力(12, 14, 16・・・) /// スイープ中の、周波数値を表示する。 ltostring(6, F_Start, str_xHz); // バイナリ→ 文字列変換 lcd_Str(18, 2, str_xHz, WHITE, BLACK); // 周波数表示 /// サンプリング開始〜ドット描画 AD1CON1bits.SAMP= 1; // サンプリング開始 delay_ms(100); // 確実なサンプルを確保するための時間 AD1CON1bits.SAMP= 0; // AD変換開始 while(!AD1CON1bits.DONE); // AD変換終了待ち //// 変換値をドット描画の、Y座標(レベル)に変換、そこにドット描画する。 y= (ADC1BUF0)*5/22; // ADC1BUF0)*5/22は、数学的なy座標になる→ 下が0で上に行くほど増える) /// スイープ中の、周波数値を求める。 181218 抜けていたので追加 if(x <= 45) fx += 2; if((x >= 46) && (x <= 90)) fx += 20; if((x >= 91) && (x <= 135)) fx += 200; if((x >= 136) && (x <= 180)) fx += 2000; X_log= (int)((log10(fx)-1)*45);// x座標をログ座標に変換 if(x == 0) lcd_Pixel(x,239-y,WHITE); // 最初は無条件でドット描画 else { // 2回目からは、ライン描画 lcd_Line(X_log_temp, y_temp, X_log, y, WHITE); } /// 現在の座標データを、テンポラリに退避(次回描画時の始点座標になる) X_log_temp= X_log; y_temp= y; /// dB値を求め、液晶に表示する。 if(y == 177) { // 0db db= 0; lcd_Char(18, 3, 0x20, WHITE, BLACK); // 極性部をブランク表示にする。 Buffer_pol[x]= 0; // 計測バッファに極性を格納 } if(y < 177) { // −dB領域 db= (177-y)*0.25; lcd_Char(18, 3, 0x2D, WHITE, BLACK); // '-'表示 Buffer_pol[x]= -1; } if(y > 177) { // +dB領域 db= (y-177)*0.25; lcd_Char(18, 3, 0x2B, WHITE, BLACK); // '+'表示 Buffer_pol[x]= 1; } ftostring(2, 2, db, str_xdB); // 浮動小数点→ 文字列変換 lcd_Str(19, 3, str_xdB, WHITE, BLACK); // dB表示 Buffer_db[x]= db; // 計測バッファに、dB値を格納 /// -3dBポイントを検出したら、その時の周波数を別ロケーションに表示する。 if((y < 177) && (db == 3.00)) { // −3.00dB検知 ltostring(6, F_Start, str_xHz); // バイナリ→ 文字列変換 lcd_Str(18, 7, str_xHz, YELLOW, BLACK); // 周波数表示 lcd_Str(18, 8, "- 3.00dB", YELLOW, BLACK); // -3dB表示 } delay_ms(900); F_Start += F_Step; ++x; } F_Step *= 10; // 次の周波数帯の、ステップ数セット(20, 200, 2000) } /// 最終周波数:100000Hzを表示する。 181218 ltostring(6, F_Start, str_xHz); // バイナリ→ 文字列変換 lcd_Str(18, 2, str_xHz, WHITE, BLACK); // 周波数表示 freq_to_serial(F_Start); // 最終周波数:100000Hz出力(100kHz出力のままでよい。) /// スイープが終了したら、開始周波数とステップ数を初期化 181218 F_Start= 10; F_Step= 2; /// カーソル移動による計測モードの開始 do { delay_ms(100); // スイッチ安定待ち ※ レベルとエッジ検知を共用する為、長めに設定 if((!MoveRightCur_SW) || (!MoveLeftCur_SW)) { /// 移動する前に現在位置のカーソルを背景色と同じ黒で塗りつぶす(消すと同じ) X_log= (int)((log10(fx)-1)*45);// Xcur座標をログ座標に変換 lcd_Line(X_log, Ycur, X_log, 219, BLACK); /// カーソル移動処理 if (!MoveRightCur_SW) { Xcur++; /// 周波数値を求める。 if(Xcur <= 45) fx += 2; if((Xcur >= 46) && (Xcur <= 90)) fx += 20; if((Xcur >= 91) && (Xcur <= 135)) fx += 200; if((Xcur >= 136) && (Xcur <= 180)) fx += 2000; if (Xcur == 181) { Xcur= 180; fx= 100000; } } if (!MoveLeftCur_SW) { Xcur--; /// 周波数値を求める。 if(Xcur <= 44) fx -= 2; if((Xcur >= 45) && (Xcur <= 89)) fx -= 20; if((Xcur >= 90) && (Xcur <= 134)) fx -= 200; if((Xcur >= 135) && (Xcur <= 179)) fx -= 2000; if (Xcur == -1) { Xcur= 0; fx= 10; } } /// ログ移動した位置にカーソルを描画する X_log= (int)((log10(fx)-1)*45);// Xcur座標をログ座標に変換 lcd_Line(X_log, Ycur, X_log, 219, CYAN); /// dB値を求め、液晶に表示する。 if(Buffer_pol[Xcur] == 0) lcd_Char(18, 14, 0x20, CYAN, BLACK); // 極性部をブランク表示にする。 if(Buffer_pol[Xcur] == 1) lcd_Char(18, 14, 0x2B, CYAN, BLACK); // '+'表示 if(Buffer_pol[Xcur] == -1) lcd_Char(18, 14, 0x2D, CYAN, BLACK); // '-'表示 ftostring(2, 2, Buffer_db[Xcur], str_xdB); // 浮動小数点→ 文字列変換 lcd_Str(19, 14, str_xdB, CYAN, BLACK); // dB表示 /// 周波数値を液晶に表示する。 ltostring(6, fx, str_xHz); // バイナリ→ 文字列変換 lcd_Str(18, 13, str_xHz, CYAN, BLACK); // 周波数表示 } }while(START_SW); // START SW ONで抜け、再び、START SW ON待ち画面に戻る。それまでは繰返す。 x= 0; } /****************************************** * Drawing Coordinate Axis MESモード用 *******************************************/ void AxisDraw_MES(void){ int i; lcd_Clear(BLACK); // X、Y座標軸表示 for(i=0; i<181; i+=45) lcd_Line(i, 17, i, 217, GREEN); // X axis for(i=17; i<218; i+=40) lcd_Line(0, i, 180, i, GREEN); // Y axis lcd_Str(0, 16, "10", CYAN, BLACK); // 10 lcd_Str(3, 16, "100", CYAN, BLACK); // 100 lcd_Str(7, 16, "1k", CYAN, BLACK); // 1k lcd_Str(10,16, "10k", CYAN, BLACK); // 10k lcd_Str(14,16, "100kHz", CYAN, BLACK); // 100kHz lcd_Str(15, 0, "+10dB", CYAN, BLACK); // +10dB lcd_Str(15, 3, "0", CYAN, BLACK); // 0 lcd_Str(15, 6, "-10", CYAN, BLACK); // -10 lcd_Str(15, 9, "-20", CYAN, BLACK); // -20 lcd_Str(15, 12, "-30", CYAN, BLACK); // -30 lcd_Str(15, 15, "-40", CYAN, BLACK); // -40 } /****************************************** * Drawing Coordinate Axis CALモード用 *******************************************/ void AxisDraw_CAL(void){ int i; lcd_Clear(BLACK); // X、Y座標軸表示 lcd_Line(0, 17, 0, 217, GREEN); // X axis lcd_Line(180, 17, 180, 217, GREEN); // X axis for(i=17; i<218; i+=40) lcd_Line(0, i, 180, i, GREEN); // Y axis lcd_Str(15, 0, "+10dB", CYAN, BLACK); // +10dB lcd_Str(15, 3, "0", CYAN, BLACK); // 0 lcd_Str(15, 6, "-10", CYAN, BLACK); // -10 lcd_Str(15, 9, "-20", CYAN, BLACK); // -20 lcd_Str(15, 12, "-30", CYAN, BLACK); // -30 lcd_Str(15, 15, "-40", CYAN, BLACK); // -40 } /************************************************************************** * serial data send (MSB first) * 16ビット(bt=16で指定)SPI転送 * AD9833は、SCLKの立下りエッジでデータを読込む (規格:SCLK=40MHzmax) ****************************************************************************/ void dds_dataset(unsigned long data, unsigned int bt) { unsigned int i; DDS_FSYNC = 0; for(i = bt; i > 0 ; i--) { DDS_SDATA = (data >> (i - 1)) & 0x00000001; DDS_SCLK = 0; DDS_SCLK = 1; } DDS_FSYNC = 1; } /******************************************************************** * AD9833 DDS control (frequency to serial code) * 希望の出力周波数:fから、シリアルコードを算出し、シリアル転送する。 *********************************************************************/ void freq_to_serial(unsigned long f) { unsigned long msb, lsb; unsigned long data; data = (unsigned long)(((float)f) / (25000000.0 / (1024.0*1024.0*256.0))); // Fmclk/2^28をフロートで計算し、結果を32bit整数型にキャスト msb = (data >> 14) + 0x4000; // 上位14bit送信データ+4000H(周波数レジスタアドレス指定(b15=0.b14=1):FREQ0レジ)を、msbにセット lsb = (data & 0x00003fff) + 0x4000;// 下位14bit送信データ+4000H(周波数レジスタアドレス指定(b15=0.b14=1):FREQ0レジ)を、lsbにセット dds_dataset(0x2000, 16); //// 制御ビットへの書込み(b15=0.b14=0) /// b13:B28='1':2つの連続した16bit転送で完全なコントロールワードをロード /// 以下の、b8,5,1=0 設定でサイン波出力 // b8:RESET='0':解除 // b5:OPBITEN='0':DACが、VOUTに接続される // b3:DIV2='0':OPBITEN='0'の時は、このビットは関係なくなる // b1:MODE='0':上記条件の場合、サイン波出力(b1:MODE='1'で、三角波出力) // dds_dataset(0x2028, 16); // 矩形波出力:DACデータのMSB出力確認のため dds_dataset(lsb, 16); // lsb転送(下位14ビットの周波数レジスタ0のデータを、b15,14のコントロールビットと共に転送) dds_dataset(msb, 16); // msb転送(上位14ビットの周波数レジスタ0のデータを、b15,14のコントロールビットと共に転送) dds_dataset(0xC000, 16); // 位相レジスタ初期化:0 } /******************************************************** * Numerical Value-> Ascci Convert (long) *********************************************************/ void ltostring(char digit, unsigned long data, char *buffer) { char i; buffer += digit; // To Last of Strings for(i=digit; i>0; i--) { // From LS. Digit To MS. Digit buffer--; *buffer = (data % 10) + '0'; // This Digit Value-> Ascii Convert ('0'=0x30)-> Store Buffer data = data / 10; // Digit-1 } /// ブランキング処理 i = 0; // buffer++; while((i < digit-1)&&(*buffer == '0')) // 上位桁が0の間 { *buffer = ' '; // ブランクに変換 buffer++; i++; } } /**************************************** * Floatから文字列へ変換 *  合計有効桁は8桁以下とすること ****************************************/ void ftostring(long seisu, long shousu, float data, char *buffer) { long i; long dumy; if(shousu != 0) //小数部桁ありか buffer += seisu+shousu+1; //全体桁数+小数点 else //小数部桁なしのとき buffer += seisu + shousu; //全体桁数のみ buffer--; //配列ポインタ-1 for(i=0; i0; i--) { //小数桁数分繰り返し *buffer =(dumy % 10)+'0'; //数値を文字に変換格納 buffer--; //格納場所下位から上位へ dumy /= 10; //次の桁へ } if(shousu != 0) { //小数桁0なら小数点なし *buffer = '.'; //小数点を格納 buffer--; //ポインタ-1 } for(i=seisu; i>0; i--) { //整数桁分繰り返し *buffer = (dumy % 10)+'0'; //数値を文字に変換格納 buffer--; //ポインタ-1 dumy /= 10; //次の桁へ } /* i = 0; // ブランキング処理 buffer++; while((i