Attiny85, SI5351 via IDE ARDUINO

Projet:Contrôler très simplement un SI5351 avec un Attiny85 programmé via l’ide Arduino 1.8.7.
Attention testé jusqu’à version micronucleus 1.06 (1.6).

1.Matériel.

Commandé sur ebay: ATtiny85-20PU IC DIP-8 MCU Micro USB Development Programmer Board Pins TE769

2.Installation de l’IDE et des paquets.

D’après cette source: https://digistump.com/wiki/digispark/tutorials/connecting

Une fois l’ide arduino installé sur votre machine:

-Aller dans Fichier>Préférences

-Dans « url de gestionnaire de cartes supplémentaires »

-Ajouter « https://digistump.com/wiki/digispark/tutorials/connecting »

-Terminer en cliquant sur « Ok »

-Aller dans Outils>Types de cartes>Gestionnaire de cartes et chercher « Digistump » selectionner « Digistump AVR Boards » puis cliquer sur « Installer »

-Une fois installé, aller dans Outils>Types de cartes et sélectionner « Digispark  (Default – 16,5mhz) »

Voila, vous êtes prêt pour vos premiers tests.

3.Connexion au SI5351

4.Le code

#include <avr/pgmspace.h>
#include <Wire.h>

#define SI5351_i2c_bus_addr 0x60

#define SI5351_PLLA 0
#define SI5351_PLLB 1

void si5351_init()
{



  Wire.beginTransmission(SI5351_i2c_bus_addr);
  uint8_t reg_val;
  reg_val = Wire.endTransmission();

  if (reg_val == 0)
  {
    uint8_t status_reg = 0;
    do
    {
      status_reg = si5351_read(0);
    } while (status_reg >> 7 == 1);


    /* Disable all outputs setting CLKx_DIS high */
    si5351_write(3, 0xFF);

    // Initialize the CLK outputs according to flowchart in datasheet
    // First, turn them off
    si5351_write(16, 0x80);
    si5351_write(17, 0x80);
    si5351_write(18, 0x80);

    // Turn the clocks back on...
    si5351_write(16, 0x0c);
    si5351_write(17, 0x0c);
    si5351_write(18, 0x0c);

    /* Set the load capacitance for the XTAL */
    si5351_write(183, (0 << 6));
  }
}



void si5351_setupPLL(uint8_t mult, uint32_t num = 0, uint32_t denom = 1, bool pll = 0)//pll 1 = pllB default pllA
{
  uint32_t P1;       /* PLL config register P1 */
  uint32_t P2;       /* PLL config register P2 */
  uint32_t P3;       /* PLL config register P3 */


  P1 = (uint32_t)(128 * mult + floor(128 * ((float)num / (float)denom)) - 512);
  P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num / (float)denom)));
  P3 = denom;

  uint8_t baseaddr = (pll == 0 ? 26 : 34);

  /* The datasheet is a nightmare of typos and inconsistencies here! */
  si5351_write( baseaddr,   (P3 & 0x0000FF00) >> 8);
  si5351_write( baseaddr + 1, (P3 & 0x000000FF));
  si5351_write( baseaddr + 2, (P1 & 0x00030000) >> 16);
  si5351_write( baseaddr + 3, (P1 & 0x0000FF00) >> 8);
  si5351_write( baseaddr + 4, (P1 & 0x000000FF));
  si5351_write( baseaddr + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16) );
  si5351_write( baseaddr + 6, (P2 & 0x0000FF00) >> 8);
  si5351_write( baseaddr + 7, (P2 & 0x000000FF));

  /* Reset both PLLs */
  si5351_write(177, (1 << 7) | (1 << 5) );

}


void si5351_setupMultisynth(uint8_t output, uint32_t div, uint32_t num = 0, uint32_t denom = 1, bool pllSource = 0) //pllsource 1 = pllB default pllA
{
  uint32_t P1;       /* Multisynth config register P1 */
  uint32_t P2;       /* Multisynth config register P2 */
  uint32_t P3;       /* Multisynth config register P3 */

  if (num == 0)
  {
    /* Integer mode */
    P1 = 128 * div - 512;
    P2 = num;
    P3 = denom;
  }
  else
  {
    /* Fractional mode */
    P1 = (uint32_t)(128 * div + floor(128 * ((float)num / (float)denom)) - 512);
    P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num / (float)denom)));
    P3 = denom;
  }

  /* Get the appropriate starting point for the PLL registers */
  uint8_t baseaddr = 0;
  switch (output)
  {
    case 0:
      baseaddr = 42;
      break;
    case 1:
      baseaddr = 50;
      break;
    case 2:
      baseaddr = 58;
      break;
  }

  /* Set the MSx config registers */
  si5351_write( baseaddr,   (P3 & 0x0000FF00) >> 8);
  si5351_write( baseaddr + 1, (P3 & 0x000000FF));
  si5351_write( baseaddr + 2, (P1 & 0x00030000) >> 16); /* ToDo: Add DIVBY4 (>150MHz) and R0 support (<500kHz) later */
  si5351_write( baseaddr + 3, (P1 & 0x0000FF00) >> 8);
  si5351_write( baseaddr + 4, (P1 & 0x000000FF));
  si5351_write( baseaddr + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16) );
  si5351_write( baseaddr + 6, (P2 & 0x0000FF00) >> 8);
  si5351_write( baseaddr + 7, (P2 & 0x000000FF));

  /* Configure the clk control and enable the output */
  uint8_t clkControlReg = 0x0F;                             /* 8mA drive strength, MS0 as CLK0 source, Clock not inverted, powered up */
  if (pllSource) clkControlReg |= (1 << 5);
  if (num == 0) clkControlReg |= (1 << 6);                  /* Integer mode */
  switch (output)
  {
    case 0:
      si5351_write(16, clkControlReg);
      break;
    case 1:
      si5351_write(17, clkControlReg);
      break;
    case 2:
      si5351_write(18, clkControlReg);
      break;
  }
}

uint8_t si5351_enable()
{
  si5351_write(3,0x00);
}

uint8_t si5351_write(uint8_t addr, uint8_t data)
{
  Wire.beginTransmission(SI5351_i2c_bus_addr);
  Wire.write(addr);
  Wire.write(data & 0xFF);
  return Wire.endTransmission();
}

uint8_t si5351_read(uint8_t addr)
{
  uint8_t reg_val = 0;

  Wire.beginTransmission(SI5351_i2c_bus_addr);
  Wire.write(addr);
  Wire.endTransmission();

  Wire.requestFrom(SI5351_i2c_bus_addr, (uint8_t)1);

  while (Wire.available())
  {
    reg_val = Wire.read();
  }

  return reg_val;
}

void setup()
{

  Wire.begin();
  si5351_init();
  delay(100);
  si5351_setupPLL(34, 82, 125, SI5351_PLLA);
  delay(100);
  si5351_setupPLL(32, 16, 125, SI5351_PLLB);
  delay(100);

  
  si5351_setupMultisynth(0, 28, 68, 141, SI5351_PLLB);
  delay(100);
  si5351_setupMultisynth(1, 16, 0, 1, SI5351_PLLB);
  delay(100);
  si5351_setupMultisynth(2, 6, 0, 1, SI5351_PLLA);
  delay(100);

  
  si5351_enable();
  delay(100);
 
}


void loop()
{

}

 

5.Calculer ces PLL

Source: https://learn.adafruit.com/adafruit-si5351-clock-generator-breakout/wiring-and-test

Télécharger et install le ClockBuilder: http://www.adafruit.com/downloads/ClockBuilderDesktopSwInstallSi5351.zip

Lancer le, séléctionner « SI55351A on Timming TollStick », « Ok », Entrer la ou les fréquences :

-du chrystall soit 25 ou 27 mhz

-Cocher une, deux ou trois premières enable channel

-entrer la ou les fréquences de sortie souhaitées

Puis cliquez sur « Create Frequency plan » et enfin sur « View Plan Détails » juste en dessous.

J’obtiens:

PLL A
 Input Frequency (MHz) = 25,000000000
 VCO Frequency (MHz) =  866,400000000
 Feedback Divider = 34  82/125
 SSC disabled

PLL B
 Input Frequency (MHz) = 25,000000000
 VCO Frequency (MHz) =  803,200000000
 Feedback Divider = 32  16/125

Output Clocks
Channel 0
 Output Frequency (MHz) = 28,200000000
 Multisynth Output Frequency (MHz) = 28,200000000
 Multisynth Divider = 28  68/141
 R Divider = 1
 PLL source = PLLB
 Initial phase offset (ns) = 0,000
 Powered down = No
 Inverted = No
 Drive Strength = b11
 Disable State = Low
 Clock Source = b11
Channel 1
 Output Frequency (MHz) = 50,200000000
 Multisynth Output Frequency (MHz) = 50,200000000
 Multisynth Divider = 16
 R Divider = 1
 PLL source = PLLB
 Initial phase offset (ns) = 0,000
 Powered down = No
 Inverted = No
 Drive Strength = b11
 Disable State = Low
 Clock Source = b11
Channel 2
 Output Frequency (MHz) = 144,400000000
 Multisynth Output Frequency (MHz) = 144,400000000
 Multisynth Divider = 6
 R Divider = 1
 PLL source = PLLA
 Initial phase offset (ns) = 0,000
 Powered down = No
 Inverted = No
 Drive Strength = b11
 Disable State = Low
 Clock Source = b11

 

Dans la partie setup de mon code j’aurai:

 si5351_setupPLL(34, 82, 125, SI5351_PLLA); 

Soit 25MHz * (m + n/d) = 25MHz * (34 + 82/125) =  866,400000000Mhz pour  PLLA
si5351_setupPLL(32, 16, 125, SI5351_PLLB); 

Soit 25MHz * (m + n/d) = 25MHz * (32 + 16/125) =  803,200000000Mhz  pour  PLLB

Puis on redivise vers les sorties

si5351_setupMultisynth(0, 28, 68, 141, SI5351_PLLB); 

=>803,2 / (28 + 68/141) = 28,2mhz
delay(100); si5351_setupMultisynth(1, 16, 0, 1, SI5351_PLLB); 

=>803,2 / (16 + 0/1) = 50,2mhz
delay(100); si5351_setupMultisynth(2, 6, 0, 1, SI5351_PLLA); 

=>866,4 / (6 + 0/1) = 144,4mhz

Enfin, on active les sorties:

 si5351_enable();

 

 

 

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.