SparkFun Clock Generator 5P49V60 (Qwiic) Hookup Guide
Example 3: Integer and Fractional Divider Calculation
In this example, the division of the reference clock and the division for the frequency output dividers of each clock are set manually. Click on File > Examples > SparkFun Clock 5P49V60 Arduino Library > Example3_int_and_frac_divider_calc to open the example. It's especially beneficial to do this manually when applying fractional values to the frequency dividers. These values often have remainders that must be rounded and thus become the round-off error of your clock output in parts per million (ppm). Knowing this error value could be important to your application. To determine the division values requires some simple math. First, as in the previous two examples the correct libraries are imported and the microcontroller connects to the SparkFun Clock Generator using its' default address: 0x6A
.
language:c
void setup(){
Wire.begin();
Serial.begin(115200);
if (clockGen.begin() == true){
Serial.println("Clock Generator Ready.");
}
else {
Serial.println("Could not communicate with the SparkFun Clock Generator.");
while(1);
}
As in the previous sections the voltage controlled oscillator is set to to 1600MHz (1.6GHz). However, the register value must be calculated with some simple math. Our desired input (1600MHz) divided by the frequency of the reference clock (16MHz) equals the divider value 100. Easy Peezy Lemon Squeezy...
language:c
1600/16 = 100
Now we set the register values in code.
language:c
// Fist, Setting the internal oscillator to a known value that makes for easy
// division: 1600MHz. 1600MHz/16MHz = 100
Serial.println("Setting Integer Divider.");
clockGen.setPllFeedbackIntDiv(100);
Serial.print("Integer Divider set to: ");
uint16_t fbVal = clockGen.readPllFeedBackIntDiv();
Serial.println(fbVal);
The formula for this calculation is in the example sketch's comments. Next the divider values for a frequency of 22MHz is calculated with a similar equation. Divide the voltage controlled oscillator's frequency from above (1600MHz) by two, then divide that value by the desired clock output (22MHz) to get the the clock's frequency output divider's value.
language:c
(1600/2)/22 = 36.3636
This divider value has a decimal and consequently will have two separate values to write to the SparkFun Clock Generator's registers. The first value is the integer portion (36) and the second value is the fractional portion (.36). The integer value can be set as is, but the fractional value first needs additional calculations to translate it into a value the SparkFun Clock Generator expects. To do that we multiply the fractional value by 224 and round that value to the closest integer. The decimal value is the clock output's rounding error in parts per million.
language:c
2^24 * .36 = 6039796.76
.76 = rounding error
76/ppm
Now we write these two values to their registers.
language:c
// Clock One -----------------------------------------------------
// To get 16MHz Output = (1600MHz/2)/22MHz = 36.3636
// Integer portion = 36
// Fractional portion = .36 -> Need to convert to a HEX value
// 2^24 * .36 = 6039796.76
// Round the value to closest integer = 6039797
clockGen.setIntDivOutOne(36);
clockGen.setFractDivFodOne(6039797);
Serial.print("FOD One Integer Divider: ");
Serial.println(clockGen.readIntDivOutOne());
Serial.print("FOD One Fractional Divider: ");
Serial.println(clockGen.readFractDivFodOne());
clockGen.muxPllToFodOne();
// There are many OUTPUT modes available for each clock - this example uses
// LVPECL (Low voltage Positive Emitter Coupled Logic) mode and terminates
// the clock with a 100Ohm resistance to GND.
clockGen.clockOneConfigMode(LVPECL_MODE);
clockGen.clockOneControl(ENABLE);
// --------------------------------------------------------------
}
void loop(){
delay(1000);
}
The integer portion is set with clockGen.setIntiDivOutOne(36)
and the fractional portion is set with clockGen.setFractDivOut(6039796)
. These two values are then read back with their respective "read" functions: clockGen.readIntDivOutOne()
and clockGen.readFractDivFodOne()
. Next we pipe (multiplex) the VCO frequency to the frequency output divider we just set, set the signal type, and enable the clock. In the previous examples, all of the math was done behind the scenes but here doing the math may prove beneficial when needing to know the rounding error.