我基于Si5351a模塊制作了VFO。為了提高頻率的精度,我借助了GPS PPS信號。
Si5351a是制作精確時鐘的好芯片。但由于其晶體振蕩器電路的原因,存在一定的頻率誤差。將其頻率與GPS PPS進行比較,可以得到兩者之差的校正值。該頻率校正值可用于VFO校正。
原理圖
代碼
// 2025.01.07 pps OK, Sw1.2 OK 91%/62%
// 2024.12.09 tiny4kOLED
// 2024.11.16 Refered and Changed for R909-VFO-GPS
// added correction FREQ display
// changed store condition correction
// GITHUB https://github.com/Nobcha/R909-VFO-GPS
// D2:PPS,D5:2.5M,D7:EN,D0/RX:GPS/TX,LCD1602
//
// gps-calibration-5351
// https://github.com/csqwdy/gps-calibration-5351/blob/main/README.md
// 2022-03-06 Modified the encoder to work in signal change interrupt mode,
// Original was SQ1GU http://sq1gu.tobis.com.pl/en/dds
// include the library code:
#include <TINYGPS++.H>
// Change to OLED
#include
#include
#include
#include
#include
#include
#include
// The TinyGPS++ object
TinyGPSPlus gps;
Si5351 si5351;
#define control 2 // 1=button ,2=EP11 ,3=EP12
// Set up MCU pins
#define GPS_Enable 7
#define ppsPin 2 // GPS-PPS INT
#define re_sw A0
#define encoderPinA 4 // Signal change INT
#define encoderPinB 3 //
#define ledPin A1
#define func_sw A2 // SW1:<80, SW2:<250,
#define Freq2 1000000000ULL
volatile byte seqA = 0;
volatile byte seqB = 0;
volatile byte cnt1 = 0;
volatile byte cnt2 = 0;
volatile boolean right = false;
volatile boolean left = false;
volatile boolean button = false;
// configure variables
unsigned long XtalFreq = 100000000;
unsigned long XtalFreq_old = 100000000;
long stab;
long correction = 0;
byte stab_count = 44;
unsigned long mult = 0, Freq = 10000000;
int second = 0, minute = 0, hour = 0;
int zone = 9;
unsigned int tcount = 0;
unsigned int tcount2 = 0;
int validGPSflag = false;
char c;
boolean newdata = false;
boolean GPSstatus = true;
byte new_freq = 1;
unsigned long freq_step = 1000;
byte encoderOLD, menu = 6, band = 1, f_step = 1;
boolean time_enable = true;
unsigned long pps_correct_time;
byte pps_valid = 0;
byte correct_byte = 1;
float stab_float;
unsigned long button_on_time;
boolean oled_turn = 1;
boolean vfo_counter = true; // true vfo
boolean new_c_freq = 0;
boolean pps_error = 1;
int func_sw_value;
// prototype
void PPSinterrupt(void);
void timezone_on_oled(void);
void stab_on_oled(void);
void correct_freq(void);
void corr_on_oled(void);
void freq2_on_oled(void);
void step_on_oled(void);
void band_on_oled(void);
void time_on_oled(void);
void sat_on_oled(void);
void freq_on_oled(unsigned long);
void update_si5351a(void);
void correct_si5351a(void);
static void GPSproces(unsigned long);
void change_up(void);
void change_down(void);
void loglat_on_oled(void);
void vfo_fr_oled (void);
void date_on_oled(void);
//*******************************************************************************
// Timer 1 overflow intrrupt vector. Count 2.5MHz
//*******************************************************************************
ISR(TIMER1_OVF_vect)
{
mult++; //Increment multiplier
TIFR1 = (1 << TOV1); //Clear overlow flag
}
//*********************************************************************
// Judge the rotating direction
// Signal change interrupt
本文編譯自hackster.io