一、AD9833模塊簡介
AD9833是一款低功耗、可編程波形發生器,能夠產生正弦波、三角波和方波輸出。各種類型的檢測、致動和時域反射(TDR)應用都需要波形發生器。 輸出頻率和相位可通過軟件進行編程,調整簡單。無需外部元件。 頻率寄存器為28位;時鐘速率為25MHz,可以實現0.1Hz的分辨率。 同樣,時鐘速率為1MHz時,AD9833可以實現0.004Hz的分辨率。
特性
- 模塊供電:DC 5V
- 模塊電流:10mA(MAX),正常驅動電流8mA(TYPE)
- 通訊協議:SPI串行
- 模塊主頻:25MHz(MAX)
- DAC分辨率:10位
- 相位累加器位數:28位
- 輸出通道:單通道輸出,A通道直接輸出,B通道帶濾波器輸出
- 輸出信號:正弦波、方波、三角波,正弦波帶9MHz低通濾波器
- 模塊信號特點:正弦波無耦合輸出,輸出自帶直流分量,接入射頻設備需加隔直器,也可直接使用示波器測量
- 最高主頻輸出信號范圍:正弦波:1Hz ~ 9MHz,方波:1Hz ~ 1MHz(方波占空比不可調)
- 輸出幅值:正弦波600mVpp(MAX),方波5Vpp,正弦波隨著頻率增加幅度減少,方波隨著頻率增加波形變化
- 輸出阻抗:200歐
應用
- 頻率信號發生,正弦波、方波、三角波信號發生,傳感器激勵等

二、模塊接口說明

| FSYNC | 低電平有效控制輸入 |
|---|---|
| SCLK | 串行時鐘輸入 |
| SDATA | 串行數據輸入 |
三、功能框圖和時序圖說明

頻率寄存器和相移寄存器:分別各兩個,可以配置兩個不同的頻率和相移,可通過設置激活其中一個。
12位地址截斷:28位相位累加器,但輸出被截斷至12位。使用相位累加器的全分辨率不僅不切實際,也根本不必要,因為這要求查找表具有2^28個條目。只需具有足夠的相位分辨率,使得因截斷而產生的誤差小于10位DAC的分辨率即可。這就要求SIN ROM的相位分辨率比10位DAC高出兩位。
MSB直接輸出:通過將10位DAC的MSB以數字直接輸出的形式到VOUT引腳,可以得到方波。也可以通過內置的2分頻通道將輸出頻率降低到原來的1/2。
控制寄存器:一個16位的控制寄存器

AD9833通信流程:數據以一個16位字的形式,通過SPI傳送到AD9833;通信開始前需將同步引腳拉低,且同步引腳拉低時時鐘線SCLK應為高電平;數據可一次傳輸一個字,傳輸完成后將同步引腳拉高結束通信;也可一次傳輸多個字,傳輸時保持同步引腳為低電平,直至多個字傳輸完成后拉高。
四、主要寄存器說明
控制寄存器
16 位寄存器,用于配置器件模式(如波形類型、復位、睡眠模式)。其中D1位選擇輸出正弦波還是三角波,D10-11位選擇用哪個頻率和相位寄存器,D12位選擇寫入頻率寄存器的MSB或LSB。
頻率寄存器
AD9833 有兩個獨立的 28 位頻率寄存器:FREQ0 和 FREQ1。用于精確控制輸出波形的頻率。它們存儲“頻率調諧字”(Frequency Tuning Word),該值決定了相位累加器的增量步長,從而生成所需的輸出頻率。兩個寄存器的設計允許快速切換頻率,例如在 FSK (頻率鍵控移位) 調制應用中,通過控制寄存器的 FSELECT 位(D11)來選擇使用哪個頻率寄存器(0 表示 FREQ0,1 表示 FREQ1)。
寄存器結構和位定義
總位寬:每個頻率寄存器均為 28 位,分成兩個部分:MSB (高 14 位) 和 LSB (低 14 位)。
位分配(表 7 和表 8所示):
MSB 14 位:對應頻率的高位部分,用于粗調。LSB 14 位:對應頻率的低位部分,用于細調。
寄存器地址(在串行寫入時,前兩位 D15:D14):
FREQ0:01 (D15:D14 = 01)。FREQ1:10 (D15:D14 = 10)
寫入流程
寫入頻率寄存器通過 3 線串行接口(FSYNC、SCLK、SDATA)進行,每次傳輸 16 位字(包括 2 位地址 + 14 位數據)。由于寄存器是 28 位,需要分兩次寫入:
控制寄存器設置:先寫入控制寄存器(地址 00),設置 B28 位 (D13) = 1(表示啟用 28 位連續寫入模式),以及 HLB 位 (D12) 來選擇寫入 MSB 或 LSB(1 表示 MSB,0 表示 LSB)。同時設置 FSELECT 位選擇目標寄存器(FREQ0 或 FREQ1)。
數據寫入:
如果 B28=1:連續發送兩個 16 位字(FSYNC 保持低電平)。
第一筆:地址 + LSB 14 位數據(例如,對于 FREQ0:D15:D14=01,D13:D0=LSB 數據)。
第二筆:地址 + MSB 14 位數據(相同地址,D13:D0=MSB 數據)。
如果 B28=0:可單獨寫入 MSB 或 LSB(使用 HLB 位選擇),但推薦使用連續發送模式以確保完整 28 位數據。SDATA 輸入可參考表 9,10,11。
相位寄存器
AD9833 有兩個獨立的 12 位相位寄存器:PHASE0 和 PHASE1。用于添加相位偏移到相位累加器的輸出,從而控制波形的起始相位或實現相位調制(如 PSK,相位鍵控移位)。通過控制寄存器的 PSELECT 位(D10)選擇使用哪個相位寄存器(0 表示 PHASE0,1 表示 PHASE1)。
寄存器結構和位定義
總位寬:每個相位寄存器均為 12 位(無 MSB/LSB 分割)。
位分配(表 7 和表 12所示):
12 位相位偏移字:對應相位的高精度調整。
寄存器地址(D15:D14=11):PHASE0 和 PHASE1 共享地址 11,可通過控制寄存器的 PSELECT 位區分。
寫入流程
相位寄存器寫入更簡單,因為只有 12 位:
控制寄存器設置:寫入控制寄存器(地址 00),設置 PSELECT 位選擇 PHASE0 或 PHASE1。B28 和 HLB 位不影響相位寫入。
數據寫入:單筆 16 位字傳輸。
SDATA = 11 (地址) + 相位 12 位數據,其中D13位選 PHASE0 還是 PHASE1,D12為無關位,D11-0為數據有效位。
注意:上電或復位后,頻率寄存器和相位寄存器默認為 0。

五、頻率和相位計算
頻率計算
輸出頻率 f_{OUT} 的計算基于以下公式:
f_{OUT} = {FREQREG} X f_{MCLK}}/{2^{28}}
FREQREG:28 位頻率調諧字的十進制值(范圍 0 ~ 2^{28} - 1 ≈ 268,435,455)。
f_{MCLK}: 外部主時鐘頻率(最高 25 MHz)。
分辨率:當 MCLK=25 MHz 時,最小頻率步長 ≈ 0.093 Hz(即 25X10^6 / 2^{28} ≈0.093 Hz。
示例:
假設 MCLK=25 MHz,想要輸出 1 kHz 正弦波。
計算 FREQREG = (1000X2^{28}) / 25X10^6 ≈10737.418(十進制)。
二進制(取整):0000 0000 0010 1001 1111 0001(28 位)。
分成 MSB/LSB:MSB=0000 0000 0000 0000,LSB=0010 1001 1111 0001。
寫入:先設置控制寄存器 B28=1, HLB=0(LSB 先),然后連續寫入兩個 16 位字。
相位計算

PHASEREG:12 位相位字的十進制值(范圍 0 ~ 4095)。
分辨率:最小相位步長 = 2π / 4096≈0.0015弧度(或約 0.088 度)。
滿量程:對應 2π 弧度(360 度)。
示例:
想要 90 度相位偏移(π/2 弧度)。
計算 PHASEREG = (90 / 360) * 4096 ≈ 1024(十進制)。
二進制:0100 0000 0000(12 位)。
寫入:SDATA = 1100 0100 0000 0000

六、STM32F103驅動AD9833輸出波形信號
準備工作
STM32F103C8T6最小系統板,AD9833模塊,OLED屏,EC11旋轉編碼器模塊,按鍵和導線若干。
引腳接線
| STM32F103C8T6 | AD9833 |
|---|---|
| PA3 | FSYNC |
| PA4 | SCLK |
| PA5 | SDATA |
| PA0 | EC11旋轉編碼器 -> B,減少頻率 |
| PA1 | EC11旋轉編碼器 -> A,增加頻率 |
| PA2 | EC11旋轉編碼器 -> S,移位調節 |
| PB8 | OLED -> SLC |
| PB9 | OLED -> SDA |
| PB12 | 按鍵,切換輸出波形 |

代碼示例
AD9833.c
#include "AD9833.h" // AD9833 definitions.
#include "delay.h" // AD9833 definitions.
#define FCLK 25000000 //設置晶振頻率
#define RealFreDat 268435456.0/FCLK//總的公式為 Fout=(Fclk/2的28次方)*28位寄存器的值
/***************************************************************************//**
* @brief Initializes the SPI communication peripheral and resets the part.
*
* @return 1.
*******************************************************************************/
unsigned char AD9833_Init(void)
{
AD9833_SPI_Init(0, 1000000, 1, 1);
AD9833_SetRegisterValue(AD9833_REG_CMD | AD9833_RESET);
return (1);
}
/***************************************************************************//**
* @brief Sets the Reset bit of the AD9833.
*
* @return None.
*******************************************************************************/
void AD9833_Reset(void)
{
AD9833_SetRegisterValue(AD9833_REG_CMD | AD9833_RESET);
delay_ms(10);
}
/***************************************************************************//**
* @brief Clears the Reset bit of the AD9833.
*
* @return None.
*******************************************************************************/
void AD9833_ClearReset(void)
{
AD9833_SetRegisterValue(AD9833_REG_CMD);
}
/***************************************************************************//**
* @brief Writes the value to a register.
*
* @param - regValue - The value to write to the register.
*
* @return None.
*******************************************************************************/
void AD9833_SetRegisterValue(unsigned short regValue)
{
unsigned char data[5] = {0x03, 0x00, 0x00};
data[1] = (unsigned char)((regValue & 0xFF00) > > 8);
data[2] = (unsigned char)((regValue & 0x00FF) > > 0);
ADI_CS_LOW;
AD9833_SPI_Write(data,2);
ADI_CS_HIGH;
}
void AD9833_SetFrequencyQuick(float fout,unsigned short type)
{
//AD9833_Setup(AD9833_FSEL0, AD9833_PSEL0, type);
AD9833_SetFrequency(AD9833_REG_FREQ0, fout,type);// 400 kHz
}
/***************************************************************************//**
* @brief Writes to the frequency registers.
*
* @param - reg - Frequence register to be written to.
* @param - val - The value to be written.
*
* @return None.
*******************************************************************************/
void AD9833_SetFrequency(unsigned short reg, float fout,unsigned short type)
{
unsigned short freqHi = reg;
unsigned short freqLo = reg;
unsigned long val=RealFreDat*fout;
freqHi |= (val & 0xFFFC000) > > 14 ;
freqLo |= (val & 0x3FFF);
AD9833_SetRegisterValue(AD9833_B28|type);
AD9833_SetRegisterValue(freqLo);
AD9833_SetRegisterValue(freqHi);
}
/***************************************************************************//**
* @brief Writes to the phase registers.
*
* @param - reg - Phase register to be written to.
* @param - val - The value to be written.
*
* @return None.
*******************************************************************************/
void AD9833_SetPhase(unsigned short reg, unsigned short val)
{
unsigned short phase = reg;
phase |= val;
AD9833_SetRegisterValue(phase);
}
/***************************************************************************//**
* @brief Selects the Frequency,Phase and Waveform type.
*
* @param - freq - Frequency register used.
* @param - phase - Phase register used.
* @param - type - Type of waveform to be output.
*
* @return None. AD9833_Setup(1000,0,AD9833_OUT_SINUS);
*******************************************************************************/
void AD9833_Setup(unsigned short freq,
unsigned short phase,
unsigned short type)
{
unsigned short val = 0;
val = freq | phase | type;
AD9833_SetRegisterValue(val);
}
/***************************************************************************//**
* @brief Sets the type of waveform to be output.
*
* @param - type - type of waveform to be output.
*
* @return None.
*******************************************************************************/
void AD9833_SetWave(unsigned short type)
{
AD9833_SetRegisterValue(type);
}
main.c
#include "stm32_config.h"
#include "stdio.h"
#include "key.h"
#include "Encoder.h"
#include "OLED.h"
#include "ad9833.h"
uint8_t mode;
uint32_t last_value = 0xFFFFFFFF;
uint8_t start;
uint32_t value;
int main(void)
{
MY_NVIC_PriorityGroup_Config(NVIC_PriorityGroup_2); //設置中斷分組
delay_init(72); //初始化延時函數
Key_Init();
OLED_Init();
Encoder_Init();
AD9833_Init();
AD9833_SetFrequencyQuick(10000,AD9833_OUT_SINUS);
delay_ms(100);
OLED_ShowString(0,5,"AD9833",16,1);
OLED_ShowChinese(70,5,0,16,1);
OLED_ShowChinese(86,5,1,16,1);
OLED_ShowChinese(102,5,2,16,1);
OLED_ShowString(95,160,"Hz",16,1);
OLED_Refresh();
while(1)
{
KeyEvent_TypeDef key_event = Key_Scan();
switch (key_event)
{
case KEY_MODE_CLICK:
// Mode鍵短按事件
mode++;
if (mode > 2) mode = 0;
switch(mode)
{
case 0:
OLED_ShowChinese(70,5,0,16,1);
OLED_ShowChinese(86,5,1,16,1);
OLED_ShowChinese(102,5,2,16,1);
start = AD9833_OUT_SINUS;
AD9833_SetFrequencyQuick(value, start);
break;
case 1:
OLED_ShowChinese(70,5,3,16,1);
OLED_ShowChinese(86,5,4,16,1);
OLED_ShowChinese(102,5,5,16,1);
start = AD9833_OUT_TRIANGLE;
AD9833_SetFrequencyQuick(value, start);
break;
case 2:
OLED_ShowChinese(70,5,6,16,1);
OLED_ShowChinese(86,5,7,16,1);
OLED_ShowString(102,5," ",16,1);
start = AD9833_OUT_MSB;
AD9833_SetFrequencyQuick(value, start);
break;
}
break;
// case KEY_MODE_LONG:
// // Mode鍵長按事件
// break;
// case KEY_MODE_REPEAT:
// // Mode鍵連發事件
// break;
// case KEY_GROUP_CLICK:
// // Group鍵短按事件
// break;
// case KEY_GROUP_LONG:
// // Group鍵長按事件
// break;
// case KEY_GROUP_REPEAT:
// // Group鍵連發事件
// break;
// default:
// break;
}
delay_ms(10);
Encoder_Value_Update();
Encoder_Display();
value = Encoder_GetValue();
if (value != last_value)
{
AD9833_SetFrequencyQuick(value, start);
last_value = value;
OLED_ShowNum(20, 160, value, 9, 16, 1);
OLED_Refresh();
}
delay_ms(10);
OLED_Refresh();
}
}
效果展示

下圖為輸出方波信號,經過濾波后輸出(藍色)和直接輸出(黃色)的比較
七、注意事項和常見問題
注意事項
(1)模塊為低功耗模塊,供電電源不超過5.5V。
(2)由于模塊是高精度器件,為了避免不必要的干擾,建議使用線性電源供電。
(3)輸出信號建議使用SMA轉BNC的線直接示波器觀測效果,接觸不良或劣質的線材可能導致信號衰減或者噪聲過大。
(4)如需簡單測試模塊功能,建議搭配本店控制板使用,先給DDS 模塊供電,再給控制板供電即可產生波形,長按中間鍵切換功能。
常見問題
Q:AD9833模塊的2個輸出口是什么關系,可以設置成不同的頻率輸出嗎?
A:首先AD9833芯片只有一個輸出通道。模塊的A通道為芯片直接輸出,B通道為A通道經濾波后輸出。所以模塊的2個輸出口不能設置不同的頻率輸出。
Q:模快的主頻是多少?輸出幅度可以調節嗎?
A:模塊的主頻是輸入時鐘決定的,板載默認時鐘為25MHz,即默認主頻為25MHz。輸出幅度是固定的,沒有辦法程控。
Q:模塊可以實現掃頻么?方波占空比可調嗎?
A:模塊可以實現掃頻,本店提供的代碼可支持掃頻。模塊方波占空比不可以調節,邊沿時間為ns級。
Q:通道A和B可以獨立調節嗎?可以做調制嗎?
A:兩個通道固定相差180度,B通道有濾波器,建議使用正弦波和三角波,A通道為直接輸出建議使用方波,不可獨立調節。默認代碼是點頻信號,無法做調制。
-
STM32
+關注
關注
2309文章
11162瀏覽量
373423 -
信號發生器
+關注
關注
28文章
1700瀏覽量
113395 -
波形發生器
+關注
關注
3文章
320瀏覽量
32709
發布評論請先 登錄
AD9833來產生30-100KHZ的TTL方波但只能輸出正弦波和三角波
AD9833產生30K—100KHZ的頻率信號要求輸出TTL方波但AD9833只能輸出正弦波或者三角波
51與adc0832++++信號發生器+可產生正弦波、方波、三角波+含ISIS仿真
如何使用Arduino和AD9833構建信號發生器
基于STM32F103驅動AD9833模塊 DDS信號發生器輸出正弦波/三角波/方波可編程信號
評論