Si5351Aの実験その2(任意の周波数の発生)
2016年12月23日 JH7UBC
3CHクロックジェネレータSi5351Aで、任意の周波数を発生させる方法について説明します。
Arduino UNOとSi5351Aの接続は、前の記事と同じです。
このアルゴリズムは、JA2GQP局のブログに掲載されているsi5351a TFT VFOの記事の中の
Hans Summers氏のスケッチを参考にさせていただいています。
PLLの周波数は、600MHz〜900MHzですが、最大のfvco=900MHzに設定します。
目的の周波数(出力周波数)をfoutとすれば、分周器の値がd=fvco/fout(整数値)で決まります。
以下、各定数が下のように決定できます。
(カタログの出力周波数の定数a,b,cは、d,e,fと書き換えています。)
これをもとに7MHzを発生させるスケッチを書くと次のようになります。
オリジナルのuint32_t は、unsigmed longに、uint8_tは、unsigned intに書き換えました。
denomの値は、周波数の精度をあげるために、最大の 1048575とします。
スケッチのサイズは、2,486バイトです。
(frequencyの値を目的の周波数にします。ここでは、7MHzにしています。)
/* * EX-2 * 任意の周波数の発生 * 2016.12.23 * JH7UBC */ #include <Wire.h> #define Si5351A_ADDR 0x60 #define MSNA_ADDR 26 #define MS0_ADDR 42 #define CLK0_CTRL 16 #define OUTPUT_CTRL 3 #define PLL_RESET 177 #define XTAL_LC 183 unsigned long frequency = 7000000; //目的周波数 const unsigned long XtalFreq = 25000000; //水晶発振器の周波数 unsigned long divider; unsigned long PllFreq; unsigned int mult; unsigned long l; float f; unsigned long num; const unsigned long denom = 1048575; unsigned long P1; unsigned long P2; unsigned long P3; void setup() { Wire.begin(); // Arduino is Master. Si5351_write(OUTPUT_CTRL,0xFF); //Disable Output Si5351_write(CLK0_CTRL,0x80); //CLOCK0 Power down Si5351_write(XTAL_LC,0x92); //Crystal Load Capasitance=8pF divider = 900000000 / frequency; if (divider % 2) divider--; PLLA_set(); MS0_set(); Si5351_write(PLL_RESET,0xA0); //Reset PLLA and PLLB Si5351_write(CLK0_CTRL,0b01001111); //CLOCK0 Power up 8mA Si5351_write(OUTPUT_CTRL,0xFE); //Enable CLOCK0 } void loop() { } void Si5351_write(byte Reg , byte Data) { Wire.beginTransmission(Si5351A_ADDR); Wire.write(Reg); Wire.write(Data); Wire.endTransmission(); } void PLLA_set() { PllFreq = divider * frequency; mult = PllFreq / XtalFreq; l = PllFreq % XtalFreq; f = l; f *= denom; f /= XtalFreq; num = f; P1 = (unsigned long)(128 * ((float)num /(float)denom)); P1 = (unsigned long)(128 * (unsigned long)mult + P1 - 512); P2 = (unsigned long)(128 * ((float)num / (float)denom)); P2 = (unsigned long)(128 * num -denom * P2); P3=denom; Si5351_write(MSNA_ADDR + 0,(P3 & 0x0000FF00) >> 8); //MSNA_P3[15:8] Si5351_write(MSNA_ADDR + 1,(P3 & 0x000000FF)); //MSNA_P3[7:0] Si5351_write(MSNA_ADDR + 2,(P1 & 0x00030000) >> 16); //MSNA_P1[17:16] Si5351_write(MSNA_ADDR + 3,(P1 & 0x0000FF00) >> 8); //MSNA_P1[15:8] Si5351_write(MSNA_ADDR + 4,(P1 & 0x000000FF)); //MSNA_P1[7:0] Si5351_write(MSNA_ADDR + 5,((P3 & 0x000F0000) >> 12) | ((P2 & 0X000F0000) >> 16)); //MSNA_P3[19:16]MSNA_P2[19:16] Si5351_write(MSNA_ADDR + 6,(P2 & 0x0000FF00) >> 8); //MSNA_P2[15:8] Si5351_write(MSNA_ADDR + 7,(P2 & 0x000000FF)); //MSNA_P2[7:0] } void MS0_set() { P1 = 128 * divider - 512; P2 = 0; P3 = 1; Si5351_write(MS0_ADDR + 0,(P3 & 0x0000FF00) >> 8); //MS0_P3[15:8] Si5351_write(MS0_ADDR + 1,(P3 & 0x000000FF)); //MS0_P3[7:0] Si5351_write(MS0_ADDR + 2,(P1 & 0x00030000) >> 16); //MS0_P1[17:16] Si5351_write(MS0_ADDR + 3,(P1 & 0x0000FF00) >> 8); //MS0_P1[15:8] Si5351_write(MS0_ADDR + 4,(P1 & 0x000000FF)); //MS0_P1[7:0] Si5351_write(MS0_ADDR + 5,((P3 & 0x000F0000) >> 12) | ((P2 & 0X000F0000) >> 16)); //MS0_P3[19:16]MS0_P2[19:16] Si5351_write(MS0_ADDR + 6,(P2 & 0x0000FF00) >> 8); //MS0_P2[15:8] Si5351_write(MS0_ADDR + 7,(P2 & 0x000000FF)); //MS0_P2[7:0] } |
このスケッチで発生できるのは、500KHz〜150MHzです。
理由は、fvco=900MHzで、d+(e/f)が6〜1800だからです。
dividerの値を偶数としているのは、分周比が8以下のときは、8,6,のように偶数しか使えないので、
dividerをあらかじめ偶数にしているようです。
CLK0,CLK1,CLK2の出力のON/OFFは、レジスタ3で、
CLK0の出力強度は、レジスタ16のビット1と0で設定できます。
このスケッチでは、CLK0のbit1,0は、11で8mAです。
出力は7MHzで、およそ13dBm=20mWです。
10で6mA, 11dBm=12mW
01で 4mA, 7.2dBm=5.3mW
00で2mA,2.1dBm=1.6mW
です。
次は、マルチチャンネル化の実験です。