作者:SHR-sky
前言
作为一款高带宽的DDS模块,AD9959经常用于电赛的信号类赛题中。
本文章提供STM32F407的AD9959驱动,同时介绍其参数以及电赛应用。
正文
一、参数
1.特性参数
模块供电:5V
模块驱动电流:400mA(MAX)(所以可能存在带载问题,建议输出端添加跟随器)
模块带宽:200MHz
模块输出波形:正弦波(输出可能被抬升Vpp/2,,取决于具体模块)
模块频率最小步进:1Hz
模块最大输出幅值:500mVPP左右(正弦波,可调,频率越高,最大输出电压越低)
二、电赛应用
常用于作为信号源,由于为四通道DDS,导致通道之间天然没有频率偏移,在“稳定同频显示”中起到非常重要的作用。
但是,这里重点强调,一定要在芯片上加散热片,该芯片功耗极大,极易过热烧毁!
本质上AD9959就是利用SPI写寄存器的值,从而控制四个通道的输出。可见本人博客电赛2023H,2024C题的解析,都可以利用AD9959就行解题,可以省去非常多麻烦。
与此关联的还有乘法器、衰减器以及高频加法器,请见本人博客。
三、驱动代码
头函数
#ifndef _AD9959_H_
#define _AD9959_H_
#include "sys.h"
#include "stdint.h"
#define SCLK PDout(0)
#define CS PDout(1)
#define UPDATE PDout(2)
#define SDIO0 PDout(3)
#define PS0 PDout(4)
#define PS1 PEout(5)
#define PS2 PEout(6)
#define PS3 PDout(7)
#define SDIO1 PDout(8)
#define SDIO2 PDout(9)
#define SDIO3 PDout(10)
#define AD9959_PWR PDout(15)
#define RESET PDout(14)
//AD9959管脚宏定义
//AD9959寄存器地址定义
#define CSR_ADD 0x00 //CSR 通道选择寄存器
#define FR1_ADD 0x01 //FR1 功能寄存器1
#define FR2_ADD 0x02 //FR2 功能寄存器2
#define CFR_ADD 0x03 //CFR 通道功能寄存器
#define CFTW0_ADD 0x04 //CTW0 通道频率转换字寄存器
#define CPOW0_ADD 0x05 //CPW0 通道相位转换字寄存器
#define ACR_ADD 0x06 //ACR 幅度控制寄存器
#define LSRR_ADD 0x07 //LSR 线性扫描斜率寄存器
#define RDW_ADD 0x08 //RDW 上升扫描增量寄存器
#define FDW_ADD 0x09 //FDW 下降扫描增量寄存器
#define PROFILE_ADDR_BASE 0x0A //Profile寄存器,配置文件寄存器起始地址
//CSR[7:4]通道选择启用位
#define CH0 0x10
#define CH1 0x20
#define CH2 0x40
#define CH3 0x80
//FR1[9:8] 调制电平选择位
#define LEVEL_MOD_2 0x00//2电平调制 2阶调制
#define LEVEL_MOD_4 0x01//4电平调制 4阶调制
#define LEVEL_MOD_8 0x02//8电平调制 8阶调制
#define LEVEL_MOD_16 0x03//16电平调制 16阶调制
//CFR[23:22] 幅频相位(AFP)选择位
#define DISABLE_Mod 0x00 //00 调制已禁用
#define ASK 0x40 //01 振幅调制,幅移键控
#define FSK 0x80 //10 频率调制,频移键控
#define PSK 0xc0 //11 相位调制,相移键控
//(CFR[14])线性扫描启用 sweep enable
#define SWEEP_ENABLE 0x40 //1 启用
#define SWEEP_DISABLE 0x00 //0 不启用
void delay1 (uint32_t length);//延时
void IntReset(void); //AD9959复位
void IO_Update(void); //AD9959更新数据
void Intserve(void); //IO口电平状态初始化
void AD9959_Init(void); //IO口初始化
/***********************AD9959基本寄存器操作函数*****************************************/
void AD9959_WriteData(uint8_t RegisterAddress, uint8_t NumberofRegisters, uint8_t *RegisterData);//向AD9959写数据
void Write_CFTW0(uint32_t fre); //写CFTW0通道频率转换字寄存器
void Write_ACR(uint16_t Ampli); //写ACR通道幅度转换字寄存器
void Write_CPOW0(uint16_t Phase); //写CPOW0通道相位转换字寄存器
void Write_LSRR(uint8_t rsrr,uint8_t fsrr); //写LSRR线性扫描斜率寄存器
void Write_RDW(uint32_t r_delta); //写RDW上升增量寄存器
void Write_FDW(uint32_t f_delta); //写FDW下降增量寄存器
void Write_Profile_Fre(uint8_t profile,uint32_t data);//写Profile寄存器,频率
void Write_Profile_Ampli(uint8_t profile,uint16_t data);//写Profile寄存器,幅度
void Write_Profile_Phase(uint8_t profile,uint16_t data);//写Profile寄存器,相位
/********************************************************************************************/
/*****************************点频操作函数***********************************/
void AD9959_Set_Fre(uint8_t Channel,uint32_t Freq); //写频率
void AD9959_Set_Amp(uint8_t Channel, uint16_t Ampli);//写幅度
void AD9959_Set_Phase(uint8_t Channel,uint16_t Phase);//写相位
/****************************************************************************/
/*****************************调制操作函数 ***********************************/
void AD9959_Modulation_Init(uint8_t Channel,uint8_t Modulation,uint8_t Sweep_en,uint8_t Nlevel);//设置各个通道的调制模式。
void AD9959_SetFSK(uint8_t Channel, uint32_t *data,uint16_t Phase);//设置FSK调制的参数
void AD9959_SetASK(uint8_t Channel, uint16_t *data,uint32_t fre,uint16_t Phase);//设置ASK调制的参数
void AD9959_SetPSK(uint8_t Channel, uint16_t *data,uint32_t Freq);//设置PSK调制的参数
void AD9959_SetFre_Sweep(uint8_t Channel, uint32_t s_data,uint32_t e_data,uint32_t r_delta,uint32_t f_delta,uint8_t rsrr,uint8_t fsrr,uint16_t Ampli,uint16_t Phase);//设置线性扫频的参数
void AD9959_SetAmp_Sweep(uint8_t Channel, uint32_t s_Ampli,uint16_t e_Ampli,uint32_t r_delta,uint32_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Phase);//设置线性扫幅的参数
void AD9959_SetPhase_Sweep(uint8_t Channel, uint16_t s_data,uint16_t e_data,uint16_t r_delta,uint16_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Ampli);//设置线性扫相的参数
/********************************************************************************************/
#endif
代码
/************************************************************
AD9959 驱动程序
AD9959--单片机
硬件连接: CS ——PA6;
SCLK ——PB1;
UPDATE ——PB0;
SP0 ——PA7;
SP1 ——PA2;
SP2 ——PB10;
SP3 ——PC0;
SDIO0 ——PA5;
SDIO1 ——PA4;
SDIO2 ——PA3;
SDIO3 ——PA8;
AD9959_PWR(PDC)——PA9;
RST ——PA10;
GND --GND(0V)
//AD9959.c
//说明:本程序基于硬件的外接晶振为25MHZ
**************************************************************/
#include "AD9959.h"
uint8_t FR1_DATA[3] = {0xD0, 0x00, 0x00}; // VCO gain control[23]=1系统时钟高于255Mhz; PLL[22:18]=10100,20倍频,20*25M=500MHZ; Charge pump control = 75uA
uint8_t FR2_DATA[2] = {0x00, 0x00}; // 双方向扫描,即从起始值扫到结束值后,又从结束值扫到起始值
// uint8_t FR2_DATA[2] = {0x80,0x00};// 单方向扫描,即从起始值扫到结束值后,又从起始值扫到结束值,以此类推
double ACC_FRE_FACTOR = 8.589934592; // 频率因子8.589934592=(2^32)/500000000 其中500M=25M*20(倍频数可编程)
uint8_t CFR_DATA[3] = {0x00, 0x03, 0x02}; // default Value = 0x000302 //通道功能寄存器
/************************************************************
** 函数名称 :void AD9959_Init(void)
** 函数功能 :初始化控制AD9959需要用到的IO口,及寄存器
** 入口参数 :无
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void AD9959_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //PA,PB,PC端口时钟使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_2|GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;//初始化管脚PA2.3.4.5.6.7.8.9.10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_10;//初始化管脚PB0.1.10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //IO口速度为2MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //初始化管脚PC0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //IO口速度为2MHz
GPIO_Init(GPIOC, &GPIO_InitStructure); //根据设定参数初始化GPIOC
*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); // PD port clock enable
GPIO_InitStructure.GPIO_Pin = (0xC79F << 0); // Initialize PD0~12
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
Intserve(); // IO口电平状态初始化
IntReset(); // AD9959复位
// 初始化功能寄存器
AD9959_WriteData(FR1_ADD, 3, FR1_DATA); // 写功能寄存器1
AD9959_WriteData(FR2_ADD, 2, FR2_DATA); //
}
// 延时
void delay1(uint32_t length)
{
length = length * 12;
while (length--)
;
}
/************************************************************
** 函数名称 :void Intserve(void)
** 函数功能 :IO口电平状态初始化
**************************************************************/
void Intserve(void)
{
AD9959_PWR = 0;
CS = 1;
SCLK = 0;
UPDATE = 0;
PS0 = 0;
PS1 = 0;
PS2 = 0;
PS3 = 0;
SDIO0 = 0;
SDIO1 = 0;
SDIO2 = 0;
SDIO3 = 0;
}
/************************************************************
** 函数名称 :void IntReset(void)
** 函数功能 :AD9959复位
**************************************************************/
void IntReset(void)
{
RESET = 0;
delay1(1);
RESET = 1;
delay1(30);
RESET = 0;
}
/************************************************************
** 函数名称 void IO_Update(void)
** 函数功能 : AD9959更新数据
**************************************************************/
void IO_Update(void)
{
UPDATE = 0;
delay1(2);
UPDATE = 1;
delay1(4);
UPDATE = 0;
}
/************************************************************
** 函数名称 :void AD9959_WriteData(u8 RegisterAddress, u8 NumberofRegisters, u8 *RegisterData)
** 函数功能 :使用模拟SPI向AD9959写数据
** 入口参数 :RegisterAddress: 寄存器地址
NumberofRegisters: 要写入的字节数
*RegisterData: 数据起始地址
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void AD9959_WriteData(uint8_t RegisterAddress, uint8_t NumberofRegisters, uint8_t *RegisterData)
{
uint8_t ControlValue = 0;
uint8_t ValueToWrite = 0;
uint8_t RegisterIndex = 0;
uint8_t i = 0;
ControlValue = RegisterAddress;
// 写入地址
SCLK = 0;
CS = 0;
for (i = 0; i < 8; i++)
{
SCLK = 0;
if (0x80 == (ControlValue & 0x80))
SDIO0 = 1;
else
SDIO0 = 0;
SCLK = 1;
ControlValue <<= 1;
}
SCLK = 0;
// 写入数据
for (RegisterIndex = 0; RegisterIndex < NumberofRegisters; RegisterIndex++)
{
ValueToWrite = RegisterData[RegisterIndex];
for (i = 0; i < 8; i++)
{
SCLK = 0;
if (0x80 == (ValueToWrite & 0x80))
SDIO0 = 1;
else
SDIO0 = 0;
SCLK = 1;
ValueToWrite <<= 1;
}
SCLK = 0;
}
CS = 1;
}
/************************************************************
** 函数名称 :void Write_CFTW0(uint32_t fre)
** 函数功能 :写CFTW0通道频率转换字寄存器
** 入口参数 : Freq: 写入频率,范围0~200 000 000 Hz
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void Write_CFTW0(uint32_t fre)
{
uint8_t CFTW0_DATA[4] = {0x00, 0x00, 0x00, 0x00}; // 中间变量
uint32_t Temp;
Temp = (uint32_t)fre * ACC_FRE_FACTOR;
CFTW0_DATA[3] = (uint8_t)Temp;
CFTW0_DATA[2] = (uint8_t)(Temp >> 8);
CFTW0_DATA[1] = (uint8_t)(Temp >> 16);
CFTW0_DATA[0] = (uint8_t)(Temp >> 24);
AD9959_WriteData(CFTW0_ADD, 4, CFTW0_DATA); // CTW0 address 0x04
}
/************************************************************
** 函数名称 :void Write_ACR(uint16_t Ampli)
** 函数功能 :写ACR通道幅度转换字寄存器
** 入口参数 :Ampli: 输出幅度,范围0~1023,控制值0~1023对应输出幅度0~500mVpp左右
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void Write_ACR(uint16_t Ampli)
{
uint32_t A_temp = 0;
uint8_t ACR_DATA[3] = {0x00, 0x00, 0x00}; // default Value = 0x--0000 Rest = 18.91/Iout
A_temp = Ampli | 0x1000;
ACR_DATA[1] = (uint8_t)(A_temp >> 8); // 高位数据
ACR_DATA[2] = (uint8_t)A_temp; // 低位数据
AD9959_WriteData(ACR_ADD, 3, ACR_DATA); // ACR address 0x06.CHn设定幅度
}
/************************************************************
** 函数名称 :void Write_CPOW0(uint16_t Phase)
** 函数功能 :写CPOW0通道相位转换字寄存器
** 入口参数 :Phase: 输出相位,范围:0~16383(对应角度:0°~360°)
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void Write_CPOW0(uint16_t Phase)
{
uint8_t CPOW0_data[2] = {0x00, 0x00};
CPOW0_data[1] = (uint8_t)Phase;
CPOW0_data[0] = (uint8_t)(Phase >> 8);
AD9959_WriteData(CPOW0_ADD, 2, CPOW0_data); // CPOW0 address 0x05.CHn设定相位
}
/************************************************************
** 函数名称 :void Write_LSRR(uint8_t rsrr,uint8_t fsrr)
** 函数功能 :写LSRR线性扫描斜率寄存器
** 入口参数 : rsrr: 上升斜率,范围:0~255
fsrr: 下降斜率,范围:0~255
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void Write_LSRR(uint8_t rsrr, uint8_t fsrr)
{
uint8_t LSRR_data[2] = {0x00, 0x00};
LSRR_data[1] = rsrr;
LSRR_data[0] = fsrr; // 高8位下降斜率
AD9959_WriteData(LSRR_ADD, 2, LSRR_data);
}
/************************************************************
** 函数名称 :void Write_RDW(uint32_t r_delta)
** 函数功能 :写RDW上升增量寄存器
** 入口参数 :r_delta:上升增量,0-4294967295
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void Write_RDW(uint32_t r_delta)
{
uint8_t RDW_data[4] = {0x00, 0x00, 0x00, 0x00}; // 中间变量
RDW_data[3] = (uint8_t)r_delta;
RDW_data[2] = (uint8_t)(r_delta >> 8);
RDW_data[1] = (uint8_t)(r_delta >> 16);
RDW_data[0] = (uint8_t)(r_delta >> 24);
AD9959_WriteData(RDW_ADD, 4, RDW_data);
}
/************************************************************
** 函数名称 :void Write_FDW(uint32_t f_delta)
** 函数功能 :写FDW下降增量寄存器
** 入口参数 :f_delta:下降增量,0-4294967295
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void Write_FDW(uint32_t f_delta)
{
uint8_t FDW_data[4] = {0x00, 0x00, 0x00, 0x00}; // 中间变量
FDW_data[3] = (uint8_t)f_delta;
FDW_data[2] = (uint8_t)(f_delta >> 8);
FDW_data[1] = (uint8_t)(f_delta >> 16);
FDW_data[0] = (uint8_t)(f_delta >> 24);
AD9959_WriteData(FDW_ADD, 4, FDW_data);
}
/************************************************************
** 函数名称 :void Write_Profile_Fre(uint8_t profile,uint32_t data)
** 函数功能 :写Profile寄存器
** 入口参数 :profile: profile号(0~14)
data: 写入频率,范围0~200 000 000 Hz
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void Write_Profile_Fre(uint8_t profile, uint32_t data)
{
uint8_t profileAddr;
uint8_t Profile_data[4] = {0x00, 0x00, 0x00, 0x00}; // 中间变量
uint32_t Temp;
Temp = (uint32_t)data * ACC_FRE_FACTOR; // 将输入频率因子分为四个字节 4.294967296=(2^32)/500000000
Profile_data[3] = (uint8_t)Temp;
Profile_data[2] = (uint8_t)(Temp >> 8);
Profile_data[1] = (uint8_t)(Temp >> 16);
Profile_data[0] = (uint8_t)(Temp >> 24);
profileAddr = PROFILE_ADDR_BASE + profile;
AD9959_WriteData(profileAddr, 4, Profile_data);
}
/************************************************************
** 函数名称 :void Write_Profile_Ampli(uint8_t profile,uint16_t data)
** 函数功能 :写Profile寄存器
** 入口参数 :profile: profile号(0~14)
data: 写入幅度,范围0~1023,
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void Write_Profile_Ampli(uint8_t profile, uint16_t data)
{
uint8_t profileAddr;
uint8_t Profile_data[4] = {0x00, 0x00, 0x00, 0x00}; // 中间变量
// 为幅度调制时幅度数据为[31:22]位
Profile_data[1] = (uint8_t)(data << 6); //[23:22]
Profile_data[0] = (uint8_t)(data >> 2); //[31:24]
profileAddr = PROFILE_ADDR_BASE + profile;
AD9959_WriteData(profileAddr, 4, Profile_data); // 写入32位数据
}
/************************************************************
** 函数名称 :void Write_Profile_Phase(uint8_t profile,uint16_t data)
** 函数功能 :写Profile寄存器
** 入口参数 :profile: profile号(0~14)
data: 写入相位,范围:0~16383
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void Write_Profile_Phase(uint8_t profile, uint16_t data)
{
uint8_t profileAddr;
uint8_t Profile_data[4] = {0x00, 0x00, 0x00, 0x00}; // 中间变量
// 为相位调制时相位数据为[31:18]位
Profile_data[1] = (uint8_t)(data << 2); //[23:18]
Profile_data[0] = (uint8_t)(data >> 6); //[31:24]
profileAddr = PROFILE_ADDR_BASE + profile;
AD9959_WriteData(profileAddr, 4, Profile_data); // 写入32位数据
}
/************************************************************
** 函数名称 :void AD9959_Set_Fre(uint8_t Channel,uint32_t Freq)
** 函数功能 :设置通道的输出频率
** 入口参数 :Channel: 输出通道 CH0-CH3
Freq: 输出频率,范围0~200 000 000 Hz
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void AD9959_Set_Fre(uint8_t Channel, uint32_t Freq)
{
uint8_t CHANNEL[1] = {0x00};
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn
Write_CFTW0(Freq); // 输出CHn设定频率
}
/************************************************************
** 函数名称 :void AD9959_Set_Amp(uint8_t Channel, uint16_t Ampli)
** 函数功能 :设置通道的输出幅度
** 入口参数 :Channel: 输出通道 CH0-CH3
Ampli: 输出幅度,范围0~1023,控制值0~1023对应输出幅度0~500mVpp左右
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void AD9959_Set_Amp(uint8_t Channel, uint16_t Ampli)
{
uint8_t CHANNEL[1] = {0x00};
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn
Write_ACR(Ampli); // CHn设定幅度
}
/************************************************************
** 函数名称 :void AD9959_Set_Phase(uint8_t Channel,uint16_t Phase)
** 函数功能 :设置通道的输出相位
** 入口参数 :Channel: 输出通道 CH0-CH3
Phase: 输出相位,范围:0~16383(对应角度:0°~360°)
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void AD9959_Set_Phase(uint8_t Channel, uint16_t Phase)
{
uint8_t CHANNEL[1] = {0x00};
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn
Write_CPOW0(Phase); // CHn设定相位
}
/************************************************************
** 函数名称 :void AD9959_Modulation_Init(uint8_t Channel,uint8_t Modulation,uint8_t Sweep_en,uint8_t Nlevel)
** 函数功能 :设置各个通道的调制模式。
** 入口参数 : Channel: 输出通道 CH0-CH3
Modulation: 调制模式DISABLE_Mod,ASK,FSK,PSK
Sweep_en: 线性扫描模式 SWEEP_ENABLE启用、SWEEP_DISABLE不启用;启用时Nlevel只能是LEVEL_MOD_2
Nlevel: 调制电平选择 LEVEL_MOD_2、4、8、16
** 出口参数 :无
** 函数说明 :如将调制电平设置为2电平调制时,对应的P0-P3引脚上的高低电平分别控制CH0-CH3通道(如果对应通道开启的话)
如将调制电平设置为4电平调制时,对应的P0,P1和P2,P3引脚上的高低电平分别控制CH0-CH1通道(如果对应通道开启的话)
由于AD9959只有P0-P3,4个用于调制控制的引脚,因此输出在4电平调制时,只能有2个通道同时设置为调制输出;
8电平和16电平调制时,只能有1个通道同时设置为调制输出。请适当设置几电平调制以满足应用需求。
**注意!!!:设置成4电平调制时,输出通道只能选择CH0-1
设置成8,16电平调制时,输出通道只能选择CH0
本函数未做任意通道兼容,具体方法请参考AD9959芯片手册22-23页,操作FR1[14:12]为对应值。
**************************************************************/
void AD9959_Modulation_Init(uint8_t Channel, uint8_t Modulation, uint8_t Sweep_en, uint8_t Nlevel)
{
uint8_t i = 0;
uint8_t CHANNEL[1] = {0x00};
uint8_t FR1_data[3];
uint8_t FR2_data[2];
uint8_t CFR_data[3];
for (i = 0; i < 3; i++) // 设置默认值
{
FR1_data[i] = FR1_DATA[i];
CFR_data[i] = CFR_DATA[i];
}
FR2_data[0] = FR2_DATA[0];
FR2_data[1] = FR2_DATA[1];
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn
FR1_data[1] = Nlevel;
CFR_data[0] = Modulation;
CFR_data[1] |= Sweep_en;
CFR_data[2] = 0x00;
if (Channel != 0) // 有通道被使能
{
AD9959_WriteData(FR1_ADD, 3, FR1_data); // 写功能寄存器1
AD9959_WriteData(FR2_ADD, 2, FR2_data); // 写功能寄存器1
AD9959_WriteData(CFR_ADD, 3, CFR_data); // 写通道功能寄存器
}
}
/************************************************************
** 函数名称 :void AD9959_SetFSK(uint8_t Channel, uint32_t *data,uint16_t Phase)
** 函数功能 :设置FSK调制的参数
** 入口参数 :Channel: 输出通道 CH0-CH3
*data: 调整频率数据的起始地址
Phase: 输出相位,范围:0~16383(对应角度:0°~360°)
** 出口参数 :无
** 函数说明 :FSK时信号幅度默认为最大
**************************************************************/
void AD9959_SetFSK(uint8_t Channel, uint32_t *data, uint16_t Phase)
{
uint8_t i = 0;
uint8_t CHANNEL[1] = {0x00};
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn
Write_CPOW0(Phase); // 设置相位
Write_CFTW0(data[0]);
for (i = 0; i < 15; i++)
Write_Profile_Fre(i, data[i + 1]);
}
/************************************************************
** 函数名称 :void AD9959_SetASK(uint8_t Channel, uint32_t *data,uint32_t fre,uint16_t Phase)
** 函数功能 :设置ASK调制的参数
** 入口参数 :Channel: 输出通道 CH0-CH3
*data: 调整幅度数据的起始地址
Freq: 输出频率,范围0~200 000 000 Hz
Phase: 输出相位,范围:0~16383(对应角度:0°~360°)
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void AD9959_SetASK(uint8_t Channel, uint16_t *data, uint32_t fre, uint16_t Phase)
{
uint8_t i = 0;
uint8_t CHANNEL[1] = {0x00};
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn
Write_CFTW0(fre); // 设置频率
Write_CPOW0(Phase); // 设置相位
Write_ACR(data[0]);
for (i = 0; i < 15; i++)
Write_Profile_Ampli(i, data[i + 1]);
}
/************************************************************
** 函数名称 :void AD9959_SetPSK(uint8_t Channel, uint16_t *data,uint32_t fre,uint16_t Phase)
** 函数功能 :设置PSK调制的参数
** 入口参数 :Channel: 输出通道 CH0-CH3
*data: 调整相位数据的起始地址
Freq: 输出频率,范围0~200 000 000 Hz
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void AD9959_SetPSK(uint8_t Channel, uint16_t *data, uint32_t Freq)
{
uint8_t i = 0;
uint8_t CHANNEL[1] = {0x00};
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn
Write_CFTW0(Freq);
Write_CPOW0(data[0]);
for (i = 0; i < 15; i++)
Write_Profile_Phase(i, data[i + 1]);
}
/************************************************************
** 函数名称 :void AD9959_SetFre_Sweep(uint8_t Channel, uint32_t s_data,uint32_t e_data,uint8_t fsrr,uint8_t rsrr,uint32_t r_delta,uint32_t f_delta,uint16_t Phase)
** 函数功能 :设置线性扫频的参数
** 入口参数 :Channel: 输出通道 CH0-CH3
s_data: 起始频率,范围0~200 000 000 Hz
e_data: 结束频率,范围0~200 000 000 Hz
r_delta:上升步长频率,0~200 000 000Hz
f_delta:下降步长频率,0~200 000 000Hz
rsrr: 上升斜率,范围:1~255,系统时钟为500Mhz时一个控制字约为8ns
fsrr: 下降斜率,范围:1~255
Ampli: 输出幅度,范围0~1023,控制值0~1023对应输出幅度0~500mVpp左右
Phase: 输出相位,范围:0~16383(对应角度:0°~360°)
** 出口参数 :无
** 函数说明 :频点与频点间停留时间 dT = Xsrr*8 单位ns,扫描点数=(起始-结束)/步长
扫频总时间=总扫描频点数*dT
**************************************************************/
void AD9959_SetFre_Sweep(uint8_t Channel, uint32_t s_data, uint32_t e_data, uint32_t r_delta, uint32_t f_delta, uint8_t rsrr, uint8_t fsrr, uint16_t Ampli, uint16_t Phase)
{
uint8_t CHANNEL[1] = {0x00};
uint32_t Fer_data = 0;
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn
Write_CPOW0(Phase); // 设置相位
Write_ACR(Ampli); // 幅度设置
Write_LSRR(rsrr, fsrr); // 斜率
Fer_data = (uint32_t)r_delta * ACC_FRE_FACTOR; // 频率转换成控制字
Write_RDW(Fer_data); // 上升步长
Fer_data = (uint32_t)f_delta * ACC_FRE_FACTOR;
Write_FDW(Fer_data); // 下降步长
Write_CFTW0(s_data); // 起始频率
Write_Profile_Fre(0, e_data); // 结束频率
}
/************************************************************
** 函数名称 :void AD9959_SetAmp_Sweep(uint8_t Channel, uint32_t s_Ampli,uint16_t e_Ampli,uint32_t r_delta,uint32_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Phase)
** 函数功能 :设置线性扫幅的参数
** 入口参数 :Channel: 输出通道 CH0-CH3
s_Ampli: 起始幅度,控制值0~1023对应输出幅度0~500mVpp左右
e_Ampli: 结束幅度,
r_delta: 上升步长幅度,0~1023
f_delta: 下降步长幅度,0~1023
rsrr: 上升斜率,范围:1~255,系统时钟为500Mhz时一个控制字约为8ns
fsrr: 下降斜率,范围:1~255
fre: 输出频率,范围0~200 000 000 Hz
Phase: 输出相位,范围:0~16383(对应角度:0°~360°)
** 出口参数 :无
** 函数说明 :幅点与幅点间停留时间 dT = Xsrr*8 单位ns;扫描点数=(起始-结束)/步长
扫幅总时间=总扫描幅点数*dT
**************************************************************/
void AD9959_SetAmp_Sweep(uint8_t Channel, uint32_t s_Ampli, uint16_t e_Ampli, uint32_t r_delta, uint32_t f_delta, uint8_t rsrr, uint8_t fsrr, uint32_t fre, uint16_t Phase)
{
uint8_t CHANNEL[1] = {0x00};
uint8_t ACR_data[3] = {0x00, 0x00, 0x00};
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn
Write_CFTW0(fre); // 幅度频率
Write_CPOW0(Phase); // 设置相位
Write_LSRR(rsrr, fsrr); // 斜率
Write_RDW(r_delta << 22); // 上升步长
Write_FDW(f_delta << 22); // 下降步长
ACR_data[1] = (uint8_t)(s_Ampli >> 8); // 高位数据
ACR_data[2] = (uint8_t)s_Ampli; // 低位数据
AD9959_WriteData(ACR_ADD, 3, ACR_data); // ACR 设定起始幅度
Write_Profile_Ampli(0, e_Ampli); // 结束幅度
}
/************************************************************
** 函数名称 :void AD9959_SetPhase_Sweep(uint8_t Channel, uint16_t s_data,uint16_t e_data,uint16_t r_delta,uint16_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Ampli)
** 函数功能 :设置线性扫相的参数
** 入口参数 :Channel: 输出通道 CH0-CH3
s_data: 起始相位,范围:0~16383(对应角度:0°~360°)
e_data: 结束相位,
r_delta:上升步长,范围:0~16383(对应角度:0°~360°)
f_delta:下降步长,
rsrr: 上升斜率,范围:1~255,系统时钟为500Mhz时一个控制字约为8ns
fsrr: 下降斜率,范围:1~255
fre: 输出频率,范围0~200 000 000 Hz
Ampli: 输出幅度,范围0~1023,控制值0~1023对应输出幅度0~500mVpp左右
** 出口参数 :无
** 函数说明 :频点与频点间停留时间 dT = Xsrr*8 单位ns;扫描点数=(起始-结束)/步长
扫频总时间=总扫描频点数*dT
**************************************************************/
void AD9959_SetPhase_Sweep(uint8_t Channel, uint16_t s_data, uint16_t e_data, uint16_t r_delta, uint16_t f_delta, uint8_t rsrr, uint8_t fsrr, uint32_t fre, uint16_t Ampli)
{
uint8_t CHANNEL[1] = {0x00};
CHANNEL[0] = Channel;
AD9959_WriteData(CSR_ADD, 1, CHANNEL); // 控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn
Write_CFTW0(fre); // 幅度频率
Write_ACR(Ampli); // 幅度设置
Write_LSRR(rsrr, fsrr); // 斜率
Write_RDW(r_delta << 18); // 上升步长
Write_FDW(f_delta << 18); // 下降步长
Write_CPOW0(s_data); // 起始相位
Write_Profile_Phase(0, e_data); // 结束相位
}
四、模块原理图与PCB文件
官方提供原理图:AD9959_pcb_0.pdf
Layout
总结
欢迎到本人仓库中看一看2023H和2024C的工程文件,如果有所帮助的话,请留下一颗star⭐吧,非常感谢!
SHR-sky/2023-H: 2023年电赛H题工程,完成所有问题。主控采用STM32,软件上采用DFT与FFT算法,通过控制定时器实现精准延时,从而实现相位校准,抑制漂移 (github.com)