Статистика
Время:
Зарегистрированных: 89601
Последним зарегистрирован: ЕВГЕНИЙ563
Рекорд посещаемости: 12585
Групп пользователей: 4
 Группы:
[Admin] [Cоучастник] [Автор] [Модератор]
 Сейчас на сайте
 Всего: 660
 Гостей: 656
 Анонимных: 1
 Пользователей: 3
 Зарегистрированные:
PVB wolf_office otrazhenie
Forum Rules Внимание!

Внимание! Перед тем как создавать тему на форуме, воспользуйтесь поиском! Пользователь создавший тему, которая уже была, будет немедленно забанен! Читайте правила названия тем. Пользователи создавшие тему с непонятными заголовками, к примеру: "Помогите, Схема, Резистор, Хелп и т.п." также будут заблокированны навсегда. Пользователь создавший тему не по разделу форума будет немедленно забанен! Уважайте форум, и вас также будут уважать!

  Ответить Новая тема Новый опрос

> Дробный делитель на Si5351, В копилочку
AntonSor
Сообщение: # 709149   Nov 13 2016, 12:33 PM
Quote Post


Соучастник
*****

Группа: Cоучастник
Сообщений: 1506
Пользователь №: 25633
Регистрация: 28-October 07
Место жительства: Видное, МО



В известной библиотеке на qrp-labs.com есть пример работы с целочисленными делителями MultiSynth Si5351. Представляю Вашему вниманию модификацию этой библиотеки для работы с дробными делителями. Может быть, кому-нибудь пригодится.
Пример написан на MikroC для отладочной платы EasyAVR6. Микроконтроллер AtMEGA328P с кварцем на 8 МГц. Si5351 подключено к PC4 - SDA и PC5 - SCL, к ней кварц 25 МГц. Программа формирует на выходе 0 частоту 45 МГц, на выходе 1 - 44,56 МГц, на выходе 2 - 460 кГц.
CODE

///установка дробного делителя
void setupMultisynthFraq(char synth, unsigned long dividerA,unsigned long dividerB,unsigned long dividerC, char rDiv)
{
       unsigned long P1;                                        // Synth config addrister P1
       unsigned long P2;                                        // Synth config addrister P2
       unsigned long P3;                                        // Synth config addrister P3

       P1 = 128 * dividerA+(unsigned long)Floor(128*dividerB/dividerC) - 512;
       P2 = 128*dividerB-dividerC*(unsigned long)Floor(128*dividerB/dividerC);                                                        // P2 = 0, P3 = 1 forces an integer value for the divider
       P3 = dividerC;
       //все по даташиту
       
       i2cSendRegister(synth + 0,   (P3 & 0x0000FF00) >> 8);
       i2cSendRegister(synth + 1,  (P3 & 0x000000FF));
       i2cSendRegister(synth + 2,   ((P1 & 0x00030000) >> 16) | rDiv);
       i2cSendRegister(synth + 3,   (P1 & 0x0000FF00) >> 8);
       i2cSendRegister(synth + 4,   (P1 & 0x000000FF));
       i2cSendRegister(synth + 5,   ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
       i2cSendRegister(synth + 6,   (P2 & 0x0000FF00) >> 8);
       i2cSendRegister(synth + 7,  (P2 & 0x000000FF));
}

void si5351aSetFrequencyOut23(unsigned long frequency2,unsigned long frequency3)  //установка частоты на выходе 2 и 3 от PLLB
{
       unsigned long pllFreq;
       unsigned long xtalFreq = XTAL_FREQ;
       unsigned long fix.gif
       float f;
       char mult;
       unsigned long num;
       unsigned long denom;
       unsigned long divider;
       float dividerOut3;//дробный коэффициент деления третьего выхода
       unsigned long dividerA,dividerB,dividerC; //для третьего выхода - разбивка дроби
//        i2c_init();                                                // Initialise the I2C
       TWI_Init(100000);


       divider = 900000000 / frequency2;// Calculate the division ratio. 900,000,000 is the maximum internal
                                                                       // PLL frequency: 900MHz
       if (divider % 2) divider--;                // Ensure an even integer division ratio

       pllFreq = divider * frequency2;        // Calculate the pllFrequency: the divider * desired output frequency

       mult = pllFreq / xtalFreq;                // Determine the multiplier to get to the required pllFrequency
       l = pllFreq%xtalFreq;                        // It has three parts:
       f = fix.gif                                                        // mult is an integer that must be in the range 15..90
       f = f*1048575;                                        // num and denom are the fractional parts, the numerator and denominator
       f = f/xtalFreq;                                        // each is 20 bits (range 0..1048575)
       num = (unsigned long)f;                                                // the actual multiplier is  mult + num / denom
       denom = 1048575;                                // For simplicity we set the denominator to the maximum 1048575

                                                                       // Set up PLL A with the calculated multiplication ratio
       setupPLL(SI_SYNTH_PLL_B, mult, num, denom);
                                                                       // Set up MultiSynth divider 0, with the calculated divider.
                                                                       // The final R division stage can divide by a power of two, from 1..128.
                                                                       // reprented by constants SI_R_DIV1 to SI_R_DIV128 (see si5351a.h header file)
                                                                       // If you want to output frequencies below 1MHz, you have to use the
                                                                       // final R division stage
       setupMultisynth(SI_SYNTH_MS_1, divider, SI_R_DIV_1);

       dividerOut3=pllFreq/(128.0*frequency3);// для третьей частоты - будет с ошибкой  и учитываем деление на 128
/*                             longtostr(pllFreq,txt2);
   Lcd_Out(1,1,txt2);
          floattostr(dividerOut3,txt2);
   Lcd_Out(2,1,txt2);     */
   //нужна точность до герца - берем делитель C до 1/128/1000 прибл 1/65535, хотя хватило бы и 1/32768
      dividerC=65535;//принудительно
      dividerA=(unsigned long)dividerOut3;//округляем
      dividerB=(unsigned long)((dividerOut3-dividerA)*dividerC);//берем дробную часть, умножаем ее на знаменатель
   
       setupMultisynthFraq(SI_SYNTH_MS_2, dividerA,dividerB,dividerC, SI_R_DIV_128);         //делим на 128 для уменьшения джиттера и устанавливаем
                                                                       // Reset the PLL. This causes a glitch in the output. For small changes to
                                                                       // the parameters, you don't need to reset the PLL, and there is no glitch
      i2cSendRegister(SI_PLL_RESET, 0xA0);
                                                                       // Finally switch on the CLK0 output (0x4F)
                                                                       // and set the MultiSynth0 input to be PLL A
       i2cSendRegister(SI_CLK1_CONTROL, 0x4F | SI_CLK_SRC_PLL_B);
      //i2cSendRegister(SI_CLK2_CONTROL, 0x4F | SI_CLK_SRC_PLL_B);
        i2cSendRegister(SI_CLK2_CONTROL, 0x0F | SI_CLK_SRC_PLL_B);    //0f - потому что работаем в дробном режиме
//        i2c_exit();                                                // Exit I2C
TWI_Stop();



}


void main(){


si5351aSetFrequency(45000000);
si5351aSetFrequencyOut23(45000000-460000,460000);//частоты второй пч и ssb детектора

}



Это сообщение отредактировал AntonSor - Nov 13 2016, 12:35 PM

Присоединённый файл ( Кол-во скачиваний: 297 )
Присоединённый файл  Si5351Test_Frac_Divider_13_11_2016.zip
PMEmail Poster
Top
AntonSor
Сообщение: # 714793   Dec 6 2016, 10:04 PM
Quote Post


Соучастник
*****

Группа: Cоучастник
Сообщений: 1506
Пользователь №: 25633
Регистрация: 28-October 07
Место жительства: Видное, МО



Тут меня спросили:
QUOTE
Доброго времени суток. Нужна помощь в создании на основе этой микросхемы генератора до 150 мгц. Конкретнее : библиотека позволяющая обойти ограничение в 112.5 мгц по максимальной частоте. CLK1 и CLK2 не нужны. Вы можете как-то помочь?

Отвечаю фразой из даташита an619.pdf :
QUOTE

2.1.1. Selecting the Proper VCO Frequencies and Divide Ratios
The  general  criteria  below  may  be  used  to  set  the  VCO  frequencies.  This  is  a  general  model,  and  individual applications may require some modification.
1.  Valid Multisynth divider ratios are 4, 6, 8, and any fractional value between 8 + 1/1,048,575 and 900 + 0/1. This means that if any output is greater than 112.5 MHz (900 MHz/8), then this output frequency sets one of the VCO frequencies
---
4.1.3. Output Multisynth Divider Equations (150 MHz <Fout<=200 MHz)
Output frequencies greater than 150 MHz are available on Multisynths 0-5. For this frequency range a divide value of 4 must be used by setting
MSx_P1=0,
MSx_P2=0,
MSx_P3=1,
MSx_INT=1, and
MSx_DIVBY4[1:0]=11b.
Set the appropriate feedback Multisynth to generate f VCO =Fout*4

То есть, для выходной частоты от 112,5 до 200 МГц требуется использовать только целые четные делители, и для частоты выше 150 МГц отключать дробный делитель совсем (коэффициенты равны нулю) и делить лишь спецделителем на 4.
При изменении частоты VCO от 600 до 900 МГц, отключенном делителе Multisynth и доп делителе 4 частота на выходе будет от 150 до 225 МГц. Чтобы перекрыть участок от 112,5 до 150 МГц, примените делитель Multisynth 6 и отключите доп делитель - получится перекрытие от 100 до 150 МГц.
На самом деле, код для включения дополнительного делителя записывается туда же, куда и делитель Rdiv - в адрес synth + 2. Из библиотечного кода:
CODE

const SI_R_DIV_1=0;//                0b00000000;                        // R-division ratio definitions
const SI_R_DIV_2=16;//                0b00010000;
const SI_R_DIV_4=32;//                0b00100000;
const SI_R_DIV_8=48;//                0b00110000;
const SI_R_DIV_16=64;//                0b01000000;
const SI_R_DIV_32=80;//                0b01010000;
const SI_R_DIV_64=96;//                0b01100000;
const SI_R_DIV_128=112;//                0b01110000;

А для включения доп делителя на четыре здесь будет ещё и
CODE

const SI_R_DIV_1_DIV_4=12;//                0b00001100;

MSx_INT=1 находится в регистре SI_CLK0_CONTROL, а конкретно в 0x4F | SI_CLK_SRC_PLL_A . Если делитель целочисленный, там 4f, если дробный, то 0f. В исходной версии библиотеки 4f, так что это значение уже есть.
Для формирования этих значений регистров можно применить два подхода. Первый заключается в том, что используется библиотечная процедура записи целочисленного делителя и в ней устанавливается делитель, подобранный так, чтобы на выходе были P1=0.
В целочисленной библиотеке и так P2=0, P3=1. А P1 = 128 * divider - 512. Поэтому, чтобы был ноль, 128 * divider должно быть =512. Т.е. divider = 512/128 = 4.
Таким образом, для выходной частоты от 150 до 225 МГц используем следующие куски кода в процедуре si5351aSetFrequency:
CODE

setupPLL(SI_SYNTH_PLL_A, mult, num, denom); //устанавливаем частоту генератора VCO
setupMultisynth(SI_SYNTH_MS_0, 4, 0b00001100); //устанавливаем делитель в 4, чтобы P1=0 и включаем доп делитель на 4
i2cSendRegister(SI_PLL_RESET, 0xA0); //сброс ФАПЧ
i2cSendRegister(SI_CLK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A);//устанавливаем бит целого делителя

А для частот от 100 до 150 МГц напрямую и без затей указываем делитель 6 и без доп делителя
CODE

setupPLL(SI_SYNTH_PLL_A, mult, num, denom); //устанавливаем частоту генератора VCO
setupMultisynth(SI_SYNTH_MS_0, 6, 0);//устанавливаем делитель 6 и без всякого доп делителя
i2cSendRegister(SI_PLL_RESET, 0xA0); //сброс ФАПЧ
i2cSendRegister(SI_CLK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A);//устанавливаем бит целого делителя


Второй путь - это написание собственной процедуры отправки данных. Берем процедуру setupMultisynth и меняем отправку вот на что (для частот от 150 до 200 МГц)
CODE

       i2cSendRegister(synth + 0,0); //   (P3 & 0x0000FF00) >> 8) =0
       i2cSendRegister(synth + 1,1); //  (P3 & 0x000000FF))=1
       i2cSendRegister(synth + 2,0b00001100); //   ((P1 & 0x00030000) >> 16) | rDiv) для rDiv =0b00001100
       i2cSendRegister(synth + 3,0); //   (P1 & 0x0000FF00) >> 8)=0
       i2cSendRegister(synth + 4,0); //   (P1 & 0x000000FF))=0
       i2cSendRegister(synth + 5,0); //   ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16))=0
       i2cSendRegister(synth + 6,0); //   (P2 & 0x0000FF00) >> 8)=0
       i2cSendRegister(synth + 7,0); //  (P2 & 0x000000FF))=0
PMEmail Poster
Top
Ghost1
Сообщение: # 931354   Jul 8 2022, 08:56 PM
Quote Post


Фанат
******

Группа: Cоучастник
Сообщений: 3038
Пользователь №: 124432
Регистрация: 23-July 18




На qrp labe выложили сранение si5351 (silicon lab) и ms5351m (китайский чип) https://qrp-labs.com/synth/ms5351m.html


PMEmail Poster
Top
AntonSor
Сообщение: # 931370   Jul 9 2022, 10:22 AM
Quote Post


Соучастник
*****

Группа: Cоучастник
Сообщений: 1506
Пользователь №: 25633
Регистрация: 28-October 07
Место жительства: Видное, МО



Скололи, получается. Отлично, надо будет прикупить для пробы
PMEmail Poster
Top
Ghost1
Сообщение: # 931393   Jul 9 2022, 05:38 PM
Quote Post


Фанат
******

Группа: Cоучастник
Сообщений: 3038
Пользователь №: 124432
Регистрация: 23-July 18




Всё же не одно и тоже, есть проект https://create.arduino.cc/projecthub/CesarS...ersion-2-bfa619

того он чёт на  ms5351m не хочет работать, банды выше 100 мгц не переключаются энкодер работает только с дисплеем, на микруху вообще не влияет никак

со стоковой библиотекой от adafruit на демо примере ещё работает, а от etherkit надо переписывать

попробовал ручками выставить делитель на 4 (те 25 * 36 = 900 / 4 ) и какой слабый пик на 225 мгц, но зато 3 гармоника на 337,5 прям качает

мощность китайца макс 12 миллиампер
PMEmail Poster
Top
Ghost1
Сообщение: # 931400   Jul 9 2022, 11:14 PM
Quote Post


Фанат
******

Группа: Cоучастник
Сообщений: 3038
Пользователь №: 124432
Регистрация: 23-July 18




разобрался - почему-то не компилилось нормально через мобилу (ArduinoDroid) вечно ругался на незарегистрированные идентификаторы, перезалил через комп и всё заработало до 225 мгц проверил - работает, i2c адрес такой же 0x60
PMEmail Poster
Top

Настройки темы Ответить Шустрый ответ Новая тема Новый опрос


 




  banner DIPTRACE - САМЫЙ ЛУЧШИЙ ТАКСИРОВЩИК ПЕЧАТНЫХ ПЛАТ
Portal-X