HMC7044芯片模拟SPI配置
1 摘要
HMC7044是一款高性能双环路整数N分频抖动衰减器,能够选择参考并生成超低相位噪声的频率,支持配有并行或串行(JESD204B型)接口的高速数据转换器。 HMC7044具有两个可通过SPI选择的整数模式PLL和交叠的片内VCO,调谐范围分别达2.5 GHz和3 GHz。 该器件旨在满足GSM和LTE基站设计的要求,并通过多种时钟管理和分配特性来简化基带和无线电卡时钟树的设计。 HMC7044提供14路低噪声且可配置的输出,可以灵活地与许多不同器件接口,包括数据转换器、现场可编程门阵列(FPGA)和混频器本振(LO)。
2 功能框图
HMC7044采用 双锁相环(PLL)级联架构,专门为高速数据转换器(JESD204B/C)时钟系统设计。第一级PLL (PLL1) - 抖动衰减器锁定一个干净的VCXO到相对嘈杂的外部参考时钟,其中关键组件R1分频器、N1分频器、电荷泵CP1、外部环路滤波器。第二级PLL (PLL2) - 高性能时钟发生器,将干净的VCXO频率倍频到高频VCO(2.4-3.2GHz),其中关键组件R2分频器、N2分频器、电荷泵CP2、内部VCO。

内部结构

3 SPI接口
3.1 数据格式及时序
总线采用3线接口:SLEN(片选)、SCLK(时钟)、SDATA(数据),寄存器数据采用24位寄存器(13位地址+8位数据)。SPI工作模式为模式0(CPOL=0, CPHA=0)

读时序

写时序

3.2 典型写周期
①主设备(主机)将SLEN和SDATA置有效电平,以发起读操作,随后产生SCLK上升沿。从设备(HMC7044)在 SLEN 置有效后,于 SCLK 的第一个上升沿采样 SDIO 引脚;将 SDATA 置低电平,则触发写操作的启动。
②主机在 SCLK 后续两个下降沿,将待写入的 2 位多字节字段置低(0);HMC7044 则在 SCLK 后续两个上升沿,锁存该 2 位多字节字段。
③主机在 SCLK 后续13 个下降沿,将 13 位地址字段(A12 至 A0)高位优先(MSB first) 加载至 SDATA 引脚;HMC7044 在 SCLK 后续13 个上升沿,于 SDIO 引脚高位优先锁存该 13 位地址字段。
④主机在 SCLK 后续8 个下降沿,将 8 位数据(D7 至 D0)高位优先加载至 SDATA 引脚;HMC7044 在 SCLK 后续8 个上升沿,高位优先锁存该 8 位数据(D7 至 D0)。
⑤SCLK 的最后一个上升沿执行片内数据传输至寄存器组,完成器件的配置更新。
⑥将 SLEN 置无效电平,寄存器写周期执行完毕。
4 GUI配置寄存器表
4.1. PLL1设置
根据硬件设计,选择输入CLIKIN0、CLIKIN1、CLIKIN1、CLIKIN1,根据需求设置相应的分频系数。

4.2. PLL2设置

4.3. OUT设置

5 基于SOC驱动设计
寄存器具体位含义需查看相应的寄存器地址功能。
5.1 驱动头文件
/**
* @file spi_emio.h
* @brief Zynq EMIO模拟三线制SPI驱动头文件(使用XGpioPs)
* @version 2.1
*/
#ifndef SPI_EMIO_H
#define SPI_EMIO_H
#include "xparameters.h"
#include "xgpiops.h"
#include "xil_types.h"
/************************** 常量定义 **************************/
/* EMIO引脚定义 - 根据实际硬件配置修改 */
#define SPI_EMIO_SCLK_PIN 78 /* SPI时钟引脚 */
#define SPI_EMIO_MOSI_PIN 79 /* SPI主出从入引脚 */
#define SPI_EMIO_MISO_PIN 79 /* SPI主入从出引脚 */
#define SPI_EMIO_CS_PIN 80 /* SPI片选引脚 */
/* GPIO设备ID */
#define SPI_GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
/************************** 类型定义 **************************/
/**
* @brief SPI模式枚举
*/
typedef enum {
SPI_MODE_0 = 0, /* CPOL=0, CPHA=0 */
SPI_MODE_1, /* CPOL=0, CPHA=1 */
SPI_MODE_2, /* CPOL=1, CPHA=0 */
SPI_MODE_3 /* CPOL=1, CPHA=1 */
} spi_mode_t;
/**
* @brief SPI工作模式
*/
typedef enum {
SPI_3WIRE_MODE = 0, /* 三线制模式(双向) */
SPI_3WIRE_TX_MODE, /* 三线制只发送模式 */
SPI_3WIRE_RX_MODE /* 三线制只接收模式 */
} spi_3wire_mode_t;
/**
* @brief SPI配置结构体
*/
typedef struct {
spi_mode_t mode; /* SPI模式 */
spi_3wire_mode_t wire_mode; /* 三线制工作模式 */
u32 speed_khz; /* SPI速度(KHz) */
u8 lsb_first; /* LSB先传输 */
u32 delay_us; /* 延时(微秒) */
} spi_config_t;
/**
* @brief SPI设备结构体
*/
typedef struct {
XGpioPs gpio; /* GPIO实例 (使用XGpioPs) */
spi_config_t config; /* SPI配置 */
u8 initialized; /* 初始化标志 */
} spi_device_t;
/************************** 函数声明 **************************/
/* 初始化函数 */
int spi_init(spi_device_t *spi);
int spi_configure(spi_device_t *spi, const spi_config_t *config);
/* 基本控制函数 */
void spi_cs_assert(spi_device_t *spi);
void spi_cs_deassert(spi_device_t *spi);
void spi_delay_us(u32 microseconds);
/* 数据传输函数 */
int spi_send_byte(spi_device_t *spi, u8 data);
int spi_send_data(spi_device_t *spi, const u8 *data, u32 length);
u8 spi_receive_byte(spi_device_t *spi);
int spi_receive_data(spi_device_t *spi, u8 *data, u32 length);
int spi_transfer_byte(spi_device_t *spi, u8 tx_data, u8 *rx_data);
int spi_transfer_data(spi_device_t *spi, const u8 *tx_data, u8 *rx_data, u32 length);
/* 24bit数据传输函数 */
int spi_send_24bit(spi_device_t *spi, u32 data);
int spi_send_24bit_data(spi_device_t *spi, const u32 *data, u32 length);
u8 spi_receive_24bit_cs(spi_device_t *spi,u32 addr);
u8 spi_receive_24bit_data(spi_device_t *spi, u32 addr);
/* 工具函数 */
void spi_set_mode(spi_device_t *spi, spi_mode_t mode);
void spi_set_speed(spi_device_t *spi, u32 speed_khz);
void spi_set_3wire_mode(spi_device_t *spi, spi_3wire_mode_t wire_mode);
#endif /* SPI_EMIO_H */
5.2 驱动代码
/**
* @file spi_emio.c
* @brief Zynq EMIO模拟三线制SPI驱动源文件(使用XGpioPs)
* @version 2.1
*/
#include "spi_emio.h"
#include "xil_printf.h"
#include "sleep.h"
/************************** 静态函数声明 **************************/
static void spi_sclk_high(spi_device_t *spi);
static void spi_sclk_low(spi_device_t *spi);
static void spi_mosi_high(spi_device_t *spi);
static void spi_mosi_low(spi_device_t *spi);
static u8 spi_miso_read(spi_device_t *spi);
static void spi_set_data_direction(spi_device_t *spi, int is_output);
static u32 calculate_delay_us(u32 speed_khz);
/************************** 函数实现 **************************/
/**
* @brief 初始化SPI设备
* @param spi SPI设备指针
* @return 成功返回XST_SUCCESS,失败返回XST_FAILURE
*/
int spi_init(spi_device_t *spi)
{
int status;
XGpioPs_Config *ConfigPtr;
if (spi == NULL) {
return XST_FAILURE;
}
ConfigPtr = XGpioPs_LookupConfig(SPI_GPIO_DEVICE_ID);
if (ConfigPtr == NULL) {
xil_printf("SPI GPIO配置查找失败\r\n");
return XST_FAILURE;
}
/* 初始化GPIO */
status = XGpioPs_CfgInitialize(&spi->gpio, ConfigPtr, ConfigPtr->BaseAddr);
if (status != XST_SUCCESS) {
xil_printf("SPI GPIO初始化失败: %d\r\n", status);
return XST_FAILURE;
}
/* 设置引脚方向和输出使能 */
XGpioPs_SetDirectionPin(&spi->gpio, SPI_EMIO_SCLK_PIN, 1); /* 输出 */
XGpioPs_SetDirectionPin(&spi->gpio, SPI_EMIO_MOSI_PIN, 1); /* 输出 */
XGpioPs_SetDirectionPin(&spi->gpio, SPI_EMIO_CS_PIN, 1); /* 输出 */
XGpioPs_SetDirectionPin(&spi->gpio, SPI_EMIO_MISO_PIN, 0);


2127

被折叠的 条评论
为什么被折叠?



