咚咚咚————【封装驱动】Si5351A方波信号发生器发送任意(8K-160Mhz)频率程序

咚咚咚————【封装驱动】Si5351A方波信号发生器发送任意[8K-160Mhz]频率程序


(使用阿波罗STM32F7开发板)

(一)效果展示

(二)源码分享

芯片SI5351A源代码下载
可以支持一下吗QAQ

SI5351A.c

/********************************************
主控芯片:STM32F405RGT6主频168Mhz
晶体频率:HSE=8Mhz  SYSCLK=168Mhz
模块型号:STM32串口初始化
通讯方式:
函数功能:Si5351时钟芯片
作者:苏夏雨
授权:未经作者允许,禁止转载
********************************************/
#include "si5351a.h"
#include "delay.h"
void IICstart()//IIC总线起始信号
{
	  SDA(1);
	  CLK(1);
	  SDA(0);
    delay_us(100); 
	  CLK(0);
    delay_us(100); 	
}
void IICstop()//IIC总线停止信号
{
	  CLK(0);
    delay_us(100); 
	  SDA(0);
    delay_us(100); 
	  CLK(1);
    delay_us(100); 
	  SDA(1);	
    delay_us(100); 
}
void IICsend(u8 DATA)//IIC总线发送信数据
{
		u16 i;
    for(i=0;i<8;i++) //发送一个字节数据 
    {     
        CLK(0); 		 //拉低时钟线,准备开始给SDA赋值
			
        if((DATA&0x80)==0)  
        {SDA(0);}  
        else  
        {SDA(1);}  
				
        DATA<<=1;  
        delay_us(100);    
        CLK(1);
        delay_us(100);      //等待从设备把数据接收完
		}  
    CLK(0);  
    SDA(1);	 				   //释放数据线   
    delay_us(100);   
    CLK(1); 
    delay_us(100); 
		while(i<1000){i++;}//等待从设备应答ACK 
		CLK(0); 					 //释放时钟线,为下次操作做准备
}
void IICsendreg(uint8_t reg, uint8_t data)
{
  IICstart();      //起始信号
  delay_us(200);  
  IICsend(0xC0);   //发送设备地址+写信号
  delay_us(200);  
  IICsend(reg);    //内部寄存器地址
  delay_us(200);  
  IICsend(data);   //内部寄存器数据
  delay_us(200);  
  IICstop(); 
}
void Si5351Init()//初始化Si5351芯片
{
		GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_GPIOB_CLK_ENABLE();			//开启GPIOB时钟
		GPIO_Initure.Pin=GPIO_PIN_10|GPIO_PIN_11;//PB10,11引脚
		GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;//上拉模式
		GPIO_Initure.Speed=GPIO_SPEED_HIGH;//GPIO速度高速
	  HAL_GPIO_Init(GPIOB,&GPIO_Initure);//初始化GPIOB
}
void SetFrequency(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;
  divider = 900000000 / frequency;	//锁相环频率:900 mhz
  if (divider % 2) divider--;				//确保一个更整数除法比率
  pllFreq = divider * frequency;		//计算pllFrequency:分频器*所需的输出频率
  mult = pllFreq / xtalFreq;				//确定所需的pllFrequency的乘数
  l = pllFreq % xtalFreq;						//它有三个部分:
  f = l;														//乘是一个整数,必须在15 . . 90
  f *= 1048575;											//num和分母项是小数部分,分子和分母
  f /= xtalFreq;										//每20位(范围0 . . 1048575)
  num = f;													//实际的乘数是乘+ num /分母项
  denom = 1048575;									//为简单起见我们将分母最大1048575
																		//设置锁相环与倍增系数计算
  SetPLLClk(SI_SYNTH_PLL_A, mult, num, denom);
		//设置MultiSynth分配器0分计算。
		//最后R分裂阶段可以除以2的幂,从1 . . 128。
		//由常量SI_R_DIV1 reprented SI_R_DIV128(见si5351a。h头文件)
		//如果你想在1兆赫兹以下输出,你必须使用
		//最后R分裂阶段

  SetMultisynth(SI_SYNTH_MS_0,divider,SI_R_DIV_1);
		//重置锁相环。这将导致输出的故障。对于小的变化
		//参数,不需要复位锁相环,没有故障

  IICsendreg(SI_PLL_RESET,0xA0);	
		//最后打开CLK0输出(0 x4f)
		//并设置MultiSynth0是锁相环的输入
  IICsendreg(SI_CLK0_CONTROL, 0x4F|SI_CLK_SRC_PLL_A);
}
void SetPLLClk(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom)//设置PPL时钟
{
  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;

  IICsendreg(pll + 0, (P3 & 0x0000FF00) >> 8);
  IICsendreg(pll + 1, (P3 & 0x000000FF));
  IICsendreg(pll + 2, (P1 & 0x00030000) >> 16);
  IICsendreg(pll + 3, (P1 & 0x0000FF00) >> 8);
  IICsendreg(pll + 4, (P1 & 0x000000FF));
  IICsendreg(pll + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
  IICsendreg(pll + 6, (P2 & 0x0000FF00) >> 8);
  IICsendreg(pll + 7, (P2 & 0x000000FF));
}
void SetMultisynth(uint8_t synth,uint32_t divider,uint8_t rDiv)//设置多synth
{
  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;

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

SA5351A.h

/********************************************
主控芯片:STM32F405RGT6主频168Mhz
晶体频率:HSE=8Mhz  SYSCLK=168Mhz
模块型号:STM32串口初始化
通讯方式:
函数功能:Si5351时钟芯片
作者:苏夏雨
授权:未经作者允许,禁止转载
********************************************/
#ifndef _si5351a_h
#define _si5351a_h
#include "system.h"
//Si5351寄存器声明
#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		0x00			// 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	0x00
#define SI_CLK_SRC_PLL_B	0b00100000
#define XTAL_FREQ	25000000			// Crystal frequency
//IIC总线引脚配置
#define SDA(n) {n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);}
#define CLK(n) {n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_RESET);}
//相关函数声明
void Si5351Init(void);//初始化Si5351的GPIO
void SetPLLClk(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom);//设置PPL时钟
void SetFrequency(uint32_t frequency);//时钟Si5351时钟频率
void SetMultisynth(uint8_t synth,uint32_t divider,uint8_t rDiv);//设置多synth
#endif

(三)需要改进的地方及不足

学校里的示波器只有100M带宽,所以只能测试有效值低于12.5Mhz的方波(频率太高带宽就不够用了,一般是示波器带宽除以八)后续频率的测试没有进行…

  • 11
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
/******************************************** 主控芯片:STM32F405RGT6主频168Mhz 晶体频率:HSE=8Mhz SYSCLK=168Mhz 模块型号:SI5351A 通讯方式: 函数功能:Si5351时钟芯片 作者:苏夏雨 授权:未经作者允许,禁止转载 ********************************************/ #ifndef _si5351a_h #define _si5351a_h #include "system.h" //Si5351寄存器声明 #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 0x00 // 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 0x00 #define SI_CLK_SRC_PLL_B 0b00100000 #define XTAL_FREQ 25000000 // Crystal frequency //IIC总线引脚配置 #define SDA(n) {n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);} #define CLK(n) {n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_RESET);} //相关函数声明 void Si5351Init(void);//初始化Si5351的GPIO void SetPLLClk(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom);//设置PPL时钟 void SetFrequency(uint32_t frequency);//时钟Si5351时钟频率 void SetMultisynth(uint8_t synth,uint32_t divider,uint8_t rDiv);//设置多synth #endif
适用于家庭无线电设备,例如超外差接收机,SDR,HAM QRP收发器或RF发生器。 硬件部件: 面包板(通用) × 1个 Arduino Nano R3 × 1个 带按钮的旋转编码器 × 1个 Adafruit SSD1306 128X64 OLED显示屏× 1个 Adafruit SI5351时钟发电模块× 1个 拨动开关,SPDT × 2个 松下RCA插孔,用于RF输出设置× 2个 电容100 nF × 3 电容器10 µF × 1个 电容10 nF × 2个 电阻1k欧姆 × 1个 电感100 uH × 1个 软件应用程序和在线服务 Arduino IDE 这是VFO(变频振荡器)的项目,可用于自制设备,例如超外差接收器,DCR,SDR或Ham QRP收发器。它还具有用于信号强度(S-Meter)和20 Band预设的条形图指示器。也可以用作RF /时钟发生器。这是新版本(V.2),我更新了以前的项目,它包含新功能。 特征: 工作范围为10kHz至225MHz。 1Hz,10Hz,1kHz,5kHz,10kHz和1MHz的调谐步长。 中频(IF)偏移(+或-)可调。 BCB和HAM频率的20个频段预设(快捷方式)。 发电机功能模式。 RX / TX模式选择器,用于Homebrew QRP收发器。 通过模拟输入(ADC)的信号表的条形图。 用作Homebrew无线电接收器(如超外差,SDR,直接转换和Homebrew QRP收发器)上的本地振荡器。 用作简单的RF /时钟发生器,用于校准参考或时钟生成。 可与Arduino Uno,Nano和Pro Mini一起使用。 使用通用的128x64 I2C OLED SSD1306显示器和Si5351模块。 I2C数据传输,仅需2条线即可连接显示器/ Si5351和arduino。 频率生成的高稳定性和精度。 简单但非常有效且免费。 设置: 原理图/接线: 演示视频: 指示: 在Arduino IDE上打开scketch,安装所有必需的库。 选择首选项(请参阅注释)并编译草图,然后将其加载到Arduino Nano,Uno或Pro Mini。 按照示意图连接Arduino,Display,Si5351模块,旋转编码器等。 打开Arduino的电源。 旋转旋转编码器以调高或调低频率。 按下按钮1更改频率步进调谐。可用的步进为1Hz,10Hz,1kHz,5kHz,10kHz和1MHz。 按下按钮2浏览(选择)20个频段预设或进入发生器模式。 打开/关闭开关SW 2,以从RX模式更改为TX模式。RX模式= SW 2开路,TX模式= SW 2接地。在TX模式下,不会从RF输出中添加/减去IF值。这是在Homebrew QRP收发器中使用的理想选择。 将无线电的S-Meter输出信号连接到X2连接器(S-Meter输入)。该输入具有可调的灵敏度,必须在Sketch中调整增益,以接受500mV至5V(最大)的信号。 关于用户首选项的注意事项: -可以更改原理图上的以下项目: #define IF 455 //输入您的IF频率,例如:455 = 455kHz,10700 = 10.7MHz,0 =直接转换接收器或RF发生器,+将加和-将减去ffset。 #define BAND_INIT 7 //在启动时输入初始频段(1-21),例如:1 =频率发生器,2 = 800kHz(MW),7 = 7.2MHz(40m),11 = 14.1MHz(20m)。 #define XT_CAL_F 33000 // Si5351校准系数,调整为可得10MHz。增加该值将降低频率,反之亦然。 #define S_GAIN 303 //调整信号仪表A / D输入的灵敏度:101 = 500mv;202 = 1v;303 = 1.5v;404 = 2v;505 = 2.5v;1010 = 5v(最大)。 #define tunestep A0 //调谐步骤按钮使用的引脚。 #define band A1 //波段选择器按钮使用的引脚。 #define rx_tx A2 // RX / TX选择器开关使用的引脚,RX =开关断开,TX =开关闭合至GND。在TX中时,不考虑IF。 #define adc A3 //信号表A / D输入所使用的引脚。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值