2.45 AD9833 DDS 模块(来自笔上山海的贡献)
2.45.1 模块来源
采购链接: AD9833 模块 DDS 模块 提供测试程序 正弦波/方波/三角波信号发生器 资料下载: https://pan.baidu.com/s/1JZ0ga4uTyXUq5u-Or9BVlg?pwd=GOOD 提取码:GOOD
**图 2.45.1-1 产品实物展示**2.45.2 规格参数
工作电压:2.3 V 至 5.5 V 电源供电工作电流:12.65 mW(3 V 时)通信方式:3 线**SPI**接口芯片引脚数量:10 引脚 MSOP 封装相关资料手册
2.45.3 移植过程
我们的目标是在梁山派 GD32F470 上能够通过模块输出波形的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
2.45.3.1 查看资料
模块作用:
可编程波形发生器,能够产生正弦 波、三角波和方波输出。各种类型的检测、信号激励和时 域反射(TDR)应用都需要波形发生器。输出频率和相位可 通过软件进行编程,调整简单。无需外部元件。频率寄存 器为 28 位:时钟速率为 25 MHz 时,可以实现 0.1 Hz 的分辨 率;而时钟速率为 1 MHz 时,则可以实现 0.004 Hz 的分辨率。
模块驱动:
AD9833 通过一个三线式串行接口写入数据。该串行接口能 够以最高 40 MHz 的时钟速率工作,并且与 DSP 和微控制器 标准兼容。该器件采用 2.3 V 至 5.5 V 电源供电。注意:在生成方波时会过冲(可以在加入电源滤波电路缓解但不能彻底解决!!!)
2.45.3.2 引脚选择
######### AD9833 | ######### 立创·梁山派 | ######### 接线图 |
---|
2.45.3.3 移植至工程
移植步骤中的导入.c 和.h 文件与上一节相同,只是将.c 和.h 文件更改为 AD9833.c 与 ccd.h。见 2.2.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
在文件 AD9833.c 中,编写如下代码。
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LCKFB
* 修改日期: 2023年06月12日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#include "AD9833.h"
#include "gd32f4xx.h"
/******************************************************************
* 函 数 名 称:Ad9833GpioConfig
* 函 数 说 明:Ad9833的初始化
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:软件SPI的配置
******************************************************************/
void AD9833_GpioConfig(void)
{
rcu_periph_clock_enable(RCU_SDATA); //使能SDATA引脚时钟
rcu_periph_clock_enable(RCU_SCLK); //使能SCLK引脚时钟
rcu_periph_clock_enable(RCU_FSNYC); //使能FSNYC引脚时钟
//配置SDATA为上拉推挽输出
gpio_mode_set(PORT_SDATA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_SDATA);
gpio_output_options_set(PORT_SDATA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_SDATA);
//输出高电平
gpio_bit_set(PORT_SDATA, GPIO_SDATA);
//配置SCLK为上拉推挽输出
gpio_mode_set(PORT_SCLK, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_SCLK);
gpio_output_options_set(PORT_SCLK, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_SCLK);
//输出高电平
gpio_bit_set(PORT_SCLK, GPIO_SCLK);
//配置FSNYC为上拉推挽输出
gpio_mode_set(PORT_FSNYC, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_FSNYC);
gpio_output_options_set(PORT_FSNYC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_FSNYC);
//输出高电平
gpio_bit_set(PORT_FSNYC, GPIO_FSNYC);
}
/******************************************************************
* 函 数 名 称:AD9833_WriteData
* 函 数 说 明:向AD9833写入16位数据
* 函 数 形 参:txdata=写入的16位数据
* 函 数 返 回:无
* 作 者:LC
* 备 注:FSNYC低电平有效,数据在时钟的下降沿被采集数据,在时钟的上升沿更新数据
******************************************************************/
void AD9833_WriteData(uint16_t txdata)
{
int i;
ADI_FSNYC_OUT(1);
ADI_SCLK_OUT(0);
ADI_SCLK_OUT(1);
ADI_FSNYC_OUT(0);
//写16位数据
for(i=0;i<16;i++)
{
if (txdata & 0x8000)
{
ADI_SDATA_OUT(1);
}
else
{
ADI_SDATA_OUT(0);
}
ADI_SCLK_OUT(0);
txdata<<=1;
ADI_SCLK_OUT(1);
}
ADI_FSNYC_OUT(1);
}
/******************************************************************
* 函 数 名 称:AD9833_SetFrequency
* 函 数 说 明:ad9833设置频率寄存器
* 函 数 形 参:reg=待写入的频率寄存器 fout=频率值
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void AD9833_SetFrequency(unsigned short reg, double fout)
{
int frequence_LSB=0, frequence_MSB=0;
double frequence_mid=0, frequence_DATA=0;
long int frequence_hex=0;
/*********************************计算频率的16进制值***********************************/
//如果时钟频率不为25MHZ,修改该处的频率值,单位MHz ,AD9833最大支持25MHz
frequence_mid = 268435456/25;//适合25M晶振
frequence_DATA = fout;
frequence_DATA = frequence_DATA/1000000;
frequence_DATA = frequence_DATA*frequence_mid;
frequence_hex = frequence_DATA; //这个frequence_hex的值是32位的一个很大的数字,需要拆分成两个14位进行处理;
frequence_LSB = frequence_hex; //frequence_hex低16位送给frequence_LSB
frequence_LSB = frequence_LSB&0x3fff; //去除最高两位,16位数换去掉高位后变成了14位
frequence_MSB = frequence_hex>>14; //frequence_hex高16位送给frequence_HSB
frequence_MSB = frequence_MSB&0x3fff; //去除最高两位,16位数换去掉高位后变成了14位
frequence_LSB = frequence_LSB|reg;
frequence_MSB = frequence_MSB|reg;
AD9833_WriteData(0x2100); //选择数据一次写入,B28位和RESET位为1
AD9833_WriteData(frequence_LSB);
AD9833_WriteData(frequence_MSB);
}
/******************************************************************
* 函 数 名 称:AD9833_SetPhase
* 函 数 说 明:ad9833设置相位寄存器
* 函 数 形 参:reg=待写入的相位寄存器 fout=相位值
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void AD9833_SetPhase(unsigned short reg, unsigned short val)
{
unsigned short phase = reg;
phase |= val;
AD9833_WriteData(phase);
}
/******************************************************************
* 函 数 名 称:AD9833_SetWave
* 函 数 说 明:ad9833设置波形
* 函 数 形 参:WaveMode=输出波形类型
* Freq_SFR=输出的频率寄存器类型
* Phase_SFR=输出的相位寄存器类型
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void AD9833_SetWave(unsigned int WaveMode,unsigned int Freq_SFR,unsigned int Phase_SFR)
{
unsigned int val = 0;
val = (val | WaveMode | Freq_SFR | Phase_SFR);
AD9833_WriteData(val);
}
/******************************************************************
* 函 数 名 称:AD9833_Setup
* 函 数 说 明:设置ad9833的输出
* 函 数 形 参:Freq_SFR = 频率寄存器类型
* Freq = 频率值
* Phase_SFR= 相位寄存器类型
* Phase = 相位值
* WaveMode = 波形类型
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void AD9833_Setup(unsigned int Freq_SFR,double Freq,unsigned int Phase_SFR,unsigned int Phase,unsigned int WaveMode)
{
unsigned int Fsel,Psel;
AD9833_WriteData(0x0100); //复位AD9833,即RESET位为1
AD9833_WriteData(0x2100); //选择数据一次写入,B28位和RESET位为1
AD9833_SetFrequency(Freq_SFR,Freq);
AD9833_SetPhase(Phase_SFR,Phase);
if(Freq_SFR == AD9833_REG_FREQ0)
{
Fsel = AD9833_FSEL0;
}
else
{
Fsel = AD9833_FSEL1;
}
if(Phase_SFR == AD9833_REG_PHASE0)
{
Psel = AD9833_PSEL0;
}
else
{
Psel = AD9833_PSEL1;
}
AD9833_SetWave(WaveMode,Fsel,Psel);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
在文件 AD9833.h 中,编写如下代码。
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LCKFB
* 修改日期: 2023年06月12日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#ifndef _AD9833_H__
#define _AD9833_H__
#include "GD32F4XX.h"
//引脚定义
#define RCU_SDATA RCU_GPIOD
#define PORT_SDATA GPIOD
#define GPIO_SDATA GPIO_PIN_5
#define RCU_SCLK RCU_GPIOD
#define PORT_SCLK GPIOD
#define GPIO_SCLK GPIO_PIN_4
#define RCU_FSNYC RCU_GPIOD
#define PORT_FSNYC GPIOD
#define GPIO_FSNYC GPIO_PIN_1
//端口输出
#define ADI_SDATA_OUT(X) gpio_bit_write(PORT_SDATA, GPIO_SDATA, (X)?SET:RESET)
#define ADI_SCLK_OUT(X) gpio_bit_write(PORT_SCLK, GPIO_SCLK, (X)?SET:RESET)
#define ADI_FSNYC_OUT(X) gpio_bit_write(PORT_FSNYC, GPIO_FSNYC, (X)?SET:RESET)
//输出波形
#define AD9833_OUT_SINUS ((0 << 5) | (0 << 1) | (0 << 3)) //正弦波
#define AD9833_OUT_TRIANGLE ((0 << 5) | (1 << 1) | (0 << 3)) //三角波
#define AD9833_OUT_MSB ((1 << 5) | (0 << 1) | (1 << 3)) //方波
#define AD9833_OUT_MSB2 ((1 << 5) | (0 << 1) | (0 << 3)) //方波
//相关寄存器
#define AD9833_REG_CMD (0 << 14)
#define AD9833_REG_FREQ0 (1 << 14)
#define AD9833_REG_FREQ1 (2 << 14)
#define AD9833_REG_PHASE0 (6 << 13)
#define AD9833_REG_PHASE1 (7 << 13)
//命令控制位
#define AD9833_B28 (1 << 13)
#define AD9833_HLB (1 << 12)
#define AD9833_FSEL0 (0 << 11)
#define AD9833_FSEL1 (1 << 11)
#define AD9833_PSEL0 (0 << 10)
#define AD9833_PSEL1 (1 << 10)
#define AD9833_PIN_SW (1 << 9)
#define AD9833_RESET (1 << 8)
#define AD9833_CLEAR_RESET (0 << 8)
#define AD9833_SLEEP1 (1 << 7)
#define AD9833_SLEEP12 (1 << 6)
#define AD9833_OPBITEN (1 << 5)
#define AD9833_SIGN_PIB (1 << 4)
#define AD9833_DIV2 (1 << 3)
#define AD9833_MODE (1 << 1)
//函数声明
void AD9833_GpioConfig(void);
void AD9833_WriteData(uint16_t txdata);
void AD9833_SetFrequency(unsigned short reg, double fout);
void AD9833_SetPhase(unsigned short reg, unsigned short val);
void AD9833_SetWave(unsigned int WaveMode,unsigned int Freq_SFR,unsigned int Phase_SFR);
void AD9833_Setup(unsigned int Freq_SFR,double Freq,unsigned int Phase_SFR,unsigned int Phase,unsigned int WaveMode);
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
2.45.4 移植验证
在自己工程中的 main 主函数中,编写如下。
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LCKFB
* 修改日期: 2023年06月12日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "sys.h"
#include "bsp_usart.h"
#include "AD9833.h"
int main(void)
{
systick_config();
usart_gpio_config(115200U);
AD9833_GpioConfig();
while(1)
{
//输出 2K 三角波
AD9833_Setup(AD9833_REG_FREQ0,2000.0,AD9833_REG_PHASE1,1024,AD9833_OUT_TRIANGLE);
delay_1ms(2000);
delay_1ms(2000);
delay_1ms(2000);
delay_1ms(2000);
//输出 50K 正弦波
AD9833_Setup(AD9833_REG_FREQ0,50000.0,AD9833_REG_PHASE1,1024,AD9833_OUT_SINUS);
delay_1ms(2000);
delay_1ms(2000);
delay_1ms(2000);
delay_1ms(2000);
//输出 1M 方波
AD9833_Setup(AD9833_REG_FREQ0,1000000.0,AD9833_REG_PHASE1,1024,AD9833_OUT_MSB);
delay_1ms(2000);
delay_1ms(2000);
delay_1ms(2000);
delay_1ms(2000);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
移植现象:该实例是产生一个 2KHZ 的三角波,8 秒后产生 50K 正弦波,8 秒后再产生 1M 方波,将探头连接到示波器上观察!!注意:生成方波有过冲是正常现象。
移植成功示例,见文件 2.45.4-1。
文件 2.45.4-1 移植成功示例