ZYNQ控制SI5351例程
在我之前发布的《ZYNQ IIC EEPROM读写例程》基础上,借用其IIC读写函数,其余代码参照DK7IH的AVR例子,即可实现SI5351控制。
硬件平台为PYNQ-Z2+ELEKTOR SDR,刚开始读写不成功,用示波器看IIC波形,没有拉低,因为PYNQ-Z2上已经有上拉电阻,把ELEKTOR SDR上的上拉电阻去掉,可正常读写,但是用示波器测频率,偏了9M,检查代码发现,DK7IH的代码中定义了INTERFREQUENCY 9000000,将其改成0,即可。
输出10MHz波形如下:
完整代码如下:
/***************************** Include Files *********************************/#include "xparameters.h"
#include "sleep.h"
#include "xiicps.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xil_printf.h"/************************** Constant Definitions *****************************//** The following constants map to the XPAR parameters created in the* xparameters.h file. They are defined here such that a user can easily* change all the needed parameters in one place.*/
#define IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define IIC_INTR_ID XPAR_XIICPS_0_INTR#define INTERFREQUENCY 0000000/
//Defines for Si5351
/
#define PLLRATIO 36
#define CFACTOR 1048575//Set of Si5351A register addresses
#define CLK_ENABLE_CONTROL 3
#define PLLX_SRC 15
#define CLK0_CONTROL 16
#define CLK1_CONTROL 17
#define CLK2_CONTROL 18
#define SYNTH_PLL_A 26
#define SYNTH_PLL_B 34
#define SYNTH_MS_0 42
#define SYNTH_MS_1 50
#define SYNTH_MS_2 58
#define PLL_RESET 177
#define XTAL_LOAD_CAP 183//Tuning
int calc_tuningfactor(void);int tuningcount = 0;
int tuning = 0;
int laststate = 0; //Last state of rotary encoder//SI5351 Declarations & frequency
void si5351_write(int, int);
void si5351_start(void);
void si5351_set_freq(int, unsigned long);/** The following constant defines the address of the IIC Slave device on the* IIC bus. Note that since the address is only 7 bits, this constant is the* address divided by 2.*/
#define IIC_SLAVE_ADDR 0x60
#define IIC_SCLK_RATE 100000/** The page size determines how much data should be written at a time.* The write function should be called with this as a maximum byte count.*/
#define PAGE_SIZE 16/** The Starting address in the IIC EEPROM on which this test is performed.*/
#define EEPROM_START_ADDRESS 0/**************************** Type Definitions *******************************//** The AddressType should be u8 as the address pointer in the on-board* EEPROM is 1 byte.*/
typedef u8 AddressType;/***************** Macros (Inline Functions) Definitions *********************//************************** Function Prototypes ******************************/int IicPsEepromIntrExample(void);
int EepromWriteData(u16 ByteCount);
int MuxInit(void);
int EepromReadData(u8 *BufferPtr, u16 ByteCount);static int SetupInterruptSystem(XIicPs * IicInstPtr);static void Handler(void *CallBackRef, u32 Event);/************************** Variable Definitions *****************************/XIicPs IicInstance; /* The instance of the IIC device. */
XScuGic InterruptController; /* The instance of the Interrupt Controller. *//** Write buffer for writing a page.*/
u8 WriteBuffer[sizeof(AddressType) + PAGE_SIZE];u8 ReadBuffer[PAGE_SIZE]; /* Read buffer for reading a page. */volatile u8 TransmitComplete; /* Flag to check completion of Transmission */
volatile u8 ReceiveComplete; /* Flag to check completion of Reception */
volatile u32 TotalErrorCount;/************************** Function Definitions *****************************//*****************************************************************************/
/**
* Main function to call the Iic EEPROM interrupt example.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int main(void)
{int Status;xil_printf("\n\r********************************************************");xil_printf("\n\r********************************************************");xil_printf("\n\r** PYNQ - SI5351 Test **");xil_printf("\n\r********************************************************");xil_printf("\n\r********************************************************\r\n");/** Run the Iic EEPROM interrupt mode example.*/Status = IicPsEepromIntrExample();if (Status != XST_SUCCESS) {xil_printf("IIC EEPROM Interrupt Example Test Failed\r\n");return XST_FAILURE;}xil_printf("Successfully ran IIC EEPROM Interrupt Example Test\r\n");//return XST_SUCCESS;unsigned long f_vfo = 14212789;si5351_start();si5351_set_freq(SYNTH_MS_0, f_vfo);si5351_set_freq(SYNTH_MS_1, 10000000);si5351_set_freq(SYNTH_MS_2, 3552000);
}/*****************************************************************************/
/**
* This function writes, reads, and verifies the data to the IIC EEPROM. It
* does the write as a single page write, performs a buffered read.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int IicPsEepromIntrExample(void)
{int Status;XIicPs_Config *ConfigPtr; /* Pointer to configuration data *//** Initialize the IIC driver so that it is ready to use.*/ConfigPtr = XIicPs_LookupConfig(IIC_DEVICE_ID);if (ConfigPtr == NULL) {return XST_FAILURE;}Status = XIicPs_CfgInitialize(&IicInstance, ConfigPtr,ConfigPtr->BaseAddress);if (Status != XST_SUCCESS) {return XST_FAILURE;}/** Setup the Interrupt System.*/Status = SetupInterruptSystem(&IicInstance);if (Status != XST_SUCCESS) {return XST_FAILURE;}/** Setup the handlers for the IIC that will be called from the* interrupt context when data has been sent and received, specify a* pointer to the IIC driver instance as the callback reference so* the handlers are able to access the instance data.*/XIicPs_SetStatusHandler(&IicInstance, (void *) &IicInstance, Handler);/** Set the IIC serial clock rate.*/XIicPs_SetSClk(&IicInstance, IIC_SCLK_RATE);return XST_SUCCESS;
}/*****************************************************************************/
/**
* This function writes a buffer of data to the IIC serial EEPROM.
*
* @param ByteCount contains the number of bytes in the buffer to be
* written.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note The Byte count should not exceed the page size of the EEPROM as
* noted by the constant PAGE_SIZE.
*
******************************************************************************/
int EepromWriteData(u16 ByteCount)
{TransmitComplete = FALSE;/** Send the Data.*/XIicPs_MasterSend(&IicInstance, WriteBuffer,ByteCount, IIC_SLAVE_ADDR);/** Wait for the entire buffer to be sent, letting the interrupt* processing work in the background, this function may get* locked up in this loop if the interrupts are not working* correctly.*/while (TransmitComplete == FALSE) {if (0 != TotalErrorCount) {return XST_FAILURE;}}/** Wait until bus is idle to start another transfer.*/while (XIicPs_BusIsBusy(&IicInstance));/** Wait for a bit of time to allow the programming to complete*/usleep(200000);return XST_SUCCESS;
}/*****************************************************************************/
/**
* This function reads data from the IIC serial EEPROM into a specified buffer.
*
* @param BufferPtr contains the address of the data buffer to be filled.
* @param ByteCount contains the number of bytes in the buffer to be read.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int EepromReadData(u8 *BufferPtr, u16 ByteCount)
{int Status;AddressType Address = EEPROM_START_ADDRESS;if (sizeof(Address) == 1) {WriteBuffer[0] = (u8) (Address);}else {WriteBuffer[0] = (u8) (Address >> 8);WriteBuffer[1] = (u8) (Address);}Status = EepromWriteData(sizeof(Address));if (Status != XST_SUCCESS) {return XST_FAILURE;}ReceiveComplete = FALSE;/** Receive the Data.*/XIicPs_MasterRecv(&IicInstance, BufferPtr,ByteCount, IIC_SLAVE_ADDR);while (ReceiveComplete == FALSE) {if (0 != TotalErrorCount) {return XST_FAILURE;}}/** Wait until bus is idle to start another transfer.*/while (XIicPs_BusIsBusy(&IicInstance));return XST_SUCCESS;
}/******************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the IIC.
*
* @param IicPsPtr contains a pointer to the instance of the Iic
* which is going to be connected to the interrupt controller.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None.
*
*******************************************************************************/
static int SetupInterruptSystem(XIicPs *IicPsPtr)
{int Status;XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */Xil_ExceptionInit();/** Initialize the interrupt controller driver so that it is ready to* use.*/IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);if (NULL == IntcConfig) {return XST_FAILURE;}Status = XScuGic_CfgInitialize(&InterruptController, IntcConfig,IntcConfig->CpuBaseAddress);if (Status != XST_SUCCESS) {return XST_FAILURE;}/** Connect the interrupt controller interrupt handler to the hardware* interrupt handling logic in the processor.*/Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&InterruptController);/** Connect the device driver handler that will be called when an* interrupt for the device occurs, the handler defined above performs* the specific interrupt processing for the device.*/Status = XScuGic_Connect(&InterruptController, IIC_INTR_ID,(Xil_InterruptHandler)XIicPs_MasterInterruptHandler,(void *)IicPsPtr);if (Status != XST_SUCCESS) {return Status;}/** Enable the interrupt for the Iic device.*/XScuGic_Enable(&InterruptController, IIC_INTR_ID);/** Enable interrupts in the Processor.*/Xil_ExceptionEnable();return XST_SUCCESS;
}/*****************************************************************************/
/**
*
* This function is the handler which performs processing to handle data events
* from the IIC. It is called from an interrupt context such that the amount
* of processing performed should be minimized.
*
* This handler provides an example of how to handle data for the IIC and
* is application specific.
*
* @param CallBackRef contains a callback reference from the driver, in
* this case it is the instance pointer for the IIC driver.
* @param Event contains the specific kind of event that has occurred.
* @param EventData contains the number of bytes sent or received for sent
* and receive events.
*
* @return None.
*
* @note None.
*
*******************************************************************************/
void Handler(void *CallBackRef, u32 Event)
{/** All of the data transfer has been finished.*/if (0 != (Event & XIICPS_EVENT_COMPLETE_RECV)){ReceiveComplete = TRUE;} else if (0 != (Event & XIICPS_EVENT_COMPLETE_SEND)) {TransmitComplete = TRUE;} else if (0 == (Event & XIICPS_EVENT_SLAVE_RDY)){/** If it is other interrupt but not slave ready interrupt, it is* an error.* Data was received with an error.*/TotalErrorCount++;}
}
//
// Si5351A commands
//
///
void si5351_write(int reg_addr, int reg_value)
{int Status;WriteBuffer[0] = reg_addr;WriteBuffer[1] = reg_value;Status = EepromWriteData(2);
}// Set PLLs (VCOs) to internal clock rate of 900 MHz
// Equation fVCO = fXTAL * (a+b/c) (=> AN619 p. 3
void si5351_start(void)
{unsigned long a, b, c;unsigned long p1, p2;//, p3;// Init clock chip//si5351_write(XTAL_LOAD_CAP, 0xD2); // Set crystal load capacitor to 10pF (default),// for bits 5:0 see also AN619 p. 60si5351_write(CLK_ENABLE_CONTROL, 0x00); // Enable all outputssi5351_write(CLK0_CONTROL, 0x0F); // Set PLLA to CLK0, 8 mA outputsi5351_write(CLK1_CONTROL, 0x2F); // Set PLLB to CLK1, 8 mA outputsi5351_write(CLK2_CONTROL, 0x2F); // Set PLLB to CLK2, 8 mA outputsi5351_write(PLL_RESET, 0xA0); // Reset PLLA and PLLB// Set VCOs of PLLA and PLLB to 650 MHza = PLLRATIO; // Division factor 650/25 MHz !!!!b = 0; // Numerator, sets b/c=0c = CFACTOR; //Max. resolution, but irrelevant in this case (b=0)//Formula for splitting up the numbers to register data, see AN619p1 = 128 * a + (unsigned long) (128 * b / c) - 512;p2 = 128 * b - c * (unsigned long) (128 * b / c);//p3 = c;//Write data to registers PLLA and PLLB so that both VCOs are set to 900MHz intermal freqsi5351_write(SYNTH_PLL_A, 0xFF);si5351_write(SYNTH_PLL_A + 1, 0xFF);si5351_write(SYNTH_PLL_A + 2, (p1 & 0x00030000) >> 16);si5351_write(SYNTH_PLL_A + 3, (p1 & 0x0000FF00) >> 8);si5351_write(SYNTH_PLL_A + 4, (p1 & 0x000000FF));si5351_write(SYNTH_PLL_A + 5, 0xF0 | ((p2 & 0x000F0000) >> 16));si5351_write(SYNTH_PLL_A + 6, (p2 & 0x0000FF00) >> 8);si5351_write(SYNTH_PLL_A + 7, (p2 & 0x000000FF));si5351_write(SYNTH_PLL_B, 0xFF);si5351_write(SYNTH_PLL_B + 1, 0xFF);si5351_write(SYNTH_PLL_B + 2, (p1 & 0x00030000) >> 16);si5351_write(SYNTH_PLL_B + 3, (p1 & 0x0000FF00) >> 8);si5351_write(SYNTH_PLL_B + 4, (p1 & 0x000000FF));si5351_write(SYNTH_PLL_B + 5, 0xF0 | ((p2 & 0x000F0000) >> 16));si5351_write(SYNTH_PLL_B + 6, (p2 & 0x0000FF00) >> 8);si5351_write(SYNTH_PLL_B + 7, (p2 & 0x000000FF));}void si5351_set_freq(int synth, unsigned long f)
{unsigned long freq = f + INTERFREQUENCY; unsigned long a, b, c = CFACTOR; unsigned long f_xtal = 25000000;double fdiv = (double) (f_xtal * PLLRATIO) / freq; //division factor fvco/freq (will be integer part of a+b/c)double rm; //remainderunsigned long p1, p2;a = (unsigned long) fdiv;rm = fdiv - a; //(equiv. to fractional part b/c)b = rm * c;p1 = 128 * a + (unsigned long) (128 * b / c) - 512;p2 = 128 * b - c * (unsigned long) (128 * b / c);//Write data to multisynth registers of synth nsi5351_write(synth, 0xFF); //1048575 MSBsi5351_write(synth + 1, 0xFF); //1048575 LSBsi5351_write(synth + 2, (p1 & 0x00030000) >> 16);si5351_write(synth + 3, (p1 & 0x0000FF00) >> 8);si5351_write(synth + 4, (p1 & 0x000000FF));si5351_write(synth + 5, 0xF0 | ((p2 & 0x000F0000) >> 16));si5351_write(synth + 6, (p2 & 0x0000FF00) >> 8);si5351_write(synth + 7, (p2 & 0x000000FF));
}
ZYNQ控制SI5351例程相关推荐
- 基于MPC的移动机器人轨迹跟踪控制qpOASES例程
参考了 一个模型预测控制(MPC)的简单实现 https://www.cnblogs.com/zhjblogs/p/13880682.html 与 基于MPC的移动机器人轨迹跟踪控制matlab例程 ...
- LabVIEW编程LabVIEW控制TC-XSM例程与相关资料
LabVIEW编程LabVIEW控制TC-XSM例程与相关资料 TC-XSM是北京通磁伟业传感技术有限公司的产品.TC-XSM仪表:显示转速.线速.频率测控仪表.可配tcsensor转速传感器.振动 ...
- LabVIEW编程LabVIEW开发 控制NI9472例程与相关资料
LabVIEW编程LabVIEW开发 控制NI9472例程与相关资料 NI 9472 是一款数字输出模块,用于 CompactDAQ 和 CompactRIO 系统.每个通道都可接受 6 V - 30 ...
- Dsp28335 - ePWM - 50Hz小舵机的控制 - 代码例程
最近要做一点小东西,使用dsp28335控制舵机,使用pwm信号.在这里写点东西给需要使用pwm这个模块的新人吧. 工程模板代码我传在我的csdn的资源里了,有需要的可以下载. 28xx设置的sysc ...
- ZYNQ PL采集AD7606数据PS LWIP发送
一,传输设计: 1,PS 通过 AXI GPIO IP核启动 PL 不间断循环构造64bit 位宽的 0-1023 的数据,通过 AXI DMA IP 核,PS的 Slave AXI GP 接口传输至 ...
- 使用webots的MPC的移动机器人轨迹跟踪控制
上一篇文章中使用MPC对机器人的一个方向自由度进行了控制, 基于MPC的移动机器人轨迹跟踪控制qpOASES例程 现在使用速度与角速度对机器人进行平面运动控制. 所以机器人的控制量为U=[v ;w], ...
- 使用ESP8266通过Blinker平台接入天猫精灵控制电视/空调
目录 `演示视频` 1.准备工作 1.1 `原理` 1.2 `使用的硬件以及硬件连接图` 1.3 `开发环境准备` 2.解码空调红外键值 2.1 `把ESP8266红外接收的实例,上传到NodeMCU ...
- 基于visual c++之windows核心编程代码分析(24)IO控制、内核通信
我们在进行Windows编程的时候,经常需要进行IO控制与内核通信,我们来实现IO控制与内核通信.请见代码实现与注释讲解 驱动代码实现与分析 /* 头文件 */ #include <ntddk. ...
- DSP28035控制舵机
1.舵机教程和参考例程 硬石舵机教程和参考例程(密码:o5zh) 2.使用到的舵机MG90S 使用的舵机MG90S 信号线(黄线)红线(电源线)棕色(地线) 舵机的控制一般需要一个20ms(50HZ) ...
最新文章
- nvGraph-NVIDIA图形库
- 虚拟机系统的磁盘扩容妙招及案例
- 收货地址 - 设置默认收货地址
- 通过通用数据访问扩展AWS生态系统
- python 三维曲线拟合_基于三维数据和参数的Scipy曲线拟合
- Hashtable Dictionary[必看]
- 中国土壤厚度空间分布数据
- 简单的idea非maven项目引入jar包
- 北航计算机专业报录比,北京航空航天大学考研报录比数据查询
- fprom预测结果内容_启动子分析预测数据库
- java 文件存在 覆盖_java – 如果文件存在于目录中,我该如何覆盖它
- windows安装php
- 智能快递柜的密码模块
- 用ccs创建一个工程文件
- 阻滞增长函数matlab拟合,matlab指数增长和阻滞增长拟合代码讲课稿
- 运放-环路控制系统-零点、极点、频宽、波特图、二阶、RC概念
- 计算机的u盘显示桌面,插入U盘后如何让U盘图标显示在Win7系统桌面上
- keras非线性回归代码专题
- (二)海思3519av100开发:开发板环境搭建
- maven的使用-很全