stm32 si5351使用(软件模拟i2c和硬件i2c)

单片机 专栏收录该内容
2 篇文章 0 订阅

参考资料来源
csdn: Si5351A方波信号发生器发送任意频率程序.
github: SI5351时钟模块测试代码.

使用的单片机为STM32F030
i2c引脚为PB8(SCL),PB9(SDA)

需要记住的地方有:

  1. si5351设备地址:写地址0xC0,读地址为0xC1(手册的第四章可以看到)
  2. si5351的寄存器和输出频率的计算要看另一本手册
    下载: AN619.

在这里插入图片描述简单说一下写操作:

  • i2c启动
  • 发送设备地址+写信号
  • 等待答应
  • 发送要写的寄存器地址
  • 等待答应
  • 发送要写的数据
  • 等待答应
  • i2c停止

软件模拟i2c

先说下软件模拟的i2c,这个好测试,因为万一别人画的板引脚反了改一下就可以测试了(惨痛教训)。
i2c.c

#include "i2c.h"

// 初始化IIC的IO口
void I2C2_Soft_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;   // 定义GPIO结构体
	
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);  // 打开GPIOB口时钟
	
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  // 输出
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; // 开漏
    GPIO_InitStructure.GPIO_Pin = Pin_SCL | Pin_SDA ; // IIC对应IO口
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; // 50MHZ
    GPIO_Init(GPIOB, &GPIO_InitStructure); // 初始化GPIO
	
    I2C2_Stop();
}
 
// 发送IIC起始信号
bool I2C2_Start(void)
{
    Pin_SCL_H; // 拉高时钟线
    Pin_SDA_H; // 拉高信号线
    I2C2_Delay1us();
    if(!Read_SDA_Pin)		return false;
    Pin_SDA_L;
    I2C2_Delay1us();
    Pin_SDA_L;
    I2C2_Delay1us();
    return true;
}
 
// 发送IIC停止信号
bool I2C2_Stop(void)
{
    Pin_SCL_H;
    Pin_SDA_L;
    I2C2_Delay1us();
    if(Read_SDA_Pin)	return false;
    Pin_SDA_H;
    I2C2_Delay1us();
    if(!Read_SDA_Pin) return false;
    Pin_SDA_H;
    I2C2_Delay1us();	
    return true;
}
 
// IIC发送ACK信号
void I2C2_Ack(void)
{
    Pin_SCL_L;
    I2C2_Delay1us();
    Pin_SDA_L;	
    Pin_SCL_H;
    I2C2_Delay1us();
    Pin_SCL_L;
    Pin_SDA_H;
    I2C2_Delay1us();
}
 
// IIC不发送ACK信号
void I2C2_NAck(void)
{
    Pin_SCL_L;
    I2C2_Delay1us();	
    Pin_SDA_H;
    Pin_SCL_H;
    I2C2_Delay1us();
    Pin_SCL_L;
    I2C2_Delay1us();
}
 
// IIC等待ACK信号
uint8_t I2C2_Wait_Ack(void)
{
    Pin_SCL_L;
    I2C2_Delay1us();	
    Pin_SDA_H;
    Pin_SCL_H;
    I2C2_Delay1us();	
    if(Read_SDA_Pin)
    {
	Pin_SCL_L;
	I2C2_Delay1us();
	return false;
    }
    Pin_SCL_L;
    I2C2_Delay1us();
    return true;
}
 
// IIC发送一个字节
void I2C2_Send_Byte(uint8_t txd)
{
    for(uint8_t i=0; i<8; i++)
    {
	Pin_SCL_L;
	I2C2_Delay1us();
	if(txd & 0x80)
	    Pin_SDA_H;
	else
	    Pin_SDA_L;
	    txd <<= 1;
	    Pin_SCL_H;
	    I2C2_Delay1us();
    }
}
 
// IIC读取一个字节
uint8_t	I2C2_Read_Byte(void)
{
    uint8_t rxd = 0;
    for(uint8_t i=0; i<8; i++)
    {
	rxd <<= 1;
	Pin_SCL_L;
	I2C2_Delay1us();
	Pin_SCL_H;	
	I2C2_Delay1us();		
	if(Read_SDA_Pin)
	{
	    rxd |= 0x01;
	}
    }
    return rxd;
}
 
// 向从机指定地址写数据
bool I2C_Write_REG(uint8_t SlaveAddress, uint8_t REG_Address,uint8_t REG_data)
{
    if(!I2C2_Start())		return false;
    I2C2_Send_Byte(SlaveAddress);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    I2C2_Send_Byte(REG_Address);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    I2C2_Send_Byte(REG_data);
    if(!I2C2_Wait_Ack()) { I2C2_Stop(); return false;	}
    if(!I2C2_Stop()) return false;
    return true;
}
 
// 从设备中读取数据
uint8_t I2C2_Read_REG(uint8_t SlaveAddress,uint8_t REG_Address)
{
    uint8_t data;
    if(!I2C2_Start())	return false;
    I2C2_Send_Byte(SlaveAddress);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    I2C2_Send_Byte(REG_Address);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    if(!I2C2_Start())	return false;
    I2C2_Send_Byte(SlaveAddress + 1);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    data = I2C2_Read_Byte();
    I2C2_NAck();
    if(!I2C2_Stop())	return false;	
    return data;
}
 
// 连续写N个字节
bool I2C2_Write_NByte(uint8_t SlaveAddress, uint8_t REG_Address, uint8_t* buf, uint8_t len)
{
    if(!I2C2_Start())return false;
    I2C2_Send_Byte(SlaveAddress);  //发送设备地址+写信号
    if(!I2C2_Wait_Ack()){I2C2_Stop(); return false;}
    I2C2_Send_Byte(REG_Address);   
    if(!I2C2_Wait_Ack()){I2C2_Stop(); return false;}
    for(uint16_t i=0; i<len; i++)
    {
        I2C2_Send_Byte(buf[i]);
	if(i<len-1)
	{
            if(!I2C2_Wait_Ack()){I2C2_Stop(); return false;}
	}
    }
    I2C2_Stop();
    return true;
}

bool I2C2_CheckDevice(uint8_t SlaveAddress)
{
    if(!I2C2_Start())	return false;
    I2C2_Send_Byte(SlaveAddress);
    if(!I2C2_Wait_Ack())
    {
	I2C2_Stop();
	return false;		
    }
    if(!I2C2_Stop())	return false;	
    return true;	
}


bool my_I2C_sendREG(uint8_t REG_Address,uint8_t REG_data)
{
    if(!I2C2_Start())		return false;
    I2C2_Send_Byte(0xC0);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    I2C2_Send_Byte(REG_Address);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    I2C2_Send_Byte(REG_data);
    if(!I2C2_Wait_Ack()) { I2C2_Stop(); return false;	}
    if(!I2C2_Stop()) return false;
    return true;
}

uint8_t my_I2C2_Read_REG(uint8_t REG_Address)
{
    uint8_t data;
    if(!I2C2_Start())	return false;
    I2C2_Send_Byte(0xC0);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    I2C2_Send_Byte(REG_Address);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    if(!I2C2_Start())	return false;
    I2C2_Send_Byte(0xC1);
    if(!I2C2_Wait_Ack()) { I2C2_Stop();	return false;	}
    data = I2C2_Read_Byte();
    I2C2_NAck();
    if(!I2C2_Stop())	return false;	
    return data;
}

i2c.h

#ifndef __I2C_H
#define	__I2C_H

#include "stm32f0xx.h"

typedef unsigned  short int   uint;
typedef enum {false = 0, true = !false} bool;

#define	I2C2_GPIOx  GPIOB
#define Pin_SCL		GPIO_Pin_8//8
#define Pin_SDA		GPIO_Pin_9//9
 
#define Pin_SCL_L		I2C2_GPIOx->ODR &= ~Pin_SCL
#define Pin_SCL_H		I2C2_GPIOx->ODR |= Pin_SCL
 
#define Pin_SDA_L		I2C2_GPIOx->ODR &= ~Pin_SDA
#define Pin_SDA_H		I2C2_GPIOx->ODR |= Pin_SDA
 
#define Read_SDA_Pin	I2C2_GPIOx->IDR & Pin_SDA


#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




static inline void I2C2_Delay1us(void)
{
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();	
}	
 
 

 
void I2C2_Soft_Init(void);			
bool I2C2_Start(void);						
bool I2C2_Stop(void);	  				
void I2C2_Send_Byte(uint8_t txd);
uint8_t I2C2_Read_Byte(void);
uint8_t I2C2_Wait_Ack(void); 		
void I2C2_Ack(void);							
void I2C2_NAck(void);						
 
bool I2C2_Write_REG(uint8_t SlaveAddress,uint8_t REG_Address,uint8_t REG_data);
uint8_t I2C2_Read_REG(uint8_t SlaveAddress,uint8_t REG_Address);
bool I2C2_Write_NByte(uint8_t SlaveAddress, uint8_t REG_Address, uint8_t* buf, uint8_t len);
bool I2C2_Read_NByte(uint8_t SlaveAddress, uint8_t REG_Address, uint8_t* buf, uint8_t len);
//建议使用这个函数来测试是否有通信
bool I2C2_CheckDevice(uint8_t SlaveAddress);

//这里的代码和硬件i2c重复了,下面会给出
void si5351aSetFrequency(uint32_t frequency , uint8_t Chanal );
void setupPLL(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom);
void setupMultisynth(uint8_t synth,uint32_t divider,uint8_t rDiv);

#endif

硬件i2c

(因为是直接改eproom的所以只给出关键部分,不然太长了)
i2c.c

void GPIO_Configuration(void)
{
  GPIO_InitTypeDef  GPIO_InitStruct; 
	
	/* Enable  GPIOA clock */
	  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);	
// 	/* Configure the I2C clock source. The clock is derived from the HSI */
//   RCC_I2CCLKConfig(RCC_I2C1CLK_HSI);      
  /*!< sEE_I2C Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE); 
 
  /*!< GPIO configuration */  
  /*!< Configure sEE_I2C pins: SCL */
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
  GPIO_Init(GPIOB , &GPIO_InitStruct);
  
  /*!< Configure sEE_I2C pins: SDA */
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
  GPIO_Init(GPIOB , &GPIO_InitStruct);
	
 /* Connect PXx to I2C_SCL*/
  GPIO_PinAFConfig( GPIOB , GPIO_PinSource8, GPIO_AF_1); 
  /* Connect PXx to I2C_SDA*/
  GPIO_PinAFConfig( GPIOB ,GPIO_PinSource9, GPIO_AF_1);
  
}

/*******************************************************************************
* Function Name  : I2C_Configuration
* Description    : I2C Configuration
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_Configuration(void)
{
  I2C_InitTypeDef  I2C_InitStruct; 
  
  /* I2C configuration */
	I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
  I2C_InitStruct.I2C_DigitalFilter = 0x00;
  I2C_InitStruct.I2C_OwnAddress1 =0x00;
  I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
  I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;	
  I2C_InitStruct.I2C_Timing = 0x00210507;
  /* I2C Peripheral Enable */
  I2C_Cmd(I2C1, ENABLE);
  /* Apply I2C configuration after enabling it */
  I2C_Init(I2C1, &I2C_InitStruct);
 
}

/*******************************************************************************
* Function Name  : I2C_EE_Init
* Description    : Initializes peripherals used by the I2C EEPROM driver.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_Init(void)
{
  /* GPIO configuration */
  GPIO_Configuration();

  /* I2C configuration */
  I2C_Configuration();
	
    /*!< Select the EEPROM address */
  sEEAddress = sEE_HW_ADDRESS;  //设备地址
}
/**
  * @brief  从I2C1的总线上的某一器件的某一起始地址中读取一定字节的数据到数组中
  * @param  start_Addr:起始字节地址
  * @param  write_Buffer:存放读取数据的数组指针
  * @retval 是否读取成功
  */
uint8_t I2C1_Write_NBytes(uint8_t start_Addr, uint8_t write_Buffer)
{
  uint8_t write_Num;
	uint32_t I2C_Timeout =2000;
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
  {
    if((I2C_Timeout--) == 0)
    {
      return 1;
    }
  }

  I2C_TransferHandling(I2C1, 0xC0, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);

  I2C_Timeout = 2000;
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
  {
    if((I2C_Timeout--) == 0)
    {
      return 1;
    }
  }

  I2C_SendData(I2C1, start_Addr);

  I2C_Timeout = 2000;
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET)
  {
    if((I2C_Timeout--) == 0)
    {
      return 1;
    }
  }

  I2C_TransferHandling(I2C1, 0xC0, 1, I2C_AutoEnd_Mode, I2C_No_StartStop);

	I2C_Timeout = 2000;
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
    {
      if((I2C_Timeout--) == 0)
      {
        return 1;
      }
    }

    I2C_SendData(I2C1, write_Buffer);

  I2C_Timeout = 2000;
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
  {
    if((I2C_Timeout--) == 0)
    {
      return 1;
    }
  }

  return 0;
}

i2c.h

#define sEE_HW_ADDRESS      0xC0
#define sEE_I2C_TIMING          0x00210507
#define sEE_OK                    0
#define sEE_FAIL                  1   
#define sEE_I2C                          I2C1

使用si5351代码

这部分发送使用的是软件模拟的i2c,想使用硬件i2c请将my_I2C_sendREG替换为I2C1_Write_NBytes

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;

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


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;

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


void si5351aSetFrequency(uint32_t frequency , uint8_t Chanal )
{
  uint32_t pllFreq;
  uint32_t xtalFreq = XTAL_FREQ;// Crystal frequency
  uint32_t l;
  float f;
  uint8_t mult;
  uint32_t num;
  uint32_t denom;
  uint32_t divider;

  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
  if( Chanal == 0 ){
		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
		my_I2C_sendREG(SI_PLL_RESET,0xA0);	
                                                                  // Finally switch on the CLK0 output (0x4F)
                                                                  // and set the MultiSynth0 input to be PLL A
		my_I2C_sendREG(SI_CLK0_CONTROL, 0x4F|SI_CLK_SRC_PLL_A);
	}
	else if ( Chanal == 1 ){
		setupMultisynth(SI_SYNTH_MS_1,divider,SI_R_DIV_1);
		my_I2C_sendREG(SI_PLL_RESET,0xA0);	
		my_I2C_sendREG(SI_CLK1_CONTROL, 0x4F|SI_CLK_SRC_PLL_A);
	}
		else if ( Chanal == 2 ){
		setupMultisynth(SI_SYNTH_MS_2,divider,SI_R_DIV_1);
		my_I2C_sendREG(SI_PLL_RESET,0xA0);	
		my_I2C_sendREG(SI_CLK2_CONTROL, 0x4F|SI_CLK_SRC_PLL_A);
		}
}

至于怎么使用
main.c(软件模拟i2c)

int main(void)
{
	uint8_t testAddr = 0;
	int Fre_1M = 15000000;
	int fre = 50;
	SystemInit();
	I2C2_Soft_Init();
	
	si5351aSetFrequency(1*Fre_1M , 0);//CLK0
//	si5351aSetFrequency(2*Fre_1M , 1);
//	si5351aSetFrequency(3*Fre_1M , 2);
	
	while(1)
	{

	}
}
  • 4
    点赞
  • 11
    评论
  • 16
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

/******************************************** 主控芯片: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,10kHz1MHz的调谐步长。 中频(IF)偏移(+或-)可调。 BCBHAM频率的20个频段预设(快捷方式)。 发电机功能模式。 RX / TX模式选择器,用于Homebrew QRP收发器。 通过模拟输入(ADC)的信号表的条形图。 用作Homebrew无线电接收器(如超外差,SDR,直接转换Homebrew QRP收发器)上的本地振荡器。 用作简单的RF /时钟发生器,用于校准参考或时钟生成。 可与Arduino Uno,NanoPro Mini一起使用使用通用的128x64 I2C OLED SSD1306显示器Si5351模块。 I2C数据传输,仅需2条线即可连接显示器/ Si5351arduino。 频率生成的高稳定性精度。 简单但非常有效且免费。 设置: 原理图/接线: 演示视频: 指示: 在Arduino IDE上打开scketch,安装所有必需的库。 选择首选项(请参阅注释)并编译草图,然后将其加载到Arduino Nano,Uno或Pro Mini。 按照示意图连接Arduino,Display,Si5351模块,旋转编码器等。 打开Arduino的电源。 旋转旋转编码器以调高或调低频率。 按下按钮1更改频率步进调谐。可用的步进为1Hz,10Hz,1kHz,5kHz,10kHz1MHz。 按下按钮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输入所使用的引脚。
©️2021 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值