一、AD9851模塊簡介
??AD9851是一款高度集成的器件,采用先進的DDS技術,再加上內(nèi)部高速,高性能的D/A轉換器和比較器,形成一個數(shù)字可編程頻率合成器和時鐘發(fā)生器功能。當參考準確的時鐘源時,AD9851產(chǎn)生穩(wěn)定的頻率并進行相位可編程的數(shù)字化模擬輸出正弦波。該正弦波可以直接用作頻率源,或內(nèi)部轉換為方波敏捷時鐘生成器應用程序。 AD9851的創(chuàng)新高速DDS內(nèi)核接受32位頻率調(diào)諧字,導致輸出調(diào)諧分辨率約為系統(tǒng)時鐘為180MHz時為0.04Hz。AD9851包含獨特的 6XREFCLK乘法器電路消除了需要一個高速參考振蕩器。 6XREFCLK乘法器對SFDR和相位噪聲特性的影響最小。
特性
- 通訊協(xié)議:SPI串行/并行
- 180MHz時鐘頻率,可選6位參考時鐘
- DAC分辨率:10位
- 相位累加器:32位
- 輸出信號:正弦波,方波。正弦波帶65MHz低通濾波器,方波耦合輸出
- 輸出通道:2通道差分。相位差180度,高頻輸出由于有濾波器,相位會偏移
- 信號特點:正弦波無耦合輸出。輸出帶自帶直流分量,接入射頻設備請加隔直器也可直接使用示波器測量
- 輸出正弦波/方波最高主頻:1Hz-65M/30MHz,方波10MHz以上需要示波器輸入阻抗為50歐,方波占空比可調(diào)
- 輸出幅度:正弦波1000mVpp,方波5Vpp,正弦波隨頻率增加幅度減小,方波隨著頻率增加波形變化
- 輸出阻抗:75歐

二、AD9851引腳說明
| D0-D7 | 8 位數(shù)據(jù)輸入。用于加載 32 位頻率字和 8 位相位/控制字的數(shù)據(jù)端口。D7 = MSB,D0 = LSB。D7也用作 40 位串行數(shù)據(jù)字的輸入引腳。 |
|---|---|
| W_CLK | 串行時鐘輸入。上升沿將并行或串行頻率/相位/控制字異步加載到 40 位輸入寄存器中。 |
| FQ_UD | 頻率更新。上升沿異步傳輸 40 位輸入寄存器的內(nèi)容,以供 DDS 內(nèi)核處理。當已知輸入寄存器的內(nèi)容僅包含有效且允許的數(shù)據(jù)時,應發(fā)出 FQ_UD。 |
| RSET | 主復位引腳,高電平有效。 |
| OUT | DAC差分輸出 |

三、功能框圖和時序圖分析



時序簡單分析:
- 復位
RESET 拉高 → 相位累加器清零,默認進入 并行模式,PLL 關閉。 - 并行方式
每次通過 W0–W4 裝載 40 位數(shù)據(jù)(8 位一組),W0 含控制字與相位字,W1–W4 為頻率調(diào)諧字。
WCLK 上升沿鎖存數(shù)據(jù),最后 FQ_UD 上升沿觸發(fā)更新。 - 串行方式
首先在并行方式下寫入特殊碼 xxxxx011 → 切換至串行。
串行移入 40 位數(shù)據(jù),LSB 先行,最后 FQ_UD 上升沿更新。 - 延遲
頻率更新延遲:約 18 個 SYSCLK 周期。
相位更新延遲:約 13 個 SYSCLK 周期。
四、并行/串行裝載 40位控制字分配
??并行裝載:W0 是“控制 + 相位”字;W1~W4 是 32 位頻率調(diào)諧字(FTW,W1 放 MSB)。其中W0位定義為:
????D7…D3:Phase[4:0](D7 是相位 MSB,D3 是相位 LSB,步進 11.25°)
????D2:低功耗
????D1:邏輯 0(僅在“請求進入串行模式”時臨時使用;進入后必須再寫回 0)
????D0:6× REFCLK 倍頻使能

??串行裝載:40-bit 一次性移入,先 32 位頻率,再控制,再相位。

進入串行模式需要留意的地方:
??上電復位后默認并行模式。在并行端口寫入 W0 時,把 D1 置 1(僅用于“請求串行”),D0 按你是否要啟用 ×6 設置;隨后按手冊 Figure 17 的時序切換到串行移位口。進入后務必再把并口 W0 的 D1 寫回 0。串行移位是按位 LSB-first;若用 MCU 的 SPI(通常 MSB-first),要么“反相/反序”配置 SPI,要么對每個字節(jié)做逐字節(jié)位反轉再發(fā)。

五、STM32F103驅動AD9851
準備工作
??STM32F103ZET6開發(fā)板、AD9851模塊、OLED顯示屏、EC11旋轉編碼器。
接線說明
| STM32F103ZET6 | AD9851模塊 |
|---|---|
| PA3 | FQ |
| PA4 | CLK |
| PA6 | REST |
| PC0 | D0 |
| PC1 | D1 |
| PC2 | D2 |
| PC3 | D3 |
| PC4 | D4 |
| PC5 | D5 |
| PC6 | D6 |
| PC7 | D7 |
| PA0 | 旋轉編碼器-A ,用于調(diào)節(jié)輸出頻率 |
| PA1 | 旋轉編碼器-B ,用于調(diào)節(jié)輸出頻率 |
| PA2 | 旋轉編碼器-S,移位調(diào)節(jié) |
| PB8 | OLED-SCL |
| PB9 | OLED-SDA |
| 5V | 5V |
| GND | 共地 |
其中,當使用串行驅動時,DO、D1、D2腳需輸入(110)固定電平,D3-6可以懸空不接,D7用作40位串行數(shù)據(jù)輸入引腳。

示例代碼
AD9851.c
//***************************************************//
//函數(shù)1: ad9851_reset() //
//函數(shù)2: ad9851_reset_serial() //
//函數(shù)3: ad9851_wr_parrel(unsigned char w0,double frequence)//
//函數(shù)4: ad9851_wr_serial(unsigned char w0,double frequence)//
//***************************************************//
// 子程序說明 //
//***************************************************//
//函數(shù)1: ad9851_reset()
// 復位ad9851,之后為并口寫入模式
//函數(shù)2: ad9851_reset_serial()
// 復位ad9851,之后為串口寫入模式
//函數(shù)3: ad9851_wr_parrel(unsigned char w0,double frequence)
// 并口寫ad9851數(shù)據(jù),w0為ad9851中w0的數(shù)據(jù),frequence
// 為寫入的頻率
//函數(shù)4: ad9851_wr_serial(unsigned char w0,double frequence)
// 串口寫ad9851數(shù)據(jù),w0為ad9851中w0的數(shù)據(jù),frequence
// 為寫入的頻率
//需定義的位:
//ad9851_w_clk ;
//ad9851_fq_up ;
//ad9851_rest ;
//ad9851_bit_data ;
//例:
//sbit ad9851_w_clk =P2^2;
//sbit ad9851_fq_up =P2^1;
//sbit ad9851_rest =P2^0;
//sbit ad9851_bit_data =P1^7;
//***************************************************//
// 寫數(shù)據(jù)說明 //
//***************************************************//
//寫數(shù)據(jù)例:
// ad9851_reset()
// wr_lcd02_data(unsigned char x)
// ad9851_wr_parrel(0x01,1000)
// ad9851_wr_serial(0x01,1000)
//***************************************************//
//---------------------------------------------------//
// 程序 //
//---------------------------------------------------//
# include <AD9851.h>
# include <stdio.h>
u8 AD9851_FD=0x00; //倍頻數(shù)
void (*_AD9851_Setfq)(u8 w0,double frequence);
//P1為8位數(shù)據(jù)口
//***************************************************//
// ad9851復位(并口模式) //
//---------------------------------------------------//
void ad9851_reset()
{
ad9851_w_clk=0;
ad9851_fq_up=0;
//rest信號
ad9851_rest=0;
ad9851_rest=1;
ad9851_rest=0;
}
//***************************************************//
// ad9851復位(口模式) //
//---------------------------------------------------//
void ad9851_reset_serial()
{
ad9851_w_clk=0;
ad9851_fq_up=0;
//rest信號
ad9851_rest=0;
ad9851_rest=1;
ad9851_rest=0;
//w_clk信號
ad9851_w_clk=0;
ad9851_w_clk=1;
ad9851_w_clk=0;
//fq_up信號
ad9851_fq_up=0;
ad9851_fq_up=1;
ad9851_fq_up=0;
}
//***************************************************//
// 向ad9851中寫命令與數(shù)據(jù)(并口) //
//---------------------------------------------------//
void ad9851_wr_parrel(u8 w0,double frequence)
{
u32 w;
long int y;
double x;
//計算頻率的HEX值
x=4294967295/180;//適合180M晶振/180為最終時鐘頻率(或30M六倍頻)
//如果時鐘頻率不為180MHZ,修改該處的頻率值,單位MHz ?。。?frequence=frequence/1000000;
frequence=frequence*x;
y=frequence;
//寫w0數(shù)據(jù)
w=w0;
AD9851_DataBus=w|(w^0xff)<<16; //w0
ad9851_w_clk=1;
ad9851_w_clk=0;
//寫w1數(shù)據(jù)
w=(y>>24);
AD9851_DataBus=w|(w^0xff)<<16; //w0
ad9851_w_clk=1;
ad9851_w_clk=0;
//寫w2數(shù)據(jù)
w=(y>>16);
AD9851_DataBus=w|(w^0xff)<<16; //w0
ad9851_w_clk=1;
ad9851_w_clk=0;
//寫w3數(shù)據(jù)
w=(y>>8);
AD9851_DataBus=w|(w^0xff)<<16; //w0
ad9851_w_clk=1;
ad9851_w_clk=0;
//寫w4數(shù)據(jù)
w=(y>>=0);
AD9851_DataBus=w|(w^0xff)<<16; //w0
ad9851_w_clk=1;
ad9851_w_clk=0;
//移入始能
ad9851_fq_up=1;
ad9851_fq_up=0;
}
//***************************************************//
// 向ad9851中寫命令與數(shù)據(jù)(串口) //
//---------------------------------------------------//
void ad9851_wr_serial(u8 w0,double frequence)
{
unsigned char i,w;
long int y;
double x;
//計算頻率的HEX值
x=4294967295/125;//適合180M晶振/180為最終時鐘頻率(或30M六倍頻)
//如果時鐘頻率不為180MHZ,修改該處的頻率值,單位MHz ?。。?frequence=frequence/1000000;
frequence=frequence*x;
y=frequence;
//寫w4數(shù)據(jù)
w=(y>>=0);
for(i=0;i<8;i++)
{
ad9851_bit_data=(w>>i)&0x01;
ad9851_w_clk=1;
ad9851_w_clk=0;
}
//寫w3數(shù)據(jù)
w=(y>>8);
for(i=0;i<8;i++)
{
ad9851_bit_data=(w>>i)&0x01;
ad9851_w_clk=1;
ad9851_w_clk=0;
}
//寫w2數(shù)據(jù)
w=(y>>16);
for(i=0;i<8;i++)
{
ad9851_bit_data=(w>>i)&0x01;
ad9851_w_clk=1;
ad9851_w_clk=0;
}
//寫w1數(shù)據(jù)
w=(y>>24);
for(i=0;i<8;i++)
{
ad9851_bit_data=(w>>i)&0x01;
ad9851_w_clk=1;
ad9851_w_clk=0;
}
//寫w0數(shù)據(jù)
w=w0;
for(i=0;i<8;i++)
{
ad9851_bit_data=(w>>i)&0x01;
ad9851_w_clk=1;
ad9851_w_clk=0;
}
//移入始能
ad9851_fq_up=1;
ad9851_fq_up=0;
}
void AD9851_IO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure ;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE); //使能PB,PE端口時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1| GPIO_Pin_2| GPIO_Pin_3| GPIO_Pin_4| GPIO_Pin_5| GPIO_Pin_6| GPIO_Pin_7 ;
GPIO_Init(GPIOC ,&GPIO_InitStructure) ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4| GPIO_Pin_6;
GPIO_Init(GPIOA ,&GPIO_InitStructure) ;
}
void AD9851_Setfq(double fq)
{
if(ad9851_ad9850)
{
fq *= 1.44;
AD9851_FD = 0;
}
_AD9851_Setfq(AD9851_FD,fq);
}
//***************************************************//
// 測試程序1000Hz //
//---------------------------------------------------//
//輸入:mode ad9851_parallel 并口 ad9851_serial 串口
//FD:0:不倍頻 1:2倍頻
void AD9851_Init(u8 mode,u8 FD)
{
AD9851_IO_Init();
AD9851_DataBus=0x00|(~0x00)<<16;
// ad9851_reset_serial();
// ad9851_wr_serial(0x00,1000000);
if(mode==ad9851_parallel){_AD9851_Setfq=ad9851_wr_parrel;ad9851_reset();}
else {_AD9851_Setfq=ad9851_wr_serial;ad9851_reset_serial();}
if(FD==1)AD9851_FD=0x01;
// AD9851_Setfq(1000000);
}
main.c
#include "stm32_config.h"
#include "stdio.h"
#include "Encoder.h"
#include "OLED.h"
#include "ad9851.h"
u32 SweepMinFre = 1000;
u32 SweepMaxFre = 1000000;
void SweepFre(void)
{
if(SweepMinFre > SweepMaxFre) SweepMinFre = 1000;
SweepMinFre += SweepMinFre;
AD9851_Setfq(SweepMinFre);
}
int main(void)
{
MY_NVIC_PriorityGroup_Config(NVIC_PriorityGroup_2); //設置中斷分組
delay_init(72); //初始化延時函數(shù)
OLED_Init();
Encoder_Init();
delay_ms(300);
AD9851_Init(ad9851_parallel, 1);
AD9851_Setfq(1000);
// ad9851_wr_serial(0,1000);
// delay_ms(100);
OLED_ShowString(40,5,"AD9851",16,1);
OLED_ShowString(95,160,"Hz",16,1);
OLED_Refresh();
while(1)
{
Encoder_Value_Update();
Encoder_Display();
uint32_t value = Encoder_GetValue();
if(value > 65000000) value = 1000;
AD9851_Setfq(value);
OLED_ShowNum(20, 160, value, 9, 16, 1);
OLED_Refresh();
delay_ms(10);
// SweepFre();
// delay_ms(200);
}
}
效果展示


注意事項和常見問題
注意事項
??(1)模塊為低功耗模塊,供電電源不超過5.2V。
??(2)由于模塊是高精度器件,為了避免不必要的干擾,建議使用線性電源供電。
??(3)輸出信號建議使用SMA轉BNC的線直接示波器觀測效果,接觸不良或劣質(zhì)的線材可能導致信號衰減或者噪聲過大。
??(4)配送的代碼僅為配套主控板使用,不提供單片機教程,額外功能需要自行開發(fā)。
??(5)如需簡單測試模塊功能,建議搭配本店控制板使用,先給DDS 模塊供電,再給控制板供電即可產(chǎn)生波形,長按中間鍵切換功能。
常見問題
??Q:AD9851模塊的2個輸出口是什么關系,可以設置成不同的頻率輸出嗎?
??A:AD9851模塊的2個輸出口不能設置成不同的頻率輸出。OUT1與 OUT1相位固定相差180°。
??Q:模快的主頻是多少?輸出幅度可以調(diào)?
??A:模塊的主頻是輸入時鐘和程序一起決定的,板載默認時鐘為30MHz,程序控制倍頻為6倍,即默認主頻為180MHz。輸出幅度是固定的,沒有辦法程控。
??Q:模塊可以實現(xiàn)掃頻么?方波占空比可調(diào)嗎?
??A:模塊可以實現(xiàn)掃頻。本店提供的代碼可支持掃頻。模塊方波占空比可以調(diào)節(jié)。
??Q:兩通道可以獨立調(diào)節(jié)嗎?可以做調(diào)制嗎?
??A:兩個通道固定相差180度,頻率高了由于濾波器作用可能相移,不可獨立調(diào)節(jié)。默認代碼是點頻信號,其他模式需要自行編程。