2.45 AD9833 DDS模块
2.45.1 模块来源
采购链接:
AD9833模块 DDS模块 提供测试程序 正弦波/方波/三角波信号发生器
资料下载:
https://pan.baidu.com/s/1JZ0ga4uTyXUq5u-Or9BVlg?pwd=GOOD
提取码:GOOD
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 引脚选择
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日* 功能介绍: ***************************************************************************************************************************************************************/#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最大支持25MHzfrequence_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_LSBfrequence_LSB = frequence_LSB&0x3fff; //去除最高两位,16位数换去掉高位后变成了14位frequence_MSB = frequence_hex>>14; //frequence_hex高16位送给frequence_HSBfrequence_MSB = frequence_MSB&0x3fff; //去除最高两位,16位数换去掉高位后变成了14位frequence_LSB = frequence_LSB|reg;frequence_MSB = frequence_MSB|reg;AD9833_WriteData(0x2100); //选择数据一次写入,B28位和RESET位为1AD9833_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位为1AD9833_WriteData(0x2100); //选择数据一次写入,B28位和RESET位为1AD9833_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);
}
在文件AD9833.h中,编写如下代码。
/********************************************************************************* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz* 版 本 号: V1.0* 修改作者: LCKFB* 修改日期: 2023年06月12日* 功能介绍: ***************************************************************************************************************************************************************/
#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.45.4 移植验证
在自己工程中的main主函数中,编写如下。
/********************************************************************************* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz* 版 本 号: V1.0* 修改作者: LCKFB* 修改日期: 2023年06月12日* 功能介绍: ***************************************************************************************************************************************************************/
#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); }
}
移植现象:该实例是产生一个2KHZ的三角波,8秒后产生50K正弦波,8秒后再产生1M方波,将探头连接到示波器上观察!!注意:生成方波有过冲是正常现象。
移植成功示例,见文件2.45.4-1。