PIC16FのNCOを利用した周波数シンセサイザの製作です。
出力波形は矩形波(0-5V)です
出力周波数範囲は、1Hz~8.388607MHz です
外観
仕様
・出力波形 矩形波
・出力電圧 5V
・出力電圧 1Hz~8.388607MHz
・周波数分解能
1Hz(1Hz-1.048575MHz時)
2Hz(1.048576MHz~2.097151MHz時)
4Hz(2.097152Hz~4.194303MHz時)
8Hz(4.194304MHz~8.388607MHz時)
・周波数設定 ロータリースイッチ
・電源電圧 100V(5V ACアダプタ使用)
設計方針
・PICの周辺モジュールであるNCO(Numerically controlled oscillator)を用いる
・水晶4.194304MHz(2^22)をNCOで分周し、周波数分解能1Hzを実現する
・設定周波数は0~9の設定可能なロータリースイッチを7個使用する
・ロータリースイッチの配線数を少なくするために、AD変換を用い0~9を判別する
・シンセサイザーの出力周波数を拡大するためにCLC(Configurable Logic Cell)を用い、T-F/Fを構成しFoscを分周する
・シンセサイザーの出力周波数をLCDで表示する
synthesizerブロック図
ロータリースイッチ
全体ブロック図
回路図
frequency_synthesizer1内部写真
LCD
ソフトウエア(mainプログラム)
ソフトウエア(周波数設定)
部品表
ソースコード
/*
* File: main.c
*
* Created on 2018/09/20, 21:16
*/
//-------- ハードウエア --------------
// RA0(2) out クロック出力
// RA1(3) out 未使用
// RA2(4) out 未使用
// RA3(5) out 未使用
// RA4(6) out 未使用
// RA5(7) out 未使用
// RA6(10) in OSC2 水晶
// RA7(9) in OSC1
//
// RB0(21) out LCD D7
// RB1(22) out LCD D6
// RB2(23) out LCD D5
// RB3(24) out LCD D4
// RB4(25) out LCD E
// RB5(26) out LCD RS
// RB6(27) in ICSPCLK
// RB7(28) in ICSPDAT
//
// RC0(11) out 未使用
// RC1(12) in ANC1 ロータリーSW
// RC2(13) in ANC2 ロータリーSW
// RC3(14) in ANC3 ロータリーSW
// RC4(15) in ANC4 ロータリーSW
// RC5(16) in ANC5 ロータリーSW
// RC6(17) in ANC6 ロータリーSW
// RC7(18) in ANC7 ロータリーSW
//
// RE3(1) in MCLR
// PIC16F18857 Configuration Bit Settings
// CONFIG1
#pragma config FEXTOSC = HS // External Oscillator mode selection bits (HS (crystal oscillator) above 4MHz; PFM set to high power)
#pragma config RSTOSC = EXT4X // Power-up default value for COSC bits (EXTOSC with 4x PLL, with EXTOSC operating per FEXTOSC bits)
//#pragma config RSTOSC = EXT1X // Power-up default value for COSC bits (EXTOSC operating per FEXTOSC bits)
#pragma config CLKOUTEN = OFF // Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2)
#pragma config CSWEN = OFF // Clock Switch Enable bit (The NOSC and NDIV bits cannot be changed by user software)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (FSCM timer disabled)
// CONFIG2
#pragma config MCLRE = ON // Master Clear Enable bit (MCLR pin is Master Clear function)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config LPBOREN = OFF // Low-Power BOR enable bit (ULPBOR disabled)
#pragma config BOREN = OFF // Brown-out reset enable bits (Brown-out reset disabled)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)
#pragma config ZCD = OFF // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)
#pragma config PPS1WAY = ON // Peripheral Pin Select one-way control (The PPSLOCK bit can be cleared and set only once in software)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a reset)
// CONFIG3
#pragma config WDTCPS = WDTCPS_31// WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = OFF // WDT operating mode (WDT Disabled, SWDTEN is ignored)
#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = SC // WDT input clock selector (Software Control)
// CONFIG4
#pragma config WRT = OFF // UserNVM self-write protection bits (Write protection off)
#pragma config SCANE = not_available// Scanner Enable bit (Scanner module is not available for use)
#pragma config LVP = ON // Low Voltage Programming Enable bit (Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.)
// CONFIG5
#pragma config CP = OFF // UserNVM Program memory code protection bit (Program Memory code protection disabled)
#pragma config CPD = OFF // DataNVM code protection bit (Data EEPROM code protection disabled)
//************************ インクルードファイル ***********************
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
//******************* 関数定義 **************************************************
void init_OSC(void); //オシレータ初期設定
void init_port(void); //PORT初期設定
void init_LCD(void); //LCD初期設定
void set_LCD_port(unsigned char data); //LCDポート設定
void set_character_lcd_cmd(unsigned char cmd); //LCDコマンド設定
void set_character_lcd_data(unsigned char data); //LCDデータ設定
void LCD_Puts(const char * s);
void clear_character(unsigned char address, unsigned char number);
void display_normal(void); //LCD1行目に[ -- FREQUENCY --]を表示
void display_higher(void); //LCD1行目に[set higher frequency]を表示
void display_lower(void); //LCD1行目に[set lower frequency]を表示
void display_frequency(void); //数値表示
void init_NCO(void); //NCO初期設定
void init_CLC1(void); //CLC1初期設定
void init_CLC2(void); //CLC2初期設定
void init_CLC3(void); //CLC3初期設定
void init_ADC(void); //ADC初期設定
unsigned char start_ADC(unsigned char adc_ch); //ADC開始
void set_frequency(void); //周波数設定
void set_frequency1(void); //周波数設定1(1Hz-1.048575Hz)
void set_frequency2(void); //周波数設定1(Hz)
void set_frequency3(void); //周波数設定1(Hz)
void set_frequency4(void); //周波数設定1(Hz)
void convert_binaly_ASCII(unsigned long binaly); //バイナリデータをASCIIに変換する
void test_display_decimal(unsigned long binaly); //バイナリデーターを10進で表示する
//******************* PORTの定義など ************************
#define LCD_D7 PORTBbits.RB0
#define LCD_D6 PORTBbits.RB1
#define LCD_D5 PORTBbits.RB2
#define LCD_D4 PORTBbits.RB3
#define LCD_E PORTBbits.RB4
#define LCD_RS PORTBbits.RB5
#define _XTAL_FREQ 16777216
//***************************** グローバル変数 **********************************
unsigned long frequency = 1;
unsigned long freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1;
unsigned char d1000000,d100000,d10000,d1000,d100,d10,d1; //各桁のascIIコード
//******************** プログラム ***********************************************
//******************** オシレータ初期設定 ***************************************
// 入力 なし
// 処理 4*PLL
// 出力 Fosc(4.194304MHz)
//******************************************************************************
void init_OSC(void){ //オシレータ初期設定
OSCCON2bits.COSC = 2; //4.1943056MHz*4PLL=16.777224MHz
OSCCON2bits.CDIV = 0; //1:1 Fosc=16.777224MHz
}
//******************** PORT初期設定 *********************************************
// 入力 なし
// 処理
// 出力
//******************************************************************************
void init_port(void){ //PORT初期設定
TRISA = 0xc0; ANSELA = 0x00; LATA = 0;
TRISB = 0xc0; ANSELB = 0x00;
TRISC = 0xfe; ANSELC = 0xfe;
RA0PPS = 0x19; //RA0:NCO1 OUT
}
//******************** LCD初期設定 *********************************************
// 入力 なし
// 処理
// 出力
//******************************************************************************
void init_LCD(void){ //LCD初期設定
LCD_RS = 0; //RS=0:command mode
LCD_E=0;
__delay_ms(40); //Delay 40ms
set_LCD_port(3); //8bitモード(0x30)をセット
LCD_E=1; __delay_us(1); LCD_E=0; //Enable 1usec high
__delay_ms(5); //Delay 4.1msec以上
set_LCD_port(3); //8bitモード(0x30)をセット
LCD_E=1; __delay_us(1); LCD_E=0; //Enable 1usec high
__delay_us(100); //Delay 100usec
set_LCD_port(3); //8bitモード(0x30)をセット
LCD_E=1; __delay_us(1); LCD_E=0; //Enable 1usec high
__delay_us(37); //Delay 37usec
set_LCD_port(2); //4bitモード(0x20)をセット
LCD_E=1; __delay_us(1); LCD_E=0; //Enable 1usec high
__delay_us(37); //Delay 37usec
set_character_lcd_cmd(0x28); //4bitモード 1/16duty
set_character_lcd_cmd(0x08); //4bitモード 表示OFF
set_character_lcd_cmd(0x01); //4bitモード クリアディスプレイ
__delay_ms(2); //Delay 1.53msec
set_character_lcd_cmd(0x06); //4bitモード 書き込みモード、アドレス+1
set_character_lcd_cmd(0x0c); //4bitモード 表示ON
LCD_Puts(" -- FREQUENCY --");
set_character_lcd_cmd(0xc0); //アドレス2行目先頭にする
LCD_Puts(" 1.000000 [MHz]"); //display_mode=0
}
/************************ LCD portCにデータを設定 ********************************
* 入力 data
* 処理 LCDデータを設定
* 出力 LCD_D7,LCD_D6,LCD_D5,LCD_D4
*******************************************************************************/
void set_LCD_port(unsigned char data){
switch(data){
case 0: LCD_D7=0; LCD_D6=0; LCD_D5=0; LCD_D4=0; break;
case 1: LCD_D7=0; LCD_D6=0; LCD_D5=0; LCD_D4=1; break;
case 2: LCD_D7=0; LCD_D6=0; LCD_D5=1; LCD_D4=0; break;
case 3: LCD_D7=0; LCD_D6=0; LCD_D5=1; LCD_D4=1; break;
case 4: LCD_D7=0; LCD_D6=1; LCD_D5=0; LCD_D4=0; break;
case 5: LCD_D7=0; LCD_D6=1; LCD_D5=0; LCD_D4=1; break;
case 6: LCD_D7=0; LCD_D6=1; LCD_D5=1; LCD_D4=0; break;
case 7: LCD_D7=0; LCD_D6=1; LCD_D5=1; LCD_D4=1; break;
case 8: LCD_D7=1; LCD_D6=0; LCD_D5=0; LCD_D4=0; break;
case 9: LCD_D7=1; LCD_D6=0; LCD_D5=0; LCD_D4=1; break;
case 10: LCD_D7=1; LCD_D6=0; LCD_D5=1; LCD_D4=0; break;
case 11: LCD_D7=1; LCD_D6=0; LCD_D5=1; LCD_D4=1; break;
case 12: LCD_D7=1; LCD_D6=1; LCD_D5=0; LCD_D4=0; break;
case 13: LCD_D7=1; LCD_D6=1; LCD_D5=0; LCD_D4=1; break;
case 14: LCD_D7=1; LCD_D6=1; LCD_D5=1; LCD_D4=0; break;
case 15: LCD_D7=1; LCD_D6=1; LCD_D5=1; LCD_D4=1; break;
}
}
/*********************** LCDにコマンドを設定 ************************************
* 入力 cmd(8bit)
* 処理 LCDにコマンドを設定(RS = 0) + 37usec delay
* 出力 なし
*******************************************************************************/
void set_character_lcd_cmd(unsigned char cmd){
LCD_RS = 0; //RS=0:command
LCD_E=1;
set_LCD_port(cmd >> 4); __delay_us(1); //LCD PORTの値(上位4bit)をセット
LCD_E=0;
__delay_us(2); //delay 2usec
LCD_E=1;
set_LCD_port(cmd & 0x0f); __delay_us(1); //LCD PORTの値(下位4bit)をセット
LCD_E=0;
__delay_us(37); //delay 37usec
}
/************************ LCDにデータを設定 *************************************
* 入力 data(8bit)
* 処理 LCDにデータを設定(RS=1) + 37usec delay
* 出力 なし
*******************************************************************************/
void set_character_lcd_data(unsigned char data){
LCD_RS = 1; //RS=1:data
LCD_E=1;
set_LCD_port(data >> 4); __delay_us(1); //LCD PORTの値(上位4bit)をセット
LCD_E=0;
__delay_us(2); //delay 2uSEC
LCD_E=1;
set_LCD_port(data & 0x0f); __delay_us(1); //LCD PORTの値(下位4bit)をセット
LCD_E=0;
__delay_us(37); //delay 37usec
}
/*******************************************************************************
* LCD_Puts(*s) *
* LCDに文字列データを出力する処理 *
* 文字列は、NULL(0x00)まで繰返し出力します。 *
* *
* *s : 出力する文字列のデータを格納した場所のアドレスを指定 *
*******************************************************************************/
void LCD_Puts(const char * s){
while(*s) {
set_character_lcd_data(*s++); //data byte の送信(連続送信)
}
}
//******************** LCD 表示アドレスを設定する ******************************
// 入力 クリア先頭アドレス、クリアバイト数
// 処理 LCD 表示 をクリアする
// 出力 なし
//******************************************************************************
void clear_character(unsigned char address, unsigned char number){
unsigned char x;
set_character_lcd_cmd(address);
for(x=0; x<number; x++) set_character_lcd_data(' ');
}
//******************** LCDに周波数を表示する ************************************
// 入力 freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1
// 処理 LCDの2行目に周波数を表示する
// 出力 なし
//******************************************************************************
void display_frequency(void){ //表示
clear_character(0xc0,16); //2行目クリア
set_character_lcd_cmd(0xc0); //アドレス2行目先頭にする
char character_string[16];
character_string[0] = 0x20; //sp
if(freq_no7 == 0){
character_string[1] = 0x20; //sp
if(freq_no6 == 0){
character_string[2] = 0x20; //sp
if(freq_no5 == 0){
character_string[3] = 0x20; //sp
if(freq_no4 == 0){
character_string[4] = 0x20; //sp
if(freq_no3 == 0){
character_string[5] = 0x20; //sp
if(freq_no2 == 0){ //9Hz-1Hzの表示
character_string[6] = 0x20; //sp
character_string[7] = 0x20; //sp
character_string[8] = freq_no1 + 0x30; //
character_string[9] = 0x20; //sp
character_string[10] = 0x20; //sp
character_string[11] = '['; //
}
else{ //99Hz-10Hzの表示
character_string[6] = 0x20; //sp
character_string[7] = freq_no2 + 0x30; //
character_string[8] = freq_no1 + 0x30; //
character_string[9] = 0x20; //sp
character_string[10] = 0x20; //sp
character_string[11] = '['; //
}
}
else{ //999Hz-100Hzの表示
character_string[5] = 0x20; //sp
character_string[6] = freq_no3 + 0x30; //
character_string[7] = freq_no2 + 0x30; //
character_string[8] = freq_no1 + 0x30; //
character_string[9] = 0x20; //sp
character_string[10] = 0x20; //sp
character_string[11] = '['; //
}
}
else{ //9kHz-1kHzの表示
character_string[4] = freq_no4 + 0x30; //
character_string[5] = '.'; //
character_string[6] = freq_no3 + 0x30; //
character_string[7] = freq_no2 + 0x30; //
character_string[8] = freq_no1 + 0x30; //
character_string[9] = 0x20; //sp
character_string[10] = '['; //
character_string[11] = 'k'; //
}
}
else{ //99kHz-10kHの表示
character_string[3] = freq_no5 + 0x30; //
character_string[4] = freq_no4 + 0x30; //
character_string[5] = '.'; //
character_string[6] = freq_no3 + 0x30; //
character_string[7] = freq_no2 + 0x30; //
character_string[8] = freq_no1 + 0x30; //
character_string[9] = 0x20; //sp
character_string[10] = '['; //
character_string[11] = 'k'; //
}
}
else{ //999kHz-100kHzの表示
character_string[2] = freq_no6 + 0x30; //
character_string[3] = freq_no5 + 0x30; //
character_string[4] = freq_no4 + 0x30; //
character_string[5] = '.'; //
character_string[6] = freq_no3 + 0x30; //
character_string[7] = freq_no2 + 0x30; //
character_string[8] = freq_no1 + 0x30; //
character_string[9] = 0x20; //sp
character_string[10] = '['; //
character_string[11] = 'k'; //
}
}
else{ //1MHz以上の表示
character_string[1] = freq_no7 + 0x30; //
character_string[2] = '.'; //
character_string[3] = freq_no6 + 0x30; //
character_string[4] = freq_no5 + 0x30; //
character_string[5] = freq_no4 + 0x30; //
character_string[6] = freq_no3 + 0x30; //
character_string[7] = freq_no2 + 0x30; //
character_string[8] = freq_no1 + 0x30; //
character_string[9] = 0x20; //sp
character_string[10] = '['; //
character_string[11] = 'M'; //
}
character_string[12] = 'H'; //
character_string[13] = 'z'; //
character_string[14] = ']'; //
character_string[15] = 0; //null
LCD_Puts(character_string); //数値表示
}
//************** LCD1行目に[-- FREQUENCY --]を表示 **********************
// 入力
// 処理
// 出力 なし
//******************************************************************************
void display_normal(void){ //LCD1行目に[ -- FREQUENCY --]を表示
clear_character(0x80,16); //1行目クリア
set_character_lcd_cmd(0x80); //アドレス1行目先頭にする
LCD_Puts(" -- FREQUENCY -- "); // -- FREQUENCY --表示
}
//************** LCD1行目に[set higher frequency]を表示 **********************
// 入力
// 処理
// 出力 なし
//******************************************************************************
void display_higher(void){ //LCD1行目に[set higher frequency]を表示
clear_character(0x80,16); //1行目クリア
set_character_lcd_cmd(0x80); //アドレス1行目先頭にする
LCD_Puts("Set higher FREQ!"); // -- FREQUENCY --表示
}
//*************** LCD1行目に[set lower frequency]を表示 **********************
// 入力
// 処理
// 出力 なし
//******************************************************************************
void display_lower(void){ //LCD1行目に[set lower frequency]を表示
clear_character(0x80,16); //1行目クリア
set_character_lcd_cmd(0x80); //アドレス1行目先頭にする
LCD_Puts("Set lower FREQ!"); // -- FREQUENCY --表示
}
/******************* バイナリデータをASCIIコードに変換する ***********************
* 入力 0<= binaly <=9999999
* 処理 バイナリ→ASCII変換
* 出力 d1000000,d100000,d10000,d1000,d100,d10,d1
**********************************************************************/
void convert_binaly_ASCII(unsigned long binaly){
unsigned long syou1,syou10,syou100,syou1000,syou10000,syou100000,syou1000000;
syou1 = binaly/10; d1 = binaly%10 + 0x30;
syou10 = syou1/10; d10 = syou1%10 + 0x30;
syou100 = syou10/10; d100 = syou10%10 + 0x30;
syou1000 = syou100/10; d1000 = syou100%10 + 0x30;
syou10000 = syou1000/10; d10000 = syou1000%10 + 0x30;
syou100000 = syou10000/10; d100000 = syou10000%10 + 0x30;
d1000000 = syou100000%10 + 0x30;
}
//********************* バイナリデーターを10進で表示する *************************
// 入力 0 < binaly < 9999999
// 処理 LCDにbinalyデータを10進に変換し表示する
// 出力 LCD
//******************************************************************************
void test_display_decimal(unsigned long binaly){ //バイナリデーターを10進で表示する
clear_character(0x80,16); //1行目クリア
set_character_lcd_cmd(0x80); //アドレス1行目先頭にする
char character_string[8];
convert_binaly_ASCII(binaly); //バイナリーデータをASCIIコードに変換
character_string[0] = d1000000;
character_string[1] = d100000;
character_string[2] = d10000;
character_string[3] = d1000;
character_string[4] = d100;
character_string[5] = d10;
character_string[6] = d1;
character_string[7] = 0; //null
LCD_Puts(character_string); //数値表示
}
//******************** CLC1初期設定 ********************************************
// 入力 Fosc(16.777224MHz
// 処理 2分周(JK-F/F→T-F/F)
// 出力 CLC1OUT(8.388608MHz)
//******************************************************************************
void init_CLC1(void){ //CLC1初期設定
//lc1g1をFoscにセット
CLC1SEL0bits.LC1D1S = 4; //入力信号Fosc(16.777224MHz)を選択
CLC1GLS0bits.LC1G1D1T = 1; CLC1GLS0bits.LC1G1D1N = 0;
CLC1GLS0bits.LC1G1D2T = 0; CLC1GLS0bits.LC1G1D2N = 0;
CLC1GLS0bits.LC1G1D3T = 0; CLC1GLS0bits.LC1G1D3N = 0;
CLC1GLS0bits.LC1G1D4T = 0; CLC1GLS0bits.LC1G1D4N = 0;
CLC1POLbits.LC1G1POL = 0; //gate0 output polarity
//lc1g2(J入力)をHにする
CLC1GLS1bits.LC1G2D1T = 0; CLC1GLS1bits.LC1G2D1N = 0;
CLC1GLS1bits.LC1G2D2T = 0; CLC1GLS1bits.LC1G2D2N = 0;
CLC1GLS1bits.LC1G2D3T = 0; CLC1GLS1bits.LC1G2D3N = 0;
CLC1GLS1bits.LC1G2D4T = 0; CLC1GLS1bits.LC1G2D4N = 0;
CLC1POLbits.LC1G2POL = 1; //gate1 output polarity
//lc1g4(K入力)をHにする
CLC1GLS3bits.LC1G4D1T = 0; CLC1GLS3bits.LC1G4D1N = 0;
CLC1GLS3bits.LC1G4D2T = 0; CLC1GLS3bits.LC1G4D2N = 0;
CLC1GLS3bits.LC1G4D3T = 0; CLC1GLS3bits.LC1G4D3N = 0;
CLC1GLS3bits.LC1G4D4T = 0; CLC1GLS3bits.LC1G4D4N = 0;
CLC1POLbits.LC1G4POL = 1; //gate3 output polarity
//lc1g3(RESET入力)をLにする
CLC1GLS2bits.LC1G3D1T = 0; CLC1GLS2bits.LC1G3D1N = 0;
CLC1GLS2bits.LC1G3D2T = 0; CLC1GLS2bits.LC1G3D2N = 0;
CLC1GLS2bits.LC1G3D3T = 0; CLC1GLS2bits.LC1G3D3N = 0;
CLC1GLS2bits.LC1G3D4T = 0; CLC1GLS2bits.LC1G3D4N = 0;
CLC1POLbits.LC1G3POL = 0; //gate2 output polarity
//JK-F/Fにセットする
CLC1CONbits.LC1MODE = 6; //JK-F/Fを選択
//出力設定
CLC1POLbits.LC1G1POL = 0; //CLC1 OUTPUT Polarity is not invert
CLC1CONbits.LC1EN = 1; //cofigration logic cell enable
}
//******************** CLC2初期設定 ********************************************
// 入力 CLC1OUT(8.388608MHz)
// 処理 2分周(JK-F/F→T-F/F)
// 出力 CLC2OUT(4.1943056MHz)
//******************************************************************************
void init_CLC2(void){ //CLC2初期設定
//lc1g1をCLC1OUTにセット
CLC2SEL0bits.LC2D1S = 32; //入力信号CLC1OUT(8.388608MHz)を選択
CLC2GLS0bits.LC2G1D1T = 1; CLC2GLS0bits.LC2G1D1N = 0;
CLC2GLS0bits.LC2G1D2T = 0; CLC2GLS0bits.LC2G1D2N = 0;
CLC2GLS0bits.LC2G1D3T = 0; CLC2GLS0bits.LC2G1D3N = 0;
CLC2GLS0bits.LC2G1D4T = 0; CLC2GLS0bits.LC2G1D4N = 0;
CLC2POLbits.LC2G1POL = 0; //gate0 output polarity
//lc1g2(J入力)をHにする
CLC2GLS1bits.LC2G2D1T = 0; CLC2GLS1bits.LC2G2D1N = 0;
CLC2GLS1bits.LC2G2D2T = 0; CLC2GLS1bits.LC2G2D2N = 0;
CLC2GLS1bits.LC2G2D3T = 0; CLC2GLS1bits.LC2G2D3N = 0;
CLC2GLS1bits.LC2G2D4T = 0; CLC2GLS1bits.LC2G2D4N = 0;
CLC2POLbits.LC2G2POL = 1; //gate1 output polarity
//lc1g4(K入力)をHにする
CLC2GLS3bits.LC2G4D1T = 0; CLC2GLS3bits.LC2G4D1N = 0;
CLC2GLS3bits.LC2G4D2T = 0; CLC2GLS3bits.LC2G4D2N = 0;
CLC2GLS3bits.LC2G4D3T = 0; CLC2GLS3bits.LC2G4D3N = 0;
CLC2GLS3bits.LC2G4D4T = 0; CLC2GLS3bits.LC2G4D4N = 0;
CLC2POLbits.LC2G4POL = 1; //gate3 output polarity
//lc1g3(RESET入力)をLにする
CLC2GLS2bits.LC2G3D1T = 0; CLC2GLS2bits.LC2G3D1N = 0;
CLC2GLS2bits.LC2G3D2T = 0; CLC2GLS2bits.LC2G3D2N = 0;
CLC2GLS2bits.LC2G3D3T = 0; CLC2GLS2bits.LC2G3D3N = 0;
CLC2GLS2bits.LC2G3D4T = 0; CLC2GLS2bits.LC2G3D4N = 0;
CLC2POLbits.LC2G3POL = 0; //gate2 output polarity
//JK-F/Fにセットする
CLC2CONbits.LC2MODE = 6; //JK-F/Fを選択
//出力設定
CLC2POLbits.LC2G1POL = 0; //CLC2 OUTPUT Polarity is not invert
CLC2CONbits.LC2EN = 1; //cofigration logic cell enable
}
//******************** CLC3初期設定 *********************************************
// 入力 CLC2OUT(4.1943056MHz)
// 処理 2分周(JK-F/F→T-F/F)
// 出力 CLC3OUT(2.097152MHz)
//******************************************************************************
void init_CLC3(void){ //CLC3初期設定
//lc1g1をCLC2OUTにセット
CLC3SEL0bits.LC3D1S = 33; //入力信号CLC2OUT(4.1943056MHz)を選択
CLC3GLS0bits.LC3G1D1T = 1; CLC3GLS0bits.LC3G1D1N = 0;
CLC3GLS0bits.LC3G1D2T = 0; CLC3GLS0bits.LC3G1D2N = 0;
CLC3GLS0bits.LC3G1D3T = 0; CLC3GLS0bits.LC3G1D3N = 0;
CLC3GLS0bits.LC3G1D4T = 0; CLC3GLS0bits.LC3G1D4N = 0;
CLC3POLbits.LC3G1POL = 0; //gate0 output polarity
//lc1g2(J入力)をHにする
CLC3GLS1bits.LC3G2D1T = 0; CLC3GLS1bits.LC3G2D1N = 0;
CLC3GLS1bits.LC3G2D2T = 0; CLC3GLS1bits.LC3G2D2N = 0;
CLC3GLS1bits.LC3G2D3T = 0; CLC3GLS1bits.LC3G2D3N = 0;
CLC3GLS1bits.LC3G2D4T = 0; CLC3GLS1bits.LC3G2D4N = 0;
CLC3POLbits.LC3G2POL = 1; //gate1 output polarity
//lc1g4(K入力)をHにする
CLC3GLS3bits.LC3G4D1T = 0; CLC3GLS3bits.LC3G4D1N = 0;
CLC3GLS3bits.LC3G4D2T = 0; CLC3GLS3bits.LC3G4D2N = 0;
CLC3GLS3bits.LC3G4D3T = 0; CLC3GLS3bits.LC3G4D3N = 0;
CLC3GLS3bits.LC3G4D4T = 0; CLC3GLS3bits.LC3G4D4N = 0;
CLC3POLbits.LC3G4POL = 1; //gate3 output polarity
//lc1g3(RESET入力)をLにする
CLC3GLS2bits.LC3G3D1T = 0; CLC3GLS2bits.LC3G3D1N = 0;
CLC3GLS2bits.LC3G3D2T = 0; CLC3GLS2bits.LC3G3D2N = 0;
CLC3GLS2bits.LC3G3D3T = 0; CLC3GLS2bits.LC3G3D3N = 0;
CLC3GLS2bits.LC3G3D4T = 0; CLC3GLS2bits.LC3G3D4N = 0;
CLC3POLbits.LC3G3POL = 0; //gate2 output polarity
//JK-F/Fにセットする
CLC3CONbits.LC3MODE = 6; //JK-F/Fを選択
//出力設定
CLC3POLbits.LC3G1POL = 0; //CLC3 OUTPUT Polarity is not invert
CLC3CONbits.LC3EN = 1; //cofigration logic cell enable
}
//******************** NCO初期設定 *********************************************
// 入力 CLC3OUT(2.097152MHz)
// 処理 Overflow = (2097152*IncrementValue)/2^21=IncrementValue
// 出力 NCO1OUT(1Hz-1.048576MHz)
//******************************************************************************
void init_NCO(void){ //NCO初期設定
NCO1CLKbits.N1CKS = 3; //NCO1 clock is CLC3OUT(2.097152MHz))
NCO1CONbits.N1PFM = 0; //NCO1 fix duty cycle mode
NCO1CONbits.N1POL = 0; //NCO1OUT not inverted
NCO1CONbits.N1OUT = 1; //NCO1OUT enable
NCO1ACCL = 0; //NCO1 ACCL = 0
NCO1ACCH = 0; //NCO1 ACCH = 0
NCO1ACCU = 0; //NCO1 ACCU = 0
NCO1INCU = 0x0f;
NCO1INCH = 0x42;
NCO1INCL = 0x40; //1MHz=1000000=0x0f4240
NCO1CONbits.N1EN = 1; //NCO1 enable
}
//******************** ADC初期設定 ******************************
// 入力 ロータリースイッチの電圧
// 処理 入力電圧から0-9の数値に変換する Tad=7.63uSec
// 出力 0-9の数値
//******************************************************************************
void init_ADC(void){ //ADC初期設定
ADCON0bits.ADCS = 0; //ADC clk is Fosc
ADCLKbits.ADCCS = 0x3f; //ADC conversion clk is Fosc/16=16.777224/128=131kHz(7.63uSec)
ADREFbits.ADNREF = 0; //Vref- is VSS
ADREFbits.ADPREF = 0; //Vref+ is VDD
ADPCH = 0x11; //ANC1 入力
ADCON0bits.ADFM0 = 0; //ADC出力フォーマット:左詰
ADCON0bits.ADCONT = 0; //ADGO is cleared upon completion of each conversion trigger
ADCON0bits.ADON = 1; //ADS is enable
}
//******************** ADC開始 ******************************
// 入力 adc_ch(1-7)
// 処理 入力電圧から0-9の数値に変換する
// 出力 ad_number(0-9)
//******************************************************************************
unsigned char start_ADC(unsigned char adc_ch){ //ADC開始
unsigned char ad_number;
ADPCH = 0x10 + adc_ch; //入力adc_chをセット
ADCON0bits.ADGO = 1; //ADCスタート
while(ADCON0bits.ADGO == 1){} //AD変換完了を待つ
if(ADRESH < 14) ad_number = 0;
else if(ADRESH < 42) ad_number = 1;
else if(ADRESH < 70) ad_number = 2;
else if(ADRESH < 99) ad_number = 3;
else if(ADRESH < 127) ad_number = 4;
else if(ADRESH < 155) ad_number = 5;
else if(ADRESH < 184) ad_number = 6;
else if(ADRESH < 212) ad_number = 7;
else if(ADRESH < 240) ad_number = 8;
else ad_number = 9;
return ad_number;
}
//*************************** 周波数設定1 **************************************
// 入力 frequency(1Hz-1.048575Hz),CLC3OUT(2.097152MHz)
// freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1;
// 処理 NCOに周波数を設定,表示する
// 出力 frequency,freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1
//******************************************************************************
void set_frequency1(void){ //周波数設定1
unsigned char nco_u,nco_h,nco_l;
NCO1CLKbits.N1CKS = 4; //NCO入力:CLC3OUT
nco_u = (unsigned char)((frequency >> 16) & 0x0000000f);
nco_h = (unsigned char)((frequency >> 8) & 0x000000ff);
nco_l = (unsigned char)(frequency & 0x000000ff);
NCO1INCU = nco_u; //NCOに値を設定
NCO1INCH = nco_h; //
NCO1INCL = nco_l; //
display_normal(); //LCD1行目に[ -- FREQUENCY --]を表示
display_frequency(); //表示
}
//*************************** 周波数設定2 **************************************
// 入力 frequency(1.048576MHz-2.097151MHz),CLC2OUT(4.1943056MHz)
// freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1;
// 処理 NCOに周波数を設定,表示する
// 出力 frequency,freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1
//******************************************************************************
void set_frequency2(void){ //周波数設定2
unsigned long frequency2;
unsigned char nco_u,nco_h,nco_l;
NCO1CLKbits.N1CKS = 3; //NCO入力:CLC2OUT
frequency2 = frequency >> 1; //frequency/2
nco_u = (unsigned char)((frequency2 >> 16) & 0x0000000f);
nco_h = (unsigned char)((frequency2 >> 8) & 0x000000ff);
nco_l = (unsigned char)(frequency2 & 0x000000ff);
NCO1INCU = nco_u; //NCOに値を設定
NCO1INCH = nco_h; //
NCO1INCL = nco_l; //
display_normal(); //LCD1行目に[ -- FREQUENCY --]を表示
display_frequency(); //表示
}
//*************************** 周波数設3 **************************************
// 入力 frequency(2.097152MHz-4.1943055MHz),CLC1OUT(8.388608MHz)
// freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1;
// 処理 NCOに周波数を設定,表示する
// 出力 frequency,freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1
//******************************************************************************
void set_frequency3(void){ //周波数設定3
unsigned long frequency3;
unsigned char nco_u,nco_h,nco_l;
NCO1CLKbits.N1CKS = 2; //NCO入力:CLC1OUT
frequency3 = frequency >> 2; //frequency/4
nco_u = (unsigned char)((frequency3 >> 16) & 0x0000000f);
nco_h = (unsigned char)((frequency3 >> 8) & 0x000000ff);
nco_l = (unsigned char)(frequency3 & 0x000000ff);
NCO1INCU = nco_u; //NCOに値を設定
NCO1INCH = nco_h; //
NCO1INCL = nco_l; //
display_normal(); //LCD1行目に[ -- FREQUENCY --]を表示
display_frequency(); //表示
}
//*************************** 周波数設定4 **************************************
// 入力 frequency(4.1943056MHz-8.388607Hz),Fosc(16.777224MHz)
// freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1;
// 処理 NCOに周波数を設定,表示する
// 出力 frequency,freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1
//******************************************************************************
void set_frequency4(void){ //周波数設定4
unsigned long frequency4;
unsigned char nco_u,nco_h,nco_l;
NCO1CLKbits.N1CKS = 0; //NCO入力:Fosc
frequency4 = frequency >> 3; //frequency/8
nco_u = (unsigned char)((frequency4 >> 16) & 0x0000000f);
nco_h = (unsigned char)((frequency4 >> 8) & 0x000000ff);
nco_l = (unsigned char)(frequency4 & 0x000000ff);
NCO1INCU = nco_u; //NCOに値を設定
NCO1INCH = nco_h; //
NCO1INCL = nco_l; //
display_normal(); //LCD1行目に[ -- FREQUENCY --]を表示
display_frequency(); //表示
}
//*************************** 周波数設定 **************************************
// 入力 frequency
// freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1;
// 処理 NCOに周波数を設定,表示する
// 出力 frequency,freq_no7,freq_no6,freq_no5,freq_no4,freq_no3,freq_no2,freq_no1
//******************************************************************************
void set_frequency(void){ //周波数設定
unsigned long temp_frequency;
unsigned char adc_ch;
for(adc_ch=1; adc_ch<8; adc_ch++){
switch(adc_ch){
case 1: freq_no1 = start_ADC(adc_ch); break;
case 2: freq_no2 = start_ADC(adc_ch); break;
case 3: freq_no3 = start_ADC(adc_ch); break;
case 4: freq_no4 = start_ADC(adc_ch); break;
case 5: freq_no5 = start_ADC(adc_ch); break;
case 6: freq_no6 = start_ADC(adc_ch); break;
case 7: freq_no7 = start_ADC(adc_ch); break;
}
}
temp_frequency = 1000000*freq_no7 + 100000*freq_no6 + 10000*freq_no5 + 1000*freq_no4 + 100*freq_no3 + 10*freq_no2 + freq_no1; //
// test_display_decimal(temp_frequency); //TEST バイナリデーターを10進で表示する
// __delay_ms(100); //TEST Delay 40ms
if(temp_frequency != frequency){ //前の値と異なる場合のみレジスタ設定および表示を行う
frequency = temp_frequency;
if(frequency == 0){ //frequencyが0のとき警告を表示する
display_higher(); //LCD1行目に[set higher frequency]を表示
display_frequency(); //表示
}
else if(frequency < 0x100000) set_frequency1(); //周波数設定1(1Hz -1.048575MHz)
else if(frequency < 0x200000) set_frequency2(); //周波数設定2(1.048576MHz -2.097151MHz)
else if(frequency < 0x400000) set_frequency3(); //周波数設定3(2.097152MHz -4.1943055MHz)
else if(frequency < 0x800000) set_frequency4(); //周波数設定4(4.1943056MHz-8.388607MHz)
else if(frequency > 0x7fffff){ //frequencyが8388607よりも大きいとき警告を表示する
display_lower(); //LCD1行目に[set lower frequency]を表示
display_frequency(); //表示
}
}
}
//***************************** MAIN Routine **********************************
//******************************************************************************
void main(void) {
init_OSC(); //オシレータ初期設定
init_port(); //PORT初期設定
init_LCD(); //LCD初期設定
init_NCO(); //NCO初期設定
init_CLC1(); //CLC1初期設定
init_CLC2(); //CLC2初期設定
init_CLC3(); //CLC3初期設定
init_ADC(); //ADC初期設定
while(1){
set_frequency(); //周波数設定
}
}
ソースファイル
frequency_synthesizer_2019_6_12
1 ファイル 403.45 KB