论坛风格切换切换到宽版
  • 6290阅读
  • 28回复

我的5351板子回来了,哪位有源码我试试板子 [复制链接]

上一主题 下一主题
离线bd5il
发帖
347
只看该作者 20楼 发表于: 2018-06-05
jihaohhhhhhhhh
GSM:13970321055
地址:江西省上饶地区弋阳县港口镇92号
邮编:334414
离线BG8GFY
发帖
118
只看该作者 21楼 发表于: 2018-06-29
我有LPC2132的si5351程序,要吗?其实程序都是一样的,就是不同CPU的iic的驱动程序不同
[ 此帖被BG8GFY在2018-06-29 01:23重新编辑 ]
QQ807087233
13896060783
离线BG8GFY
发帖
118
只看该作者 22楼 发表于: 2018-06-29
#include "si5351a.h"

int main(void)
{
    si5351aSetFrequency(10000000);

    return 0;
}
QQ807087233
13896060783
离线BG8GFY
发帖
118
只看该作者 23楼 发表于: 2018-06-29
/
// Author: Hans Summers, 2015
// Website: http://www.hanssummers.com
//
// A very very simple Si5351a demonstration
// using the Si5351a module kit http://www.hanssummers.com/synth
// Please also refer to SiLabs AN619 which describes all the registers to use
//
#include <inttypes.h>
#include "i2cmaster.h"
#include "si5351a.h"

#define I2C_WRITE 0b11000000        // I2C address for writing to the Si5351A
#define I2C_READ  0b11000001        // I2C address for reading to the Si5351A

uint8_t i2cSendRegister(uint8_t reg, uint8_t data)
{
    uint8_t stts;

    i2c_start_wait(I2C_WRITE);

    stts = i2c_write(reg);
    if (stts) return 3;

    stts = i2c_write(data);
    if (stts) return 4;

    i2c_stop();    

    return 0;
}

uint8_t i2cReadRegister(uint8_t reg, uint8_t *data)
{
    uint8_t stts;

    i2c_start_wait(I2C_WRITE);

    stts = i2c_write(reg);
    if (stts) return 3;

    stts = i2c_rep_start(I2C_READ);
    if (stts) return 4;

    *data = i2c_readNak();

    i2c_stop();    

    return 0;
}

//
// Set up specified PLL with mult, num and denom
// mult is 15..90
// num is 0..1,048,575 (0xFFFFF)
// denom is 0..1,048,575 (0xFFFFF)
//
void setupPLL(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom)
{
    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 * ((float)num / (float)denom));
    P1 = (uint32_t)(128 * (uint32_t)(mult) + P1 - 512);
    P2 = (uint32_t)(128 * ((float)num / (float)denom));
    P2 = (uint32_t)(128 * num - denom * P2);
    P3 = denom;

    i2cSendRegister(pll + 0, (P3 & 0x0000FF00) >> 8);
    i2cSendRegister(pll + 1, (P3 & 0x000000FF));
    i2cSendRegister(pll + 2, (P1 & 0x00030000) >> 16);
    i2cSendRegister(pll + 3, (P1 & 0x0000FF00) >> 8);
    i2cSendRegister(pll + 4, (P1 & 0x000000FF));
    i2cSendRegister(pll + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
    i2cSendRegister(pll + 6, (P2 & 0x0000FF00) >> 8);
    i2cSendRegister(pll + 7, (P2 & 0x000000FF));
}

//
// Set up MultiSynth with integer divider and R divider
// R divider is the bit value which is OR'ed onto the appropriate register, it is a #define in si5351a.h
//
void setupMultisynth(uint8_t synth, uint32_t divider, uint8_t rDiv)
{
    uint32_t P1;                    // Synth config register P1
    uint32_t P2;                    // Synth config register P2
    uint32_t P3;                    // Synth config register P3

    P1 = 128 * divider - 512;
    P2 = 0;                            // P2 = 0, P3 = 1 forces an integer value for the divider
    P3 = 1;

    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));
}

//
// Switches off Si5351a output
// Example: si5351aOutputOff(SI_CLK0_CONTROL);
// will switch off output CLK0
//
void si5351aOutputOff(uint8_t clk)
{
    i2c_init();
    
    i2cSendRegister(clk, 0x80);        // Refer to SiLabs AN619 to see bit values - 0x80 turns off the output stage

    i2c_exit();
}

//
// Set CLK0 output ON and to the specified frequency
// Frequency is in the range 1MHz to 150MHz
// Example: si5351aSetFrequency(10000000);
// will set output CLK0 to 10MHz
//
// This example sets up PLL A
// and MultiSynth 0
// and produces the output on CLK0
//
void si5351aSetFrequency(uint32_t frequency)
{
    uint32_t pllFreq;
    uint32_t xtalFreq = XTAL_FREQ;
    uint32_t l;
    float f;
    uint8_t mult;
    uint32_t num;
    uint32_t denom;
    uint32_t divider;

    i2c_init();                        // Initialise the I2C

    divider = 900000000 / frequency;// 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 * frequency;    // 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 = l;                            // mult is an integer that must be in the range 15..90
    f *= 1048575;                    // num and denom are the fractional parts, the numerator and denominator
    f /= xtalFreq;                    // each is 20 bits (range 0..1048575)
    num = 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_A, 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_0, divider, SI_R_DIV_1);
                                    // 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_CLK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A);

    i2c_exit();                        // Exit I2C
}
QQ807087233
13896060783
离线BG8GFY
发帖
118
只看该作者 24楼 发表于: 2018-06-29
#ifndef SI5351A_H
#define SI5351A_H

#include <inttypes.h>

#define SI_CLK0_CONTROL    16            // Register definitions
#define SI_CLK1_CONTROL    17
#define SI_CLK2_CONTROL    18
#define SI_SYNTH_PLL_A    26
#define SI_SYNTH_PLL_B    34
#define SI_SYNTH_MS_0        42
#define SI_SYNTH_MS_1        50
#define SI_SYNTH_MS_2        58
#define SI_PLL_RESET        177

#define SI_R_DIV_1        0b00000000            // R-division ratio definitions
#define SI_R_DIV_2        0b00010000
#define SI_R_DIV_4        0b00100000
#define SI_R_DIV_8        0b00110000
#define SI_R_DIV_16        0b01000000
#define SI_R_DIV_32        0b01010000
#define SI_R_DIV_64        0b01100000
#define SI_R_DIV_128        0b01110000

#define SI_CLK_SRC_PLL_A    0b00000000
#define SI_CLK_SRC_PLL_B    0b00100000

#define XTAL_FREQ    27000000            // Crystal frequency

void si5351aOutputOff(uint8_t clk);
void si5351aSetFrequency(uint32_t frequency);

#endif //SI5351A_H
QQ807087233
13896060783
离线BG8GFY
发帖
118
只看该作者 25楼 发表于: 2018-06-29
上面的程序,希望对你有用。我就是用的这个程序改的。
QQ807087233
13896060783
离线BG8GFY
发帖
118
只看该作者 26楼 发表于: 2018-06-29
根据你的硬件,把下面这两个程序改一下就行了。
uint8_t i2cSendRegister(uint8_t reg, uint8_t data)

uint8_t i2cReadRegister(uint8_t reg, uint8_t *data)
QQ807087233
13896060783
离线bd4igh
发帖
4250
只看该作者 27楼 发表于: 2018-07-02
太深奥了!
王安林
山东.日照
曾用呼号BG6AG
安徽境内首个业余台
QQ:317311229
手机:13376330683
Email  :wal 696@163.com.
离线bi8akt
发帖
196
只看该作者 28楼 发表于: 2018-07-05

// *************  SI5315 routines - tks Jerry Gaffke, KE7ER   ***********************

// An minimalist standalone set of Si5351 routines.
// VCOA is fixed at 875mhz, VCOB not used.
// The output msynth dividers are used to generate 3 independent clocks
// with 1hz resolution to any frequency between 4khz and 109mhz.

// Usage:
// Call si5351bx_init() once at startup with no args;
// Call si5351bx_setfreq(clknum, freq) each time one of the
// three output CLK pins is to be updated to a new frequency.
// A freq of 0 serves to shut down that output clock.

// The global variable si5351bx_vcoa starts out equal to the nominal VCOA
// frequency of 25mhz*35 = 875000000 Hz.  To correct for 25mhz crystal errors,
// the user can adjust this value.  The vco frequency will not change but
// the number used for the (a+b/c) output msynth calculations is affected.
// Example:  We call for a 5mhz signal, but it measures to be 5.001mhz.
// So the actual vcoa frequency is 875mhz*5.001/5.000 = 875175000 Hz,
// To correct for this error:     si5351bx_vcoa=875175000;

// Most users will never need to generate clocks below 500khz.
// But it is possible to do so by loading a value between 0 and 7 into
// the global variable si5351bx_rdiv, be sure to return it to a value of 0
// before setting some other CLK output pin.  The affected clock will be
// divided down by a power of two defined by  2**si5351_rdiv
// A value of zero gives a divide factor of 1, a value of 7 divides by 128.
// This lightweight method is a reasonable compromise for a seldom used feature.
#include <Wire.h>

#define BB0(x) ((uint8_t)x)             // Bust int32 into Bytes
#define BB1(x) ((uint8_t)(x>>8))
#define BB2(x) ((uint8_t)(x>>16))

#define SI5351BX_ADDR 0x60              // I2C address of Si5351   (typical)
#define SI5351BX_XTALPF 2               // 1:6pf  2:8pf  3:10pf

// If using 27mhz crystal, set XTAL=27000000, MSA=33.  Then vco=891mhz
#define SI5351BX_XTAL 25000000          // Crystal freq in Hz
#define SI5351BX_MSA  35                // VCOA is at 25mhz*35 = 875mhz

// User program may have reason to poke new values into these 3 RAM variables
uint32_t si5351bx_vcoa = (SI5351BX_XTAL*SI5351BX_MSA);  // 25mhzXtal calibrate
uint8_t  si5351bx_rdiv = 0;             // 0-7, CLK pin sees fout/(2**rdiv)
uint8_t  si5351bx_drive[3] = {1, 1, 1}; // 0=2ma 1=4ma 2=6ma 3=8ma for CLK 0,1,2
uint8_t  si5351bx_clken = 0xFF;         // Private, all CLK ouutput drivers off
int32_t calibration = 0;

void i2cWrite(uint8_t reg, uint8_t val) {   // write reg via i2c
  Wire.beginTransmission(SI5351BX_ADDR);
  Wire.write(reg);
  Wire.write(val);
  Wire.endTransmission();
}

void i2cWriten(uint8_t reg, uint8_t *vals, uint8_t vcnt) {  // write array
  Wire.beginTransmission(SI5351BX_ADDR);
  Wire.write(reg);
  while (vcnt--) Wire.write(*vals++);
  Wire.endTransmission();
}


void si5351bx_init() {                  // Call once at power-up, start PLLA
  uint8_t reg;  uint32_t msxp1;
  Wire.begin();
  i2cWrite(149, 0);                     // SpreadSpectrum off
  i2cWrite(3, si5351bx_clken);          // Disable all CLK output drivers
  i2cWrite(183, SI5351BX_XTALPF << 6);  // Set 25mhz crystal load capacitance
  msxp1 = 128 * SI5351BX_MSA - 512;     // and msxp2=0, msxp3=1, not fractional
  uint8_t  vals[8] = {0, 1, BB2(msxp1), BB1(msxp1), BB0(msxp1), 0, 0, 0};
  i2cWriten(26, vals, 8);               // Write to 8 PLLA msynth regs
  i2cWrite(177, 0x20);                  // Reset PLLA  (0x80 resets PLLB)
  // for (reg=16; reg<=23; reg++) i2cWrite(reg, 0x80);    // Powerdown CLK's
  // i2cWrite(187, 0);                  // No fannout of clkin, xtal, ms0, ms4
}

void si5351bx_setfreq(uint8_t clknum, uint32_t fout) {  // Set a CLK to fout Hz
  uint32_t  msa, msb, msc, msxp1, msxp2, msxp3p2top;
  if ((fout < 500000) || (fout > 109000000)) // If clock freq out of range
    si5351bx_clken |= 1 << clknum;      //  shut down the clock
  else {
    msa = si5351bx_vcoa / fout;     // Integer part of vco/fout
    msb = si5351bx_vcoa % fout;     // Fractional part of vco/fout
    msc = fout;             // Divide by 2 till fits in reg
    while (msc & 0xfff00000) {
      msb = msb >> 1;
      msc = msc >> 1;
    }
    msxp1 = (128 * msa + 128 * msb / msc - 512) | (((uint32_t)si5351bx_rdiv) << 20);
    msxp2 = 128 * msb - 128 * msb / msc * msc; // msxp3 == msc;
    msxp3p2top = (((msc & 0x0F0000) << 4) | msxp2);     // 2 top nibbles
    uint8_t vals[8] = { BB1(msc), BB0(msc), BB2(msxp1), BB1(msxp1),
                        BB0(msxp1), BB2(msxp3p2top), BB1(msxp2), BB0(msxp2)
                      };
    i2cWriten(42 + (clknum * 8), vals, 8); // Write to 8 msynth regs
    i2cWrite(16 + clknum, 0x0C | si5351bx_drive[clknum]); // use local msynth
    si5351bx_clken &= ~(1 << clknum);   // Clear bit to enable clock
  }
  i2cWrite(3, si5351bx_clken);        // Enable/disable clock
}

//void si5351_set_calibration(int32_t cal){
//    si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + cal; // apply the calibration correction factor
//    si5351bx_setfreq(0, usbCarrier);
//}

void initOscillators(){
  //initialize the SI5351
  unsigned long usbCarrier;
  si5351bx_init();
  si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + calibration; // apply the calibration correction factor
  si5351bx_setfreq(0, usbCarrier);
}






void setup() {
  // put your setup code here, to run once:
si5351bx_init();
si5351bx_setfreq(2,7050000);


}

void loop() {
  // put your main code here, to run repeatedly:

}
这是我测试的arduino的程序,arduino板子只需要连接i2c以及3.3V和地4根线。si5351的clk2就会输出7.050M。超简单的。