本文利用FPGA控制AD9833,实现信号发生器的功能。本文将对AD9833的手册进行详细的解读,并对其配置方法进行解析,最后在Verilog中进行编码,将代码烧录置FPGA中,FPGA通过外部引脚控制AD9833输出所需要的正弦波、方波和三角波。三种波形能够输出的频率范围为0~12.5Mhz。
文章目录
前言
AD9833是一种低功率可编程波形发生器,能够产生正弦、三角形和方波输出。在各种类型的传感、驱动和时域反射测量应用中,都需要产生波形。输出频率和相位是软件可编程的,允许易于调整。不需要任何外部组件。频率寄存器为28位;以25MHz的时钟速率,可以达到0.1 Hz的分辨率。类似地,使用1MHz的时钟速率,AD9833可以被调谐到0.004 Hz的分辨率。
AD9833是通过三线串行接口写入的。该串行接口以时钟速率高达40MHz,并与DSP和微控制器标准兼容。该设备的电源供电范围为2.3V至5.5V。
一、AD9833数据手册分析
博主将首先分析AD9833的数据手册,并列出博主认为手册中需要着重注意的点,以便于后续代码的提出。
1.1 AD9833特性分析
在AD9833的规格中,我们可以知道,其
V
o
u
t
V_{out}
Vout 也就是最大输出电压可以达到0.65V,其具体的表达式如下:
V
O
U
T
=
V
R
E
F
×
18
×
R
LOAD
/
R
S
E
T
×
(
1
+
(
S
I
N
(
2
π
(
F
R
E
Q
R
E
G
×
f
M
C
L
K
×
t
/
2
28
+
P
H
A
S
E
R
E
G
/
2
12
)
)
)
)
V_{\mathsf{OUT}}=V_{\mathsf{REF}}\times18\times\mathsf{R}_\text{LOAD}/{ \mathsf{R}_{\mathsf{SET}}}\times(1+(\mathsf{SIN}(2\pi(\mathsf{FREQREG}\times\mathbf{f}_{\mathsf{MCLK}}\times\mathbf{t}_{/2}28+\mathsf{PHASEREG}_{/2}12))))
VOUT=VREF×18×RLOAD/RSET×(1+(SIN(2π(FREQREG×fMCLK×t/228+PHASEREG/212))))
即:输出电压的大小跟参考电压和负载电阻密切相关,同时随着设置波形频率的变化而变化。
另外,AD9833的VDD的范围为2.3V-5.5V,也就是说你需要提供一定数值的电源电压。
1.2 AD9833时钟分析
在手册中,我们可以看到AD9833的时钟图如图1所示:
在图1中,我们需要着重关注的是AD9833的MCLK周期最小为40ns,也就是说你需要提供25Mhz的激励时钟信号,用于驱动AD9833进行内部数据操作。
观察图2,我们可知:如何需要写入AD9833的控制字,我们首先需要将FSYNC拉低,在SCLK操作时钟的周期性变化下,将SDATA也就是操作字逐一写入。需要注意的是,SCLK的操作时钟周期最小需要25ns,高低电平的维持时间最小需要10ns,在最后一个下降沿数据写入后需要在10ns-20ns
的时间内将FSYNC的电平拉高,否则写入无效。
1.3 AD9833引脚分析
AD9833的引脚图如图3所示:
在AD9833的引脚中,MCLK为激励时钟,我们采用25Mhz;FSYNC在拉低后进行写入操作,随着SCLK的电平变化将SDATA的值读入。另外,VDD和AGND之间应连接一个0.1uF和一个10uF的解耦电容。
1.4 AD9833操作原理分析
要想讲清楚AD9833的控制方式,我们需要重点观察其操作字是如何定义的。
在上述的16个控制位中,博主将讲解需要着重观察的控制位,其他控制位请读者自行查看手册。
- B28
当B28 = 1时允许连续两次写入将完整单词加载到频率寄存器中。第一次写包含频率单词的14个LSB,下一次写将包含14个MSB。每个16位字的前两位定义了该字被加载到的频率寄存器,因此,对于这两个连续的写操作,前两位应该是相同的。
当B28 = 0时,28位频率寄存器作为两个14位寄存器运行,一个包含14个MSB,另一个包含14个LSB。这意味着频率词的14个MSB可以独立于14个LSB进行改变,反之亦然。为了改变14个MSB或14个LSB,需要对适当的频率地址进行一次写入。控制位D12(HLB)通知AD9833,要改变的位是14个MSB还是14个LSB。
博主在后文中将B28 = 1,也就是连续写入两个16位字对频率寄存器进行更改。 - RESET
RESET = 1将内部寄存器重置为0,这对应于中度的模拟输出。
RESET = 0将禁用重置。
需要注意的是,RESET将不重置相位、频率和控制寄存器。另外,为了避免AD9833在初始化的时候出现虚假的DAC输出,需要在进行写入操作时也就是B28 = 1时将RESET位置1。 - MODE
MODE位与OPBITEN(D5)一起使用。这个位的功能是控制芯片上DAC连接到VOUT时VOUT引脚的输出。
当MODE = 1时三角波将从DAC中输出。
当MODE = 0时正弦波将输出。
接下来我们将利用代码来详细论述操作字的写入流程。
二、FPGA控制代码
我们将利用Verilog语言编写FPGA的代码,并用FPGA控制AD9833的SCLK、SDATA、FSYNC引脚,进行写入操作。
2.1 主函数
主函数中主要包含了各个模块,并将模块之间的变量联系起来。
module Signal_Generate(
input sys_clk,
input sys_rst_n,
input key0, // 按键检测切换波形状态
input key1,
output MCP_CS, // MCP使能标志 低电平有效
output SCK, // MCP输入信号状态 低电平信号变化 下降沿读信号
output SI, // MCP输入信号
output AD_FSYNC // AD使能标志
);
// parameter define
parameter CLK_FREQ = 26'd50_000_000; // MCP模块的驱动时钟频率
parameter MCP_FREQ = 18'd25_000_000; // MCP的SCK时钟频率
// wire define
wire MCP_CLK; // MCP时钟信号
wire locked;
wire [15:0] TxData; // 写入AD的操作数
wire TxData_en; // 开始写入标志位
wire TxData_done; // 写入完成标志位
wire [ 7:0] counter_rem; // 实时观察写入情况
wire [ 7:0] counter_rem_driver; // 实时观察驱动情况
//***************************************************
//**** main code ****
//***************************************************
// 例化按键消抖模块
key_debounce u_key0_debounce(
.clk (sys_clk),
.rst_n (sys_rst_n),
.key (key0),
.key_value (key0_value), // 按下后为低电平 输出
.key_flag (key0_flag) // 按下后标志位拉高 输出
);
key_debounce u_key1_debounce(
.clk (sys_clk),
.rst_n (sys_rst_n),
.key (key1),
.key_value (key1_value), // 按下后为低电平 输出
.key_flag (key1_flag) // 按下后标志位拉高 输出
);
// AD根据操作数写入16bits模块
AD_Write u_AD_Write(
.clk (sys_clk),
.rst_n (sys_rst_n),
.TxData (TxData), // 写入16位二进制操作数
.TxData_en (TxData_en), // 开始写入标志位 输入
.TxData_done(TxData_done), // 写入完成标志位 输出
.counter_rem(counter_rem), // 实时检查写入位置
.AD_SCK (SCK), // AD操作时钟
.AD_FSYNC (AD_FSYNC), // AD使能标志位
.AD_SI (SI) // AD写入数据
);
// AD驱动模块
AD_Driver u_AD_Driver(
.clk (sys_clk),
.rst_n (sys_rst_n),
.key0_value (key0_value),
.key0_flag (key0_flag),
.key1_value (key1_value),
.key1_flag (key1_flag),
.counter_rem_driver (counter_rem_driver), // 实时检查驱动位置
.TxData_done (TxData_done), // 写入完成标志位 输入
.TxData (TxData), // 写入操作数
.TxData_en (TxData_en) // 开始写入标志位 输出
);
// ILA检测模块
ila_0 u_ila_0(
.clk (sys_clk), // input wire clk
.probe0 (AD_FSYNC), // input wire [0:0] probe0
.probe1 (SCK), // input wire [0:0] probe1
.probe2 (SI), // input wire [0:0] probe2
.probe3 (TxData_en), // input wire [0:0] probe3
.probe4 (TxData_done), // input wire [0:0] probe4
.probe5 (TxData), // input wire [15:0] probe5
.probe6 (counter_rem_driver) // input wire [7:0] probe6
);
endmodule
接下来,我将对函数的主要功能进行介绍。
- key_debounce
此函数的主要功能是对外部按键KEY0和KEY1是否按下进行判断,当KEY0按下后,将进行波形变换操作,当KEY1按下后,将进行频率变换操作。后文会有提及。 - AD_Write
此函数主要功能是将一个16位的操作字根据一定的时序写入到AD9833中,在写入完成后将TxData_done
置位,AD_Driver接收到置位信息后,将后续需要写入的操作字赋值给TxData
中,并将开始写入标志位TxData_en
置位。 - AD_Driver
此函数的主要功能是根据当前状态变更状态字,以及控制AD9833需要输出的波形和频率。 - ILA
检测模块ILA用于实时检测。
2.2 按键检测模块
按键检测模块通过延时消抖来检测按键值变化是否有效。
module key_debounce(
input clk,
input rst_n,
input key, // 外部输入按键值
output reg key_value, // 消抖后的按键值
output reg key_flag // 消抖后的按键值有效标志
);
reg [19:0] cnt;
reg key_reg;
// 按键值消抖
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt <= 20'd0;
key_reg <= 1'b1;
end
else begin
key_reg <= key;
if(key_reg != key) begin // 检测到按键值变化
cnt <= 20'd100_0000; // 开启延时
end
else begin
if(cnt > 20'd0) // 延时过程
cnt <= cnt - 1'b1;
else
cnt <= 20'd0;
end
end
end
// 输出最终值
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
key_value <= 1'b1; // 没有按下时默认为高电平
key_flag <= 1'b0; // 标志位为无效标志
end
// 计时器递减到1时输出按键值
else if(cnt == 20'd1) begin
key_value <= key; // 将消抖后的数值保存
key_flag <= 1'b1; // 标志位为有效标志
end
else begin
key_value <= key_value; // 计时器为结束则保持原有数值
key_flag <= 1'b0;
end
end
endmodule
KEY0和KEY1在复位状态下为高电平,当按键按下后变更为低电平。在此模块中,我们用key_reg
寄存器来存储上一时刻KEY的状态,当检测到其与当前时刻的KEY状态不一致时进行100_0000个时钟周期的延时,也就是20ns*100_0000=20ms的延时,如果按键状态在该时间内为发生变化说明按下有效。将key_value
和key_flag
位变更。
2.3 操作写入模块
此模块,用于将操作字根据一定的时序写入。
module AD_Write(
input clk,
input rst_n,
input [15:0] TxData, // 写入16位二进制操作数
input TxData_en, // 开始写入标志位
output reg TxData_done, // 写入完成标志位
output counter_rem, // 实时检查写入位置
output reg AD_SCK, // AD操作时钟
output reg AD_FSYNC, // AD使能标志位
output reg AD_SI // AD写入数据
);
// reg define
reg [15:0] data; // 写入的16位操作数
reg [ 7:0] counter; // 写入时序
reg tx_en; // 保存写入标志位
// wire define
//***************************************************
//**** main code ****
//***************************************************
assign counter_rem = counter;
// 使能后频数计数器
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
counter <= 8'd0;
TxData_done <= 1'b0;
tx_en <= 1'b0;
end
else begin
// 接收到发送信号
if(TxData_en) begin
tx_en <= 1'b1; // 保存开始写入标志位
end
else begin
if(tx_en) begin // 数据发送时使能计数器
if(counter < 8'd33) begin
counter <= counter + 1'b1;
TxData_done <= 1'b0;
end else begin // 在counter计数到完成操作后重置
counter <= 8'd0;
tx_en <= 1'b0; // 结束发送
TxData_done <= 1'b1; // 置位操作完成位
end
end
else begin
counter <= 8'd0;
TxData_done <= 1'b0;
tx_en <= tx_en;
end
end
end
end
// Control the AD_SCK, AD_FSYNC, and DAT pins based on the TxData input
// AD在SCK为高电平时改变状态 在SCK下降沿时写入数据
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
AD_SCK <= 1;
AD_FSYNC <= 1;
AD_SI <= 0;
end else begin
// 开始发送16bits数据
if(tx_en) begin
case(counter)
// 准备工作
8'd0: begin
data <= TxData; // 寄存数据
AD_SCK <= 1; // FSYNC拉低时SCK为高
AD_FSYNC <= 0; // 使能发送
AD_SI <= 0; // 默认
end
// first 16bits
8'd1: begin
AD_SCK <= 1;
AD_SI <= data[15]; // SI取数据最高位
end
8'd2: begin
AD_SCK <= 0;
end
8'd3: begin
AD_SCK <= 1;
AD_SI <= data[14];
end
8'd4: begin
AD_SCK <= 0;
end
8'd5: begin
AD_SCK <= 1;
AD_SI <= data[13];
end
8'd6: begin
AD_SCK <= 0;
end
8'd7: begin
AD_SCK <= 1;
AD_SI <= data[12];
end
8'd8: begin
AD_SCK <= 0;
end
8'd9: begin
AD_SCK <= 1;
AD_SI <= data[11];
end
8'd10: begin
AD_SCK <= 0;
end
8'd11: begin
AD_SCK <= 1;
AD_SI <= data[10];
end
8'd12: begin
AD_SCK <= 0;
end
8'd13: begin
AD_SCK <= 1;
AD_SI <= data[9];
end
8'd14: begin
AD_SCK <= 0;
end
8'd15: begin
AD_SCK <= 1;
AD_SI <= data[8];
end
8'd16: begin
AD_SCK <= 0;
end
8'd17: begin
AD_SCK <= 1;
AD_SI <= data[7];
end
8'd18: begin
AD_SCK <= 0;
end
8'd19: begin
AD_SCK <= 1;
AD_SI <= data[6];
end
8'd20: begin
AD_SCK <= 0;
end
8'd21: begin
AD_SCK <= 1;
AD_SI <= data[5];
end
8'd22: begin
AD_SCK <= 0;
end
8'd23: begin
AD_SCK <= 1;
AD_SI <= data[4];
end
8'd24: begin
AD_SCK <= 0;
end
8'd25: begin
AD_SCK <= 1;
AD_SI <= data[3];
end
8'd26: begin
AD_SCK <= 0;
end
8'd27: begin
AD_SCK <= 1;
AD_SI <= data[2];
end
8'd28: begin
AD_SCK <= 0;
end
8'd29: begin
AD_SCK <= 1;
AD_SI <= data[1];
end
8'd30: begin
AD_SCK <= 0;
end
8'd31: begin
AD_SCK <= 1;
AD_SI <= data[0]; // SI取数据最低位
end
8'd32: begin
AD_SCK <= 0; // 写入最后一位数据
end
// the end
8'd33: begin
AD_SCK <= 1;
AD_FSYNC <= 1;
AD_SI <= 0;
end
default: begin
AD_SCK <= 1;
AD_FSYNC <= 1;
AD_SI <= 0;
end
endcase
end
else begin
AD_SCK <= 1;
AD_FSYNC <= 1;
AD_SI <= 0;
end
end
end
endmodule
当检测到操作写入信号TxData_en
被置位时,将模块内寄存器tx_en
置位,用于保存置位信号,因为TxData_en
将在一个时钟周期后被拉低。
当置位信号保存完成后,将开始写入操作,counter
作为写入的寄存器用于寄存当前写入的位置。当counter
为0时,将需要写入的数据保存到data
中,并将FSYNC
拉低,表示我们将要开始写入操作。注意:在FSYNC
拉低时,我们需要确保SCK
为高电平,否则FSYNC
的拉低无效。
FSYNC
拉低后,我们在SCK
为高电平时,变更SI
为需要写入数据的位次,保持一个时钟周期20ns后,将SCK
拉低,AD9833在SCK
为下降沿时将SI
的数据读入。以此往复直至写入完成的操作字。
在写入完成后,我们需要在10ns-20ns
的时间内将FSYNC
拉高,否则写入无效。并将TxData_done
置位,表示写入完成了,可以进行后续操作。
2.4 驱动操作模块
驱动模块,主要对写入的操作字进行变更,通过选择合适的波形和频率控制AD9833输出。
module AD_Driver(
input clk,
input rst_n,
input key0_value,
input key0_flag,
input key1_value,
input key1_flag,
output [ 7:0] counter_rem_driver,
input TxData_done, // 写入完成标志位 输入
output reg [15:0] TxData, // 写入操作数 输出
output reg TxData_en // 开始写入标志位 输出
);
// local parameter define
localparam [15:0] reset_add = 16'h0100;
localparam [15:0] write_freq = 16'h2100;
// 为了避免在AD9833被初始化时出现虚假的DAC输出
// 复位位应该被设置为1 直到部件准备好开始生成输出为止
// fMck=25Mhz
// (fMclk/2^28/fwanted)^(-1)=FREQREG; fwanted(min)=0.0931, fwanted(max)=25M
localparam [15:0] write_freq_lsb_3M = 16'h70b7; // 输出3M信号
localparam [15:0] write_freq_msb_3M = 16'h47ae;
localparam [15:0] write_freq_lsb_1M = 16'h6592; // 输出1M信号
localparam [15:0] write_freq_msb_1M = 16'h428f;
localparam [15:0] write_freq_lsb_1k = 16'h69f1; // 输出1k信号
localparam [15:0] write_freq_msb_1k = 16'h4000;
localparam [15:0] write_phase_c0 = 16'hc000; // 相位配置
localparam [15:0] write_sin = 16'h2000; // 正弦波
localparam [15:0] write_traingle = 16'h2002; // 三角波
localparam [15:0] write_square = 16'h2028; // 方波
// reg define
reg [ 7:0] counter; // 写入操作开始后的位置
reg [31:0] delay_counter; // 开始写入操作前的延迟
reg delay_start; // 延迟开始标志位
reg delay_end; // 延迟结束标志位
reg [ 2:0] waveform_select; // 选择波形
reg [ 2:0] freq_select; // 选择频率
reg [15:0] write_waveform; // 写入的波形类型
reg [15:0] write_freq_lsb_c0; // 写入频率数据的低位
reg [15:0] write_freq_msb_c0; // 写入频率数据的高位
// wire define
//***************************************************
//**** main code ****
//***************************************************
assign counter_rem_driver = counter;
// 开始延迟计数器
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
delay_counter <= 32'b0;
delay_start <= 1'b1;
delay_end <= 1'b0;
waveform_select <= 2'd0;
freq_select <= 2'd0;
end
else begin
// 初始化和波形频率选择后根据delay_start开启延迟
if(delay_start) begin
if(delay_counter < 10'd1000) begin
delay_counter = delay_counter + 1'b1;
end
else begin
delay_counter <= 32'b0;
delay_start <= 1'b0;
// 将delay_end作为延迟结束的标志 置1只存在一个周期
delay_end <= 1'b1;
end
end
// 根据按键调整波形和频率
else begin
// key0按下调整输出波形
if((key0_flag == 1) && (key0_value == 0)) begin
waveform_select <= waveform_select + 1'd1;
delay_start <= 1'b1;
delay_counter <= 32'b0;
delay_end <= 1'b0;
end
// key1按下调整输出频率
else if((key1_flag == 1) && (key1_value == 0)) begin
freq_select <= freq_select + 1'd1;
delay_start <= 1'b1;
delay_counter <= 32'b0;
delay_end <= 1'b0;
end
else begin
// default波形和频率不变化
waveform_select <= waveform_select;
freq_select <= freq_select;
delay_counter <= 32'b0;
delay_end <= 1'b0;
end
end
end
end
// 切换波形种类
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
write_waveform <= write_sin;
end
else begin
case(waveform_select)
2'd0: begin
write_waveform <= write_sin;
end
2'd1: begin
write_waveform <= write_traingle;
end
2'd2: begin
write_waveform <= write_square;
end
default: begin
write_waveform <= write_sin;
end
endcase
end
end
// 切换频率
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
write_freq_lsb_c0 <= write_freq_lsb_1M;
write_freq_msb_c0 <= write_freq_msb_1M;
end
else begin
case(freq_select)
2'd0: begin
write_freq_lsb_c0 <= write_freq_lsb_1M;
write_freq_msb_c0 <= write_freq_msb_1M;
end
2'd1: begin
write_freq_lsb_c0 <= write_freq_lsb_3M;
write_freq_msb_c0 <= write_freq_msb_3M;
end
2'd2: begin
write_freq_lsb_c0 <= write_freq_lsb_1k;
write_freq_msb_c0 <= write_freq_msb_1k;
end
default: begin
write_freq_lsb_c0 <= write_freq_lsb_1M;
write_freq_msb_c0 <= write_freq_msb_1M;
end
endcase
end
end
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
TxData <= 16'd0;
TxData_en <= 1'b0;
counter <= 8'd12;
end
else begin
// delay_end被置位后 将counter的值归零 开始写入操作数
// 否则写入操作会在结束处不断循环
if(delay_end) begin
counter <= 8'd0;
end
else begin
case(counter)
// 重置寄存器
8'd0: begin
TxData <= reset_add;
TxData_en <= 1'b1;
counter <= counter + 1'b1;
end
8'd1: begin
TxData <= TxData;
TxData_en <= 1'b0;
counter <= counter;
if(TxData_done) begin
counter <= counter + 1'b1;
end
end
// 选择数据一次写入
8'd2: begin
TxData <= write_freq;
TxData_en <= 1'b1;
counter <= counter + 1'b1;
end
8'd3: begin
TxData <= TxData;
TxData_en <= 1'b0;
counter <= counter;
if(TxData_done) begin
counter <= counter + 1'b1;
end
end
// 写入频率寄存器低14位
8'd4: begin
TxData <= write_freq_lsb_c0;
TxData_en <= 1'b1;
counter <= counter + 1'b1;
end
8'd5: begin
TxData <= TxData;
TxData_en <= 1'b0;
counter <= counter;
if(TxData_done) begin
counter <= counter + 1'b1;
end
end
// 写入频率寄存器高14位
8'd6: begin
TxData <= write_freq_msb_c0;
TxData_en <= 1'b1;
counter <= counter + 1'b1;
end
8'd7: begin
TxData <= TxData;
TxData_en <= 1'b0;
counter <= counter;
if(TxData_done) begin
counter <= counter + 1'b1;
end
end
// 写入相位寄存器12位
// 不确定相位寄存器是否同时写入 在图例中相位寄存器无任何写入的使能标志位
8'd8: begin
TxData <= write_phase_c0;
TxData_en <= 1'b1;
counter <= counter + 1'b1;
end
8'd9: begin
TxData <= TxData;
TxData_en <= 1'b0;
counter <= counter;
if(TxData_done) begin
counter <= counter + 1'b1;
end
end
// 选择波形输出器
8'd10: begin
TxData <= write_waveform;
TxData_en <= 1'b1;
counter <= counter + 1'b1;
end
8'd11: begin
TxData <= TxData;
TxData_en <= 1'b0;
counter <= counter;
if(TxData_done) begin
counter <= counter + 1'b1;
end
end
// 结束 将使能位TxData_en拉低
8'd12: begin
TxData <= 16'd0;
TxData_en <= 1'b0;
counter <= counter;
end
default: begin
counter <= counter;
end
endcase
end
end
end
endmodule
FPGA重置后,delay_start
置位,经过一定的延时后,开始初始化写入1Mhz的正弦波信号。写入的过程如下:
- 重置寄存器
- 选择数据一次写入
- 写入频率寄存器低14位
- 写入频率寄存器高14位
- 写入相位寄存器12位
- 选择波形输出
- 循环等待按键按下重置上述流程
当检测到按键按下时,即key_flag
和key_value
变化时,波形选择寄存器和频率选择寄存器会发生变化。以此来选择正弦波、三角波、方波和1M、3M和1K的频率信号。
三、结果展示
FPGA引脚输出。
图5是FPGA的引脚输出状态。可以看到FSYNC
为低电平时开始写入操作,TxData
为写入操作字,SI
逐一读取写入位,跟随着SCK
的变化写入。
3M的正弦波。
可以观察到周期是333ns,也就是3M,输出频率很精准。另外是436mV的峰峰值(经过外部运放放大后的,放大倍数为6.1倍),不超过手册中的650mV。
1K的正弦波。
其余波形和频率,博主忘记拍了=.=
,但确实完整输出了三角波和方波(只要按一下按键就行)。就不重新连了,有点懒。
最后的最后,展示一下AD9833在原理图中的连接图。
总结
本文,首先分析了AD9833的芯片手册,根据其芯片手册的内容,我们用Verilog语言编写了控制程序,并烧录至FPGA中用于控制AD9833。最后得到不同波形和频率的输出结果。