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

です。

次は、マルチチャンネル化の実験です。

inserted by FC2 system