Si5351Aの実験その5(位相制御)
2017年10月16日 JH7UBC
3チャンネルクロックジェネレータSi5351Aの出力の位相を制御する方法について説明します。
(JA2GQPブログの記事とTj Labのサイトの記事を参考にしました。)
Si5351のレジスタマップAN619の10ページを参照します。
出力信号の位相(遅延時間)を決めるのは、レジスタ165(CLK0),166(CLK1),167(CLK2)の値でその値は、次の式で決定します。
CLKx_PHOFF [6:0] = Round(DesiredOffset (sec) * 4 * Fvco)
N = CLKx_PHOFF[6:0], dt = Desired Offset(delay time)とおくと
N= dt * 4 * Fvco (1) (0<= N <= 127,FvcoはPLLの周波数)
遅延時間dtが決まれば、設定値Nを得ることができます。
今回は、単純化のために位相を90度遅らせる(遅延時間は4分の1周期)ことにします。
出力の周波数をFoutとすると周期T=1/Foutで
dt = T/4 = 1/(4*Fout) (2)
(2)を(1)に代入すると
N = 1/(4*Fout) * 4 * Fvco = Fvco/Fout となります。(ただし、Nは整数で127以下)
今回の実験では、PLLの周波数Fvco=900MHz,出力周波数Fout=10MHz,位相90度(遅延時間T/4)とすると
N=900/10=90 となります。
Si5351Aの実験3(マルチチャンネル化)のスケッチを利用して実験します。
PLLAに分周期MS0,MS1を接続し、CLK0とCLK1に10MHzを出力します。
CLK0は、遅延0,CLK1はT/4遅延します。
Arduino UNOにスケッチを書き込み、出力波形を観測しました。(青がCLK0,赤がCLK1)
4分の1周期位相がずれることが確認できました。
Nの値を変えることによって遅延時間を変えることができます。
回路図です。秋月電子のI2C電圧レベル変換モジュールPCA9306をArduinoとSi5351Aの間に入れました。
Si5351Aだけの接続なら3.3Vに直接接続してOKです。
ブレッドボードです。
参考までに実験に使ったスケッチです。
Nは、スケッチの中では、dividerです。
/* * Si5351A 位相制御test * 2017.10.10 * JH7UBC Keiji Hata * 秋月電子のSi5351Aモジュール使用 */ #include <Wire.h> #define Si5351A_ADDR 0x60 #define OUTPUT_CTRL 3 #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 uint32_t frequency; const uint32_t XtalFreq = 25000000; uint32_t P1; uint32_t P2; uint32_t P3; uint32_t PllFreq; uint32_t l; float f; uint8_t mult; uint32_t num; uint32_t denom; uint32_t divider; char PLL; uint8_t PLL_ADDR; uint8_t MS_ADDR; void setup(){ Wire.begin(); // Arduino is Master Si5351_init(); //Si5351 initialize //PLLAのセット 900MHz,CLK0=10MHz frequency = 10000000; divider = 900000000 / frequency; if (divider % 2) divider--; PLL_Set('A',frequency,divider); //CLK0の設定 Si5351_write(CLK0_CTRL,0x4C); //CLK0 Sorce PLLA MS_Set(0,divider); Si5351_write(CLK0_PHOFF,0);//CLK0 delay 0 //CLK1の設定 Si5351_write(CLK1_CTRL,0x4C); //CLK1 Sorce PLLA MS_Set(1,divider); Si5351_write(CLK1_PHOFF,divider);//CLK1 delay T/4 (90degree) Si5351_write(PLL_RESET,0xA0); //Reset PLLA and PLLB } void loop(){ } //Si5351のレジスタに1バイトデータを書き込む。 void Si5351_write(byte Reg , byte Data) { Wire.beginTransmission(Si5351A_ADDR); Wire.write(Reg); Wire.write(Data); Wire.endTransmission(); } //Si5351Aの初期化 void Si5351_init(){ Si5351_write(OUTPUT_CTRL,0xFF); //Disable Output Si5351_write(CLK0_CTRL,0x80); //CLOCK0 Power down Si5351_write(CLK1_CTRL,0x80); //CLOCK1 Power down Si5351_write(CLK2_CTRL,0x80); //CLOCK2 Power down Si5351_write(XTAL_LOAD_C,0x92); //Crystal Load Capasitance=8pF Si5351_write(PLL_RESET,0xA0); //Reset PLLA and PLLB Si5351_write(CLK0_CTRL,0x4F); //CLOCK0 Power up Si5351_write(CLK1_CTRL,0x4F); //CLOCK0 Power up // Si5351_write(CLK2_CTRL,0x4F); //CLOCK0 Power up Si5351_write(OUTPUT_CTRL,0xFC); //Enable CLOCK0,CLOCK1 } //PLLの設定 void PLL_Set(char Pll,uint32_t Freq,uint32_t Div){ PllFreq = Div * Freq; mult = PllFreq / XtalFreq; l = PllFreq % XtalFreq; f = l; f *= 1048575; f /= XtalFreq; num = f; denom = 1048575; P1 = (uint32_t)(128 * ((float)num /(float)denom)); P1 = (uint32_t)(128 * (uint32_t)(mult) + P1 - 512); P2 = (uint32_t)(128 * ((float)num / (float)denom)); P2 = (uint32_t)(128 * num -denom * P2); P3=denom; if (Pll == 'A') { PLL_ADDR = MSNA_ADDR; }else { PLL_ADDR = MSNB_ADDR; } Parameter_write(PLL_ADDR,P1,P2,P3); } //MultiSynth(分周器)のセット void MS_Set(uint8_t MS_No,uint32_t Div){ P1 = 128 * Div - 512; P2 = 0; P3 = 1; switch(MS_No){ case 0: MS_ADDR = MS0_ADDR; break; case 1: MS_ADDR = MS1_ADDR; break; case 2: MS_ADDR = MS2_ADDR; break; default: MS_ADDR = MS0_ADDR; } Parameter_write(MS_ADDR,P1,P2,P3); } //レジスタにパラメータP1,P2,P3を書き込む。 void Parameter_write(uint8_t REG_ADDR,uint32_t Pa1,uint32_t Pa2,uint32_t Pa3) { Si5351_write(REG_ADDR + 0,(Pa3 & 0x0000FF00) >> 8); Si5351_write(REG_ADDR + 1,(Pa3 & 0x000000FF)); Si5351_write(REG_ADDR + 2,(Pa1 & 0x00030000) >> 16); Si5351_write(REG_ADDR + 3,(Pa1 & 0x0000FF00) >> 8); Si5351_write(REG_ADDR + 4,(Pa1 & 0x000000FF)); Si5351_write(REG_ADDR + 5,((Pa3 & 0x000F0000) >> 12) | ((Pa2 & 0X000F0000) >> 16)); Si5351_write(REG_ADDR + 6,(Pa2 & 0x0000FF00) >> 8); Si5351_write(REG_ADDR + 7,(Pa2 & 0x000000FF)); } |