任意波形发生器芯片AD9102的应用


前言

本文主要介绍Analog Device公司的任意波形合成器AD9102的应用


一、任意波形合成器AD9102简介

AD9102是Analog Device公司生产的任意波形合成器集成芯片,内部集成了高速DAC,高速波形储存器,DDS直接数字频率合成器,电压基准源等,可以产生任意波形。具有低功耗,高集成度等特点。最高系统时钟频率为180MHz,可产生最高频率为90MHz的正弦波信号和10MHz的任意波形信号。功能框图如下:
在这里插入图片描述

二、硬件设计

1.AD9102最小系统

AD9102芯片最小系统十分简单,仅需少量电阻电容即可。电阻R5,R6为DAC输出电流电压转换电阻,将电流输出转化为电压输出。R7,R8为校准电阻。电容均为电源滤波和退耦电容。为了提高电磁兼容性,降低干扰,将模拟地和数字地分开布线,并用铁氧体磁珠单点连接。
在这里插入图片描述

2.时钟电路

AD9102支持单端和差分时钟输入,数据手册上推荐使用差分时钟,故使用德州仪器公司的LMH7220高速LVDS驱动器产生LVDS电平差分时钟。由于AD9102内部无时钟管理系统,波形生成器时钟即为输入时钟,故外部提供两路时钟信号,分别为10MHz和180MHz,分别为产生高频信号和低频信号时的参考时钟。
在这里插入图片描述

3.输出信号处理电路

AD9102输出为电流信号,经电阻转换为电压信号后,由可变增益放大器放大后输出。可变增益放大器采用德州仪器公司生产的VCA824集成芯片,增益由电压控制,输出带载能力强,图中电路接法最高电压放大倍数为10倍,最低为0倍,与控制电压成线性关系。具体可参阅VCA824的数据手册。控制电压由双极性DAC:AD5761R产生。
在这里插入图片描述

4.控制电路

AD9102芯片使用SPI接口控制,增益控制DAC也为SPI控制,控制器采用意法半导体公司STM32L552CEU6。控制电路如下图所示。
在这里插入图片描述

5.电源电路

整个系统需要3.3V数字电源,3.3V模拟电源,±5V模拟电源,分别由不同的电源芯片产生,如下图。
在这里插入图片描述

三、软件设计

提示:本设计使用STM32单片机HAL库方式编程,使用开发环境Keil uVision5。

1.单片机外设配置

本设计用到了SPI,定时器,内置运算放大器,I2C,GPIO,UART(可选)等外设。
在这里插入图片描述

2.AD9102初始化和基本交互

uint8_t AD9102_Init(void)//上电初始化
{
	HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);//CS拉高
	HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_SET);//RESET拉高
	HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);//TRIG拉低
	AD9102_Reset();
	return 1;
}

uint8_t AD9102_Reset(void)//重置器件
{
	HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_RESET);//RESET拉低
	HAL_Delay(10);
	HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_SET);//RESET拉高
	return 1;
}

uint8_t AD9102_WriteReg(uint16_t addr,uint16_t data)//写入寄存器
{

	uint8_t Txd[4];
	Txd[0]=((addr>>8)&0x7F);
	Txd[1]=addr&0xFF;
	Txd[2]=(data>>8)&0xFF;
	Txd[3]=data&0xFF;
	HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);//CS拉低,启动传输
	HAL_SPI_Transmit(&hspi3,Txd,4,1000);//SPI发送数据
	HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);//CS拉高,结束传输
	return 1;
}

uint16_t AD9102_ReadReg(uint16_t addr)//读取寄存器
{

	uint8_t Txd[2];
	uint8_t Rxd[2];
	uint16_t Rdata;
	Txd[0]=((addr>>8)&0x7F)|0x80;
	Txd[1]=addr&0xFF;
	HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);//CS拉低,启动传输
	HAL_SPI_Transmit(&hspi3,Txd,2,1000);//SPI发送指令
	HAL_SPI_Receive(&hspi3,Rxd,2,1000);//接收数据
	HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);//CS拉高,结束传输
	Rdata=(Rxd[0]<<8)+(Rxd[1]);
	return Rdata;
}

3.AD9102芯片操作

根据数据手册,我编写了对AD9102芯片进行操作的库函数,列表如下:

//AD9102.h

#include "stm32l5xx_hal.h"


#define RESET_Pin GPIO_PIN_12
#define RESET_GPIO_Port GPIOA
#define CS_Pin GPIO_PIN_15
#define CS_GPIO_Port GPIOA
#define TRIG_Pin GPIO_PIN_8
#define TRIG_GPIO_Port GPIOB
#define CLKMODE2_Pin GPIO_PIN_8
#define CLKMODE2_GPIO_Port GPIOA
#define CLKMODE1_Pin GPIO_PIN_11
#define CLKMODE1_GPIO_Port GPIOA


uint8_t AD9102_Init(void);//上电初始化
uint8_t AD9102_Reset(void);//重置器件
uint8_t AD9102_Trig(void);//触发
uint8_t AD9102_DisTrig(void);//终止触发
uint8_t AD9102_WriteReg(uint16_t addr,uint16_t data);//写入寄存器
uint16_t AD9102_ReadReg(uint16_t addr);//读取寄存器
uint8_t AD9102_Duplex(uint8_t value);//双工设置,0为全双工,1为半双工
uint8_t AD9102_DataSequence(uint8_t value);//数据顺序设置,1为LSB优先,0为MSB优先
uint8_t AD9102_SoftReset(void);//软件重置
uint8_t AD9102_DoubleSPI(uint8_t value);//双重SPI设置,0为标准SPI,1为双SPI
uint8_t AD9102_SPIDRV(uint8_t value);//SPI_DRV设置
uint8_t AD9102_DOUT_EN(uint8_t value);//DOUT设置
uint8_t AD9102_GetLDOStatus(uint8_t LDO);//获取LDO状态,1为开启,0为关闭,参数1:CLDO,2:DLDO1,3:DLDO2
uint8_t AD9102_LDO_EN(uint8_t LDO,uint8_t value);//内置LDO开关,参数1:1:CLDO,2:DLDO1,3:DLDO2。参数2:0为开启,1为关闭
uint8_t AD9102_RefRes_EN(uint8_t value);//参考电压电阻开关,0为开启,1为关闭
uint8_t AD9102_BandGap_EN(uint8_t value);//内置参考电压开关,0为开启,1为关闭
uint8_t AD9102_DACOutput_EN(uint8_t value);//DAC输出开关,0为开启,1为关闭
uint8_t AD9102_CLK_EN(uint8_t Clock,uint8_t value);//系统时钟开关,参数1为时钟源:1:DAC1,2:DDS核心,3:低功耗模式,4:全部时钟。参数2:0为开启,1为关闭
uint8_t AD9102_PowerSave(uint8_t value);//低功耗模式,0为关闭,1为开启
uint8_t AD9102_DACCLK_Inv(uint8_t value);//DAC时钟反相,1为反相,0为正常
uint8_t AD9102_REFADJ(uint8_t value);//参考电压调节
int8_t AD9102_GetDACGainCal(void);//读取DAC增益校准值
uint8_t AD9102_SetDACGain(int8_t value);//设置DAC增益值
uint8_t AD9102_DACGainRange(uint8_t value);//DAC增益范围设置
uint8_t AD9102_DACRset_EN(uint8_t value);//内部RSET开关,1为开启,0为关闭
uint8_t AD9102_GetRset(void);//校准后RSET值读取
uint8_t AD9102_Rset(uint8_t value);//设置RSET值
uint16_t AD9102_GetCalStatus(void);//读取校准状态
uint8_t AD9102_Cal_Reset(void);//重置校准
uint8_t AD9102_CalibrationMode(uint8_t value);//校准模式,1为进入校准模式,0为退出校准模式
uint8_t AD9102_Cal_Offset(uint8_t value);//校准偏置设置
uint8_t AD9102_CalClk_EN(uint8_t value);//启动校准时钟,1为开启,0为关闭
uint8_t AD9102_CalClk_Div(uint8_t value);//校准时钟分频
uint8_t AD9102_GetCompCalResult(void);//获取比较器校准结果
uint8_t AD9102_GetCalComp(void);//读取校准是否完成
uint8_t AD9102_StartCal(uint8_t value);//开始校准,1为开启校准,0为关闭
uint8_t AD9102_Pattern_Update(void);//更新图案寄存器
uint8_t AD9102_ReadBackMode(uint8_t value);//读回模式
uint8_t AD9102_MemoryAccess(uint8_t value);//内存接入模式
uint8_t AD9102_RunMode(uint8_t value);//软件启动和终止图案,0为启动,1为停止
uint8_t AD9102_GetPatternStatus(void);//获取图案生成状态
uint8_t AD9102_PatternMode(uint8_t mode);//波形输出模式,0为连续输出,1为有限次数输出
uint8_t AD9102_PatternDelay(uint16_t value);//波形延迟
uint8_t AD9102_DigitalOffset(uint16_t value);//数字偏置设置
uint8_t AD9102_WavePrestoreSel(uint8_t value);//预储存配置选择,0:恒定值,1:锯齿波,2:伪随机序列,3:DDS输出
uint8_t AD9102_WaveSel(uint8_t value);//波形选择,0:RAM值,1:预储存波形,2:使用延迟和周期的预储存波形,3:RAM调制的预储存波形
uint8_t AD9102_DACHoldCycle(uint8_t value);//DAC保持时间,0至15周期
uint8_t AD9102_PatternPeriodBASE(uint8_t value);//DAC周期和波形周期关系
uint8_t AD9102_DACDelay(uint8_t value);//DAC延迟
uint8_t AD9102_PatternPeriod(uint16_t value);//波形周期设置
uint8_t AD9102_PatternRepeat(uint8_t value);//波形重复输出次数
uint8_t AD9102_DOUT_Delay(uint16_t value);//触发后DOUT拉高延迟
uint8_t AD9102_DOUT_ManualSet(uint8_t value);//手动设置DOUT值
uint8_t AD9102_DOUT_Function(uint8_t value);//DOUT输出模式,0为手动设置,1为波形生成和停止标志
uint8_t AD9102_DOUT_Time(uint8_t value);//DOUT持续时间
uint8_t AD9102_DAC_ConstValue(uint16_t value);//DAC恒定值设置,0至0xFFF
uint8_t AD9102_DigitalGain(uint16_t value);//数字增益设置
uint8_t AD9102_SawtoothSamp(uint8_t value);//锯齿波每个阶梯采样次数,1至64
uint8_t AD9102_SawtoothType(uint8_t value);//锯齿波类型,0为上升锯齿波,1为下降锯齿波,2为对称锯齿波,3为零输出
uint8_t AD9102_DDS_SetFreq(uint32_t freqcode);//设置DDS频率,代码0至0xFFFFFF
uint8_t AD9102_DDS_SetFreq_Hz(double freq);//设置DDS频率,单位Hz,主频180MHz分辨率最小10.728836Hz
uint8_t AD9102_DDS_PhaseSet(uint16_t phasecode);//DDS相位设置,0至0xFFFF
uint8_t AD9102_DDS_PhaseSet_Deg(double phase);//设置DDS相位,单位度
uint8_t AD9102_DDS_PhaseSet_Rad(double phase);//设置DDS相位,单位弧度
uint8_t AD9102_DelayMode(uint8_t value);//触发延迟模式,0:每个波形都延迟,1:只延迟第一个波形
uint8_t AD9102_DDS_CosineWave(uint8_t value);//DDS输出正弦波或余弦波,1为余弦,0为正弦
uint8_t AD9102_RAM_ClockSource(uint8_t channel);//RAM时钟来源,0:MCLK,1:DDS(MSB)
uint8_t AD9102_Phase_RAM_EN(uint8_t value);//DDS相位偏移从RAM读取数据,0为从寄存器读取,1为RAM读取
uint8_t AD9102_DDSTuningRAM_EN(uint8_t value);//DDS频率控制字来源,0为寄存器,1为RAM
uint8_t AD9102_DDS_RAMTuning_Config(uint8_t value);//DDSRAM调频设置
uint8_t AD9102_StartDelay(uint16_t value);//DAC延迟,0至0xFFFF
uint8_t AD9102_StartAddress(uint16_t value);//DAC输出波形数据起始地址
uint8_t AD9102_StopAddress(uint16_t value);//DAC输出波形结束地址
uint8_t AD9102_DDSCycle(uint16_t value);//DDS周期设置
uint16_t AD9102_GetError(void);//获取错误信息
uint16_t AD9102_ReadRAM(uint16_t addr);//读取RAM,16位位宽,地址0x6000至0x6FFF
uint8_t AD9102_WriteRAM(uint16_t addr,int16_t data);//写入寄存器,12位位宽,地址0x6000至0x6FFF
uint8_t AD9102_ExtGain(double value);//设置外部增益
uint8_t AD9102_SetRAMWaveAddr(uint16_t start,uint16_t stop);//设置RAM波形起始地址和结束地址
uint8_t AD9102_OutputSineWave(double freq,double amplitude,double phase);//输出正弦波
uint8_t AD9102_OutputRectangularWave(double freq,double amplitude,double Duty);//输出方波
uint8_t AD9102_OutputTriangle(double freq,double amplitude,double peak);//输出三角波
uint8_t AD9102_OutputLOWFREQRect(double freq,double amplitude,double duty);//输出低频方波
uint8_t AD9102_OutputLOWFREQRTriangle(double freq,double amplitude,double peak);//输出低频三角波
uint8_t AD9102_OutputConstValue(int16_t value);//输出恒定值
uint8_t AD9102_OutputAnyWave(int *wavedata,uint16_t length);//输出任意波
uint8_t AD9102_MainClk(uint8_t level);//设置主频挡位,0为168MHz,1为8MHz
double AD9102_FixGain(double value);//增益校准

四、结果测试

1.实物图

在这里插入图片描述

2.正弦波输出测试

测试代码如下:

    AD9102_Init();//上电初始化
	AD9102_DisTrig();//终止触发
	AD9102_ExtGain_Init();//外部增益初始化
	AD9102_DigitalGain(0x400);
	AD9102_MainClk(1);
	AD9102_OutputSineWave(1000000,2000,0);//输出正弦波,(频率,振幅,相位)
	AD9102_Trig();//触发

输出结果:
输出频率为1MHz,振幅为2Vpp,相位为0度的正弦波
在这里插入图片描述

3.三角波输出测试

测试代码如下:

    AD9102_Init();//上电初始化
	AD9102_DisTrig();//终止触发
	AD9102_ExtGain_Init();//外部增益初始化
	AD9102_DigitalGain(0x400);
	AD9102_MainClk(1);
	AD9102_OutputTriangle(1000000,3000,50);//输出三角波(频率,振幅,对称度)
	AD9102_Trig();//触发

输出结果:
输出频率为1MHz,振幅为3Vpp,对称度为75%的三角波
在这里插入图片描述

4.方波输出测试

测试代码如下:

    AD9102_Init();//上电初始化
	AD9102_DisTrig();//终止触发
	AD9102_ExtGain_Init();//外部增益初始化
	AD9102_DigitalGain(0x400);
	AD9102_MainClk(1);
	AD9102_OutputRectangularWave(1000000,5000,30);//输出方波(频率,振幅,占空比)
	AD9102_Trig();//触发

输出结果:
输出频率为1MHz,振幅为5Vpp,对称度为30%的方波(负载电阻50欧姆)
在这里插入图片描述

5.任意波输出测试

测试代码如下:

    AD9102_Init();//上电初始化
	AD9102_DisTrig();//终止触发
	AD9102_ExtGain_Init();//外部增益初始化
	AD9102_DigitalGain(0x400);
	AD9102_MainClk(1);
	AD9102_OutputAnyWave(wavedata2,3000);//输出任意波(波形数组,波形长度)
	AD9102_Trig();//触发

其中wavedata2为任意波形数据,是一个正弦波,三角波,方波交替出现的波形,部分如下:
在这里插入图片描述
输出结果:
在这里插入图片描述

对于任意波形发生器AD9102的介绍就到这里了,具体操作代码太多放不下,完整源代码和电路原理图在我的资源里面可以找到。

### FPGA与AD9102编程实例 针对FPGA与AD9102的集成应用,通常涉及DAC(数模转换器)配置以及数据流控制逻辑的设计。下面提供了一个简化版的例子,用于说明如何通过Vivado HLS或直接使用Verilog/VHDL编写一段基本代码来初始化并操作AD9102。 #### 初始化设置 为了使能AD9102的功能模块,在启动阶段需发送特定命令序列给器件: ```verilog // Verilog code snippet for initializing AD9102 over SPI interface module ad9102_init( input wire clk, output reg sclk, // Serial Clock Line to AD9102 output reg mosi, // Master Out Slave In line input wire miso, // Not used here but shown for completeness output reg cs_n // Chip Select signal active low ); initial begin @(posedge clk); // Start by ensuring chip select is high (inactive state) cs_n = 1; // Send initialization commands... end task send_command(input [7:0] cmd); begin // Activate CS before sending command bits one-by-one on MOSI with SCLK pulses cs_n = 0; // Active Low repeat(8) begin @(posedge clk); {sclk,mosi} = {cmd[7], ~cs_n}; // Toggle clock and set data bit @(negedge clk); cmd = cmd << 1; // Shift next bit into position end // Deactivate CS after completing transfer @(posedge clk); cs_n = 1; end endtask // Example usage of the task defined above within an initial block initial begin // Initialize device according to datasheet recommendations send_command(8'hXX); // Replace XX with actual hex value from spec sheet ... end endmodule ``` 此段代码展示了利用SPI接口向AD9102发送指令的过程[^3]。需要注意的是,具体的寄存器地址和参数应参照官方提供的技术手册进行调整。 对于更复杂的项目,建议参考制造商发布的详细文档和技术支持资源,这些资料往往包含了完整的API描述、最佳实践案例研究等内容,有助于开发者更好地理解和掌握目标硬件的工作原理及其优化技巧。
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值