同ブログ関連記事:
参考サイト
●Tj Lab サイト
●JA2GQP局ブログ
●JH7UBC局ブログ
●I2C 通信について
●1602 LCDについて
90度位相シフト
回路図
プログラム Arduino IDE【ボード:Raspberry Pi Pico】
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f, 16, 2);//LCDアドレス0x3f
//LiquidCrystal_I2C lcd(0x27, 16, 2);
//////////////////////////
// Si5351A
//////////////////////////
#define Si5351A_ADDR 0x60
#define CLK0_CTRL 16
#define CLK1_CTRL 17
#define CLK2_CTRL 18
#define MSNA_ADDR 26
#define MSNB_ADDR 34
#define MS0_ADDR 42
#define MS1_ADDR 50
#define MS2_ADDR 58
#define CLK0_PHOFF 165
#define CLK1_PHOFF 166
#define PLL_RESET 177
#define XTAL_LOAD_C 183
//////////////////////////
// system clock
//////////////////////////
const unsigned long XtalFreq = 25000000;
//////////////////////////
// I/O assign
//////////////////////////
#define ENC_A 13 //Rotary encoder A
#define ENC_B 14 //Rotary encoder B
#define SW_STEP 15 // Step SW
volatile uint8_t old_value = 0x11;
volatile uint8_t value = 0;
volatile uint8_t D;
volatile int8_t count = 0;
//////////////////////////
// Register set
//////////////////////////
const long LOW_FREQ = 7000000; // lower frequency limit
const long HI_FREQ = 7200000; // upper frequency limit
unsigned long FREQ = 7000000; // default frequency
unsigned long FREQ_OLD = FREQ; // old frequency
int STEP = 1000; // STEP(default)
String freqt = String(FREQ);
String fH_old = "";
String fM_old = "";
String fL_old = "";
//////////////////////////
// Rotal encorder
//////////////////////////
void rotary(){
value = (digitalRead(ENC_B)<<1) | digitalRead(ENC_A);
if(old_value != value){
D = ((old_value << 1) ^ value) & 3;
if(D < 2){
count += 1;
}else{
count -= 1;
}
if(count >= 4){
FREQ += STEP;
count = 0;
}else if(count <= -4){
FREQ -= STEP;
count = 0;
}
FREQ = constrain(FREQ,LOW_FREQ,HI_FREQ); //VFOの下限と上限を超えないように
old_value = value;
}
}
void setup()
{
Wire.setSDA(16); //SDA
Wire.setSCL(17); //SCL
Wire.begin();
si5351_init();
freq_set(FREQ);
pinMode(SW_STEP,INPUT_PULLUP); // STEP SW pullup
attachInterrupt(ENC_A, rotary, CHANGE);
attachInterrupt(ENC_B, rotary, CHANGE);
lcd.init();
lcd.backlight();
lcd.clear();
Freq_Disp(FREQ);
Step_Disp();
}
//------------- Main program -------------------
void loop(){
if(digitalRead(SW_STEP) == LOW){Set_Step();}
if(FREQ != FREQ_OLD){
freq_set(FREQ);
Freq_Disp(FREQ);
FREQ_OLD = FREQ;
}
delay(10);
}
//周波数表示
void Freq_Disp(long frequency){
freqt = String(frequency);
String fH = freqt.substring(0,1);
String fM = freqt.substring(1,4);
String fL = freqt.substring(4,6);
lcd.setCursor(3,0);
if (STEP == 10)lcd.print("10Hz");
if (STEP == 100)lcd.print("100Hz");
if (STEP == 1000)lcd.print("1KHz");
if (STEP == 10000)lcd.print("10KHz");
//MHzの表示
lcd.setCursor(3,1);
lcd.print(fH);
fH_old = fH;
//KHzの表示
lcd.setCursor(4,1);
lcd.print(fM);
fM_old = fM;
//Hzの表示
lcd.setCursor(7,1);
lcd.print(fL);
fL_old = fL;
}
//STEP表示
void Step_Disp(){
lcd.setCursor(3, 0);
if (STEP == 10)lcd.print("10Hz");
if (STEP == 100)lcd.print("100Hz");
if (STEP == 1000)lcd.print("1KHz");
if (STEP == 10000)lcd.print("10KHz");
}
//STEP切り替え
void Set_Step(){
if (STEP == 10){
STEP = 10000;
}else{
STEP /= 10;
}
delay(10);
Step_Disp();
while(digitalRead(SW_STEP) == LOW){
delay(10);
}
}
//---------- si5351a register write 1 byte----------
void cmd_si5351(byte Reg , byte Data){
Wire.beginTransmission(Si5351A_ADDR);
Wire.write(Reg);
Wire.write(Data);
Wire.endTransmission();
}
//---------- si5351A initialyze ----------
void si5351_init(){
cmd_si5351(XTAL_LOAD_C,0b10010010); // CL=8pF
cmd_si5351(CLK0_CTRL,0x80); // Disable CLK0
cmd_si5351(CLK1_CTRL,0x80); // Disable CLK1
cmd_si5351(PLL_RESET,0xA0); // Reset PLL_A
cmd_si5351(CLK0_CTRL,0x4F); // Enable CLK0 (MS0=Integer Mode, Source=PLL_A)
cmd_si5351(CLK1_CTRL,0x4F); // Enable CLK1 (MS1=Integer Mode, Source=PLL_A)
}
//---------- set frequency ----------
void freq_set(unsigned long freq){
// freq [Hz]
//
// fvco= fxtal*(a+b/c) ( a:15 -- 90, b:0 -- 1048575, c:1 -- 1048575 )
// freq= fvco /(a+b/c) ( a:4, 6--1800, b:0 -- 1048575, c:1 -- 1048575 )
//
// P1= 128*a + floor(128*b/c) - 512
// P2= 128*b - c*floor(128*b/c)
// P3= c
//
int k;
unsigned long M;
unsigned int R;
if(freq<1500) freq=1500; else if(freq>280000000) freq=280000000;
if( freq> 150000000){M=4; R=0;}
else if(freq>=63000000){M=6; R=0;}
else if(freq>=27500000){M=14; R=0;}
else if(freq>=13000000){M=30; R=0;}
else if(freq>= 6500000){M=62; R=0;}
else if(freq>= 3000000){M=126; R=0;}
else if(freq>= 1500000){M=280; R=0;}
else if(freq>= 700000){M=600; R=0;}
else if(freq>= 330000){M=1280; R=0;}
else if(freq>= 150000){M=1300; R=1;}
else if(freq>= 67000){M=1500; R=2;}
else if(freq>= 30300){M=1600; R=3;}
else if(freq>= 14000){M=1800; R=4;}
else if(freq>= 7000){M=1800; R=5;}
else if(freq>= 3500){M=1800; R=6;}
else{M=1800; R=7;}
freq*=M;
freq<<=R;
unsigned long c=0xFFFFF;
unsigned long a=freq/XtalFreq;
unsigned long b=(long)((double)(freq-a*XtalFreq)*(double)c/(double)XtalFreq);
unsigned long dd=(128*b)/c;
unsigned long P1=128*a+dd-512;
unsigned long P2=128*b-c*dd;
unsigned long P3=c;
//Set fvco of PLL_A
cmd_si5351(MSNA_ADDR+0,(P3>>8)&0xFF); //MSNA_P3[15:8]
cmd_si5351(MSNA_ADDR+1,P3&0xFF); //MSNA_P3[7:0]
cmd_si5351(MSNA_ADDR+2,(P1>>16)&0x03); //MSNA_P1[17:16]
cmd_si5351(MSNA_ADDR+3,(P1>>8)&0xFF); //MSNA_P1[15:8]
cmd_si5351(MSNA_ADDR+4,P1&0xFF); //MSNA_P1[7:0]
cmd_si5351(MSNA_ADDR+5,(P3>>12)&0xF0|(P2>>16)&0x0F);//MSNA_P3[19:16], MSNA_P2[19:16]
cmd_si5351(MSNA_ADDR+6,(P2>>8)&0xFF); //MSNA_P2[15:8]
cmd_si5351(MSNA_ADDR+7,P2&0xFF); //MSNA_P2[7:0]
// Set MS0, MS1
// a=M, b=0, c=1 ---> P1=128*M-512, P2=0, P3=1
if(M==4){
P1=0;
cmd_si5351(MS0_ADDR+0,0); //MS0_P3[15:8]
cmd_si5351(MS0_ADDR+1,1); //MS0_P3[7:0]
cmd_si5351(MS0_ADDR+2,0b00001100); //0,R0_DIV[2:0],MS0_DIVBY4[1:0],MS0_P1[17:16]
cmd_si5351(MS0_ADDR+3,0); //MS0_P1[15:8]
cmd_si5351(MS0_ADDR+4,0); //MS0_P1[7:0]
cmd_si5351(MS0_ADDR+5,0); //MS0_P3[19:16], MS0_P2[19:16]
cmd_si5351(MS0_ADDR+6,0); //MS0_P2[15:8]
cmd_si5351(MS0_ADDR+7,0); //MS0_P2[7:0]
cmd_si5351(MS1_ADDR+0,0); //MS1_P3[15:8]
cmd_si5351(MS1_ADDR+1,1); //MS1_P3[7:0]
cmd_si5351(MS1_ADDR+2,0b00001100); //0,R1_DIV[2:0],MS1_DIVBY4[1:0],MS1_P1[17:16]
cmd_si5351(MS1_ADDR+3,0); //MS1_P1[15:8]
cmd_si5351(MS1_ADDR+4,0); //MS1_P1[7:0]
cmd_si5351(MS1_ADDR+5,0); //MS1_P3[19:16], MS0_P2[19:16]
cmd_si5351(MS1_ADDR+6,0); //MS1_P2[15:8]
cmd_si5351(MS1_ADDR+7,0); //MS1_P2[7:0]
}else{
P1=128*M-512;
cmd_si5351(MS0_ADDR+0,0); //MS0_P3[15:8]
cmd_si5351(MS0_ADDR+1,1); //MS0_P3[7:0]
cmd_si5351(MS0_ADDR+2,(R<<4)&0x70|(P1>>16)&0x03);//0,R0_DIV[2:0],MS0_DIVBY4[1:0],MS0_P1[17:16]
cmd_si5351(MS0_ADDR+3,(P1>>8)&0xFF); //MS0_P1[15:8]
cmd_si5351(MS0_ADDR+4,P1&0xFF); //MS0_P1[7:0]
cmd_si5351(MS0_ADDR+5,0); //MS0_P3[19:16], MS0_P2[19:16]
cmd_si5351(MS0_ADDR+6,0); //MS0_P2[15:8]
cmd_si5351(MS0_ADDR+7,0); //MS0_P2[7:0]
cmd_si5351(MS1_ADDR+0,0); //MS1_P3[15:8]
cmd_si5351(MS1_ADDR+1,1); //MS1_P3[7:0]
cmd_si5351(MS1_ADDR+2,(R<<4)&0x70|(P1>>16)&0x03);//0,R1_DIV[2:0],MS1_DIVBY4[1:0],MS1_P1[17:16]
cmd_si5351(MS1_ADDR+3,(P1>>8)&0xFF); //MS1_P1[15:8]
cmd_si5351(MS1_ADDR+4,P1&0xFF); //MS1_P1[7:0]
cmd_si5351(MS1_ADDR+5,0); //MS1_P3[19:16], MS0_P2[19:16]
cmd_si5351(MS1_ADDR+6,0); //MS1_P2[15:8]
cmd_si5351(MS1_ADDR+7,0); //MS1_P2[7:0]
}
cmd_si5351(CLK0_PHOFF,0);
cmd_si5351(CLK1_PHOFF,M);
cmd_si5351(PLL_RESET,0xA0); // Reset PLL_A.
}
0 件のコメント:
コメントを投稿