/*********************************************************************** * PIC18F14K50 * AD9834_Test * * Strawberry Linux社の「AD9834 小型 DDS モジュールキット」を試す。 * * LCD unlook busy : not switch direction (write fixed) * * Condition: * 内蔵発振器:16MHz使用 * Tcy= 1/(16M/4)= 250nS * * 2015/2/17 * 作成:N.Ishii ***********************************************************************/ #include #include "LCD_Lib_PIC18F.h" #include "delays.h" #pragma config FOSC = IRC, PLLEN = ON, FCMEN = OFF #pragma config IESO = OFF, USBDIV = OFF, CPUDIV = NOCLKDIV #pragma config PWRTEN = OFF, BOREN = OFF, WDTEN = OFF #pragma config HFOFST = OFF, MCLRE = OFF #pragma config STVREN = ON, BBSIZ = OFF, LVP = OFF #pragma config XINST = OFF #pragma config CP0 = OFF, CP1 = OFF, CPB = OFF #pragma config WRT0 = OFF, WRT1 = OFF, WRTB = OFF, WRTC = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF /// DDSコントロールポート定義 #define DDS_FSYNC LATCbits.LATC3 // AD9834 sync #define DDS_SCLK LATAbits.LATA5 // AD9834 clock #define DDS_SDATA LATAbits.LATA4 // AD9834 data /// Message char MsgTitle[] = "DDS AD9834 Test"; char Msg10[] = " Frq= 10Hz"; char Msg100[] = " Frq= 100Hz"; char Msg1K[] = " Frq= 1000Hz"; char Msg10K[] = " Frq= 10000Hz"; char Msg100K[] = " Frq= 100000Hz"; char Msg200K[] = " Frq= 200000Hz"; char Msg300K[] = " Frq= 300000Hz"; char Msg400K[] = " Frq= 400000Hz"; char Msg500K[] = " Frq= 500000Hz"; char Msg1M[] = " Frq= 1000000Hz"; char FSW; char SQ= 0; // 設定シーケンスNo. char OldTemp; // 1つ前の、FSWの値 /// 関数プロトタイプ宣言 void dds_dataset(unsigned long data, unsigned int bt); void freq_to_serial(unsigned long f); void FrqRegSet(void); /***************** * メイン関数 ******************/ int main(void) { OSCCON = 0b11111111; // 16MHz internal clock UCONbits.USBEN = 0 ; // USBは使用しない /// アナログ入力と併用の、RB4,5(DSW-1,2)に該当する /// ANSELxビットを'0'にリセット、デジタルピンとして使用する。 ANSELHbits.ANS10 = 0; // RB4 digital input ANSELHbits.ANS11 = 0; // RB5 digital input TRISAbits.TRISA4= 0; // RA4(SDATA) is Output TRISAbits.TRISA5= 0; // RA5(SCLK) is Output TRISC= 0; // RC is Output(D7-4, FSYNC, LED, RS. STB) TRISB= 0b11110000; // RB4-7(DSW-1,2,4,8) is Input /// 内部プルアップ設定 INTCON2bits.RABPU = 0; // プルアップ許可(これが無いとプルアップされない) WPUB = 0b11110000; // RB4-7 is Pull-Up LATCbits.LATC2= 0; // LED 消灯 /// 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(RESETパルス出力だけにする) dds_dataset(0x2100, 16); // RESET ON dds_dataset(0x2000, 16); // RESET OFF /// 開始メッセージ出力 lcd_init(); // LCD初期化 lcd_clear(); // 全消去 lcd_str(MsgTitle); // タイトル1行目表示 /// Main Loop while(1) { FSW= ~PORTB >> 4; // Read Decimal Dip SW(出力周波数選択ディップSW読込み) switch(SQ){ case 0: //// 電源投入後、1回目の、Fレジ設定転送 OldTemp= FSW; FrqRegSet(); SQ= 1; break; case 1: //// 2回目以降の、Fレジ設定転送 if(FSW != OldTemp){ // FSWの設定を変えた時のみ、Fレジ更新 OldTemp= FSW; dds_dataset(0x2100, 16); // RESET ON dds_dataset(0x2000, 16); // RESET OFF FrqRegSet(); } break; default:; break; } } } /************************************************************************** * serial data send (MSB first) * 16ビット(bt=16で指定)SPI転送 * AD9834は、SCLKの立下りエッジでデータを読込む ****************************************************************************/ 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; } /***************************************************************** * AD9834 DDS control (frequency to serial code) * 希望の出力周波数から、シリアルコードを算出し、シリアル転送する。 ******************************************************************/ void freq_to_serial(unsigned long f) { unsigned long msb, lsb; unsigned long data; data = f << 2; // 指定周波数を、4倍したのが、周波数レジスタにセットする値になる 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(0x2028, 16); //// 制御レジへの書込み // bit13:B28='1':2つの連続した16bit転送で完全なコントロールワードをロード // bit9:PIN/SW= '0',bit8:RESET= '0':リセットビットをリセット(RESET OFF) // bit5:OPBITEN= '1':SB-OUTピン有効 // bit4:SIGNPIB= '0',bit3:DIV2= '1':SB-OUTに出力(サイン出力と同じ周波数で出力) // bit1:MODEビット= '0':サイン波出力 // dds_dataset(0x2020, 16); // bit4:SIGNPIB= '0',bit3:DIV2= '0':SB-OUTに出力(サイン出力の、1/2周波数で出力) // dds_dataset(0x2038, 16); // bit4:SIGNPIB= '1',bit3:DIV2= '1':コンパレータ方形波をSB-OUTに出力 // dds_dataset(0x2000, 16); // サイン波のみの出力 dds_dataset(lsb, 16); // lsb転送(下位14ビットの周波数レジスタ0のデータを、b15,14のコントロールビットと共に転送) dds_dataset(msb, 16); // msb転送(上位14ビットの周波数レジスタ0のデータを、b15,14のコントロールビットと共に転送) dds_dataset(0xC000, 16); // 位相レジスタ初期化:0 } /*************************************************** * FSW読込み値に従い、Fレジを設定転送する ****************************************************/ void FrqRegSet(void) { switch(FSW){ case 0: freq_to_serial(10); // 10Hz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg10); break; case 1: freq_to_serial(100); // 100Hz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg100); break; case 2: freq_to_serial(1000); // 1kHz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg1K); break; case 3: freq_to_serial(10000); // 10kHz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg10K); break; case 4: freq_to_serial(100000); // 100kHz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg100K); break; case 5: freq_to_serial(200000); // 200kHz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg200K); break; case 6: freq_to_serial(300000); // 300kHz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg300K); break; case 7: freq_to_serial(400000); // 400kHz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg400K); break; case 8: freq_to_serial(500000); // 500kHz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg500K); break; case 9: freq_to_serial(1000000); // 1MHz lcd_cmd(0xC0); // 2行目の先頭に移動 lcd_str(Msg1M); break; default:; break; } }