/************************************************************************* * easy_fra_v2a プログラム(Step_3) * * <ハード概要> * 周波数スイープとして、自作の「PIC18F_DDS_AF_OSC_V2a」を使用する。 * ログアンプを使用。縦軸は、dB軸とする。 * * 2.4インチ・カラーQVGA液晶モジュール(aitendo): UL024TF * * <v2からの、追加機能> * @ dB値の、リアル表示を行う。 *  Fスイープの都度、その時のレベルを、dBで液晶に表示して行く。 *  但し、前の表示は残さないで上書きでよい。 *  よってスイープ終了後は、100kHzに於けるdB値を表示していることになる。 * A スイープ中の、周波数表示を行う。 * B スイープ中に検出された、-3dBポイントの周波数表示を行う。 * * Condition: * 8MHz External X'tal Oscillator, 10x PLL (8MHzx10= 80MHz) * Fcy=80MHz/2=40MHz, Tcy=25ns * * MPU: dsPIC33FJ64GP802 * * N.Ishii 2016.2.11 **************************************************************************/ #include "p33FJ64GP802.h" #include "colorlcd_libdsPICVH.h" /// コンフィギュレーション設定 80MH _FOSCSEL(FNOSC_PRIPLL & IESO_OFF); // Prim OSC _FOSC(FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_XT); _FWDT(FWDTEN_OFF); _FPOR(ALTI2C_OFF & FPWRT_PWR32); _FICD(JTAGEN_OFF & ICS_PGD1); /// メッセージ・テーブル char MsgData1[] = "xxxxxxHz"; char MsgData2[] = "xx.xxdB"; /// A Variable (Global) char sync_m0; // NEWテンポラリ char sync_m1; // OLDテンポラリ char sync_m2; // EDGEテンポラリ int x,y; unsigned long fx; float db; /// Function Prottypes void AxisDraw(void); void ltostring(char digit, unsigned long data, char *buffer); void ftostring(long seisu, long shousu, float data, char *buffer); /************************************************ * Function Main ************************************************/ int main(void){ /* Initialize Clock */ CLKDIVbits.PLLPRE = 0; // PLLPRE=1/2 to 4MHz PLLFBDbits.PLLDIV = 40; // PLLDIV=1/40 to 160MHz CLKDIVbits.PLLPOST = 0; // PLLPOST=1/2 to 80MHz then 40MIPS /* Initialize Clock */ OSCCON = 0x00300; // PRIPLL指定 CLKDIV = 0x0100; // クロックの分周1:2に設定 PLLFBD = 0x0026; // 40倍 8MHz÷2×40÷2 = 80MHz /* Initialize Port */ AD1PCFGL = 0xFFFA; // AN0,2 are Analog(AN1は、RA1のデジタル入力(スイープ同期信号入力)として使用) TRISA = 0x000F; // RA4 is Out, Other is Input TRISB = 0x000F; // Set QVGA Port Direction CNPU1 = 0x00E0; // RB1,2,3 pull up /* Initialize GLCD */ lcd_Init(); lcd_Clear(BLACK); // クリア lcd_Str(0, 0, "Start Test", CYAN, BLACK); delay_ms(1000); /* Initialize ADC */ AD1CON1= 0x0000; // SAMP bit= 0 ends sampling... and starts converting(手動AD変換) AD1CHS0= 0x0000; // Connect AN0 as CH0 input AD1CSSL= 0x0000; // 自動スキャンしない AD1CON3= 0x0002; // 手動サンプル、Tad= internal 2Tcy AD1CON2= 0x0000; // Vref=AVdd-AVss,入力スキャンしない、CH0を変換 AD1CON1bits.ADON = 1; // ADC Start /****** Main Loop ****/ while(1){ fx= 8; // 表示周波数初期化(10-2=8Hz) do { sync_m0 = PORTAbits.RA1; //New Sync Signal sync_m2 = sync_m1^(sync_m0 & sync_m1); //Neg_Edge Sence Sync Signal sync_m1 = sync_m0; //Chenge New Data to Old Data m1 } while(!sync_m2); // スイープ同期パルスの立下りエッジが検知されるまでエッジ検知を繰り返す。 // (立下りエッジから、スイープを開始する。) AxisDraw(); // 座標表示 /// 181回、x座標をずらしながら、サンプル→ 変換→ ドット描画を繰返し、 /// 1画面分のグラフを描画 for(x= 0; x < 181; ++x) { // delay_ms(500); // 実測、506mS delay_ms(494); // 実測、500mS AD1CON1bits.SAMP= 1; // サンプリング開始 // delay_ms(100); // 実測、101.2mS delay_ms(99); // 実測、100.08mS AD1CON1bits.SAMP= 0; // AD変換開始 while(!AD1CON1bits.DONE); // AD変換終了待ち /// 変換値をドット描画の、Y座標(レベル)に変換、そこにドット描画する。 y= (ADC1BUF0)*5/22; // ADC1BUF0)*5/22は、数学的なy座標になる→ 下が0で上に行くほど増える) lcd_Pixel(x,239-y,WHITE); /// スキャン中の、周波数値を求め液晶に表示する。 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; ltostring(6, fx, MsgData1); // バイナリ→ 文字列変換 lcd_Str(18, 2, MsgData1, WHITE, BLACK); // 周波数表示 /// 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, MsgData2); // 浮動小数点→ 文字列変換 lcd_Str(19, 3, MsgData2, WHITE, BLACK); // dB表示 /// -3dBポイントを検出したら、その時の周波数を別ロケーションに表示する。 if((y < 177) && (db == 3.00)) { // −3.00dB検知 ltostring(6, fx, MsgData1); // バイナリ→ 文字列変換 lcd_Str(18, 7, MsgData1, YELLOW, BLACK); // 周波数表示 lcd_Str(18, 8, "- 3.00dB", YELLOW, BLACK); // -3dB表示 } // delay_ms(400); // 実測、405mS(これで次回から、0.5+0.1+0.4= 1秒周期のサンプリングになる。) delay_ms(395); // 実測、400mS } } } /****************************************** * Drawing Coordinate Axis *******************************************/ void AxisDraw(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, "+10", CYAN, BLACK); // +10 lcd_Str(15, 0, "+10dB", CYAN, BLACK); // +10dB // lcd_Str(15, 3, "0dB", CYAN, BLACK); // 0dB 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 } /******************************************************** * 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