Ну и вот, что нам пишут:
It is possible for a PLL to become unresponsive (i.e., lose lock indefinitely) when it is dynamically reprogrammed or changed via the
serial port. Reprogramming/changing the N divider does not affect the PLL. Any change that causes the VCO frequency to change by
more than 250 ppm since Power-up, NVM download, or SOFT_RST requires the following special sequence of writes. Changes to the
following registers require the following special sequence of writes:
А это означает примерно, что при изменении частоты генератора более чем на 250 ppm, возможен срыв частоты.
А вот еще более конкретно:
Changes to
output frequencies without changing the PLL settings are desired.
То есть, изменение частоты желательно производить без изменения частоты PLL. Так что соваться туда скорее всего не следует.
Ну и алгоритм. Скажем частота PLL 13200000000, которую мы успешно задали. А нужно получить на выходе например 20 мгц. И как это сделать? Есть делитель, состоящий из числителя N_NUM и знаменателя N_DEN. И имеем два неизвестных. Придется одно значение, например знаменатель взять " с потолка", ну например - 536870912. Почему такое значение? Потому что это 20000000 в 16-ричной системе. Тогда числитель должен быть (13200000000/20000000)*536870912=354334801920. Имеем N_DEN=536870912, а N_NUM=354334801920. Дальше все просто.. Вот так это примерно выглядит:
/**************************** Функция управления частотой *****************************************/
void si5340aSetFrequency(unsigned long z)
{
//Определение переменных: pllFreq, XTALFreq, l, f, mult, num, denom, divider
uint64_t xtalFreq = XTAL_FREQ;
volatile uint64_t mult;
volatile uint64_t num;
volatile uint32_t denom=2147483648;
volatile uint64_t divider_1;
volatile uint64_t m_num;
volatile uint32_t m_denom = 201326592;
volatile uint64_t pllFreq = 13200000000;
divider_1 = pllFreq/xtalFreq; // Определяем значение делителя Pll.
if ((divider_1 & 1) != 0) divider_1--; // (короче делаем четным)
pllFreq = divider_1 * xtalFreq; // Считаем настоящее значение частоты, так как в значении делителя отброшены числа после запятой, кроме того, сделали значение четным.
m_num = pllFreq/ m_denom; //Значение числителя делителя PLL.
num=(pllFreq/z)*denom; //Значение числителя N_NUM.
setup_div(num, denom);
WriteByte (0x03, 0x0C, 0x01); // Update N0
setupPLL(m_num, m_denom);
WriteByte (0x02, 0x3F, 0x01); // Update M
Спать надо, может что напутал.. Завтра скорее всего буду в пути... Да, прикинул еще раз на калькуляторе..
Вроде что-то напутал. Но думаю идею поняли.