【STM32+cubemx】0030 HAL库开发:DDS芯片AD9833实现简单的波形发生器

article/2025/10/19 1:07:14

大家好,我是学电子的小白白,今天带大家了解一款波形发生器芯片——AD9833。

AD9833是AD公司出品的一款DDS波形发生器,能够产生正弦波、三角波和方波输出。

1)什么是DDS

通俗来讲,DDS是一种把波形预先存储在芯片内部的DAC,只要设置好它的工作频率,就能按这个频率来输出特定的波形。

DDS内部主要分成3部分:相位累加器、相位幅度转换、数模转换器(即DAC)。

相位累加器:

一个周期信号的波形,它的相位是均匀增加的,比如1Hz的正弦波,每1/360秒相位增加1°,增加到360°时又回到0°。相位累加器就是一个不断累加产生相位值的计数器,周期性地累加、清零。

相位累加器的位数决定了把一个周期分为多少等分,位数越高,则分得越细,一个周期内的点数也越多,输出波形在时间尺度上就会越精细。

相位幅度转换

相位幅度转换其实就是已经存储的波形表,比如我们想输出正弦波的波形时,相位累加器输出的相位是30°,则通过查表,输出sin(30°)的值,就完成了相位幅度转换。

DAC输出

有了幅度值,再通过DAC输出,就得到了当前时刻的波形值。这个就不多解释了,和通用的DAC一个意思。这里的DAC也是有位数的,位数越高,产生的波形幅度就越精细。

2)DDS芯片AD9833的特性

AD9833是AD公司出品的一款DDS波形发生器,它的主要参数如下:

能产生正弦波、三角波和方波的输出;

28位的相位累加器,也就是主频时钟为25MHz时,可实现0.1Hz的分辨率;主频时钟为1MHz时,可实现0.004Hz的分辨率;

10位的DAC输出;输出正弦波和三角波时波形幅度为38mV~650mV,输出方波时幅度最大为3.3V。

采用SPI接口,只作为SPI的从机。

这里需要说明一下,AD9833的输出波形频率,最高可达12.5MHz。这个12.5MHz是怎么来的呢?

因为AD9833的输入时钟频率最高是25MHz,由于奈奎斯特采样定律的限制,输出波形的每个周期内至少要2个点才能还原出信号,所以,25MHz/2 = 12.5MHz是这么来的。

但是,这里要特别注意一下,奈奎斯特采样定理使用的条件,它描述的是波形中所含正弦波的最高频率

因此,如果我们想让它输出12.5MHz的正弦波是可行的,一个周期内两个点的波形,再加上后端的低通滤波器就能实现;输出方波也是可行的,因为方波只有高、低电平的变化;而想要输出三角波,就不可能了,一个周期中只输出两个点,怎么都不可能形成三角波的图形,要想输出三角波,只能降低频率,让一个周期内的点数增加,才能输出类似三角波的波形。

3)使用stm32驱动AD9833输出

AD公司官方给出了一套驱动AD9833的代码,但是它的代码结构比较复杂,而且它为了兼容同系列的其他DDS芯片里面有很多冗余的部分,我们不使用官方的代码,有兴趣可以关注我的公众号找到下载地址自行研究。

这里我们自己来实现AD9833的驱动代码,使用的硬件平台是stm32单片机。

AD9833连接到SPI2接口上,使用PA8作为片选信号。

首先看AD9833的SPI接口时序:

它只有MOSI数据,所以数据只有主机到从机的,而且要注意是在时钟下降沿取数的,每次传输16bit。

在cubemx里建立工程,主要的参数设置下面几项:

使能SPI2,设置为全双工主机(半双工主机也可以);时钟初始为高、第一个跳变沿取数;

PA8设置为输出,作为AD9833的片选信号;

然后生成工程,在keil中打开后就可以编写代码了。

AD9833的寄存器比较简单,一共就三个:控制寄存器、频率寄存器、相位寄存器。

其中,控制寄存器用于设置波形、是否输出、是否低功耗等等一些控制量。频率、相位寄存器都有两个,由控制寄存器中的FSELEC、PSELECT位来选择使用哪一个。

这里我们尝试把常用的几个功能封装的函数中,其他一些细节功能的可以参见AD9833的数据手册。

首先是定义片选的拉高、拉低函数:

接着是初始化函数,由于cubemx生成的代码已经把spi接口初始化好了,所以这里我们只需要把片选线拉高就可以了:

AD9833的读写函数,我们使用HAL库的spi函数实现,由于AD9833每次传输16bit,先传高位,所以我们每次传输2字节就可以了,先传高字节;当然在传输前后,加上片选的拉低、拉高:

设置AD9833控制寄存器的函数,这里只实现了常用的几个位:RESET、SLEEP、OPBITEN、MODE这几个bit的设置:

如果想实现其他bit位的改写,也很容易。

最后是设置频率的函数:

注意这个函数设置完频率之后, AD9833_Write(0x2100);这句把输出关闭了。

在主函数中写一个测试程序:

主要功能是在初始化之后,主循环之前,设置1MHz正弦波,延时10s输出:

将代码下载到单片机运行,可以检测到上电10s后,AD9833的10脚out上输出1MHz正弦波。

如果想要输出三角波、矩形波,只要更改AD9833_CtrlSet函数的输入值即可。

使用模块来搭电路时,要注意避坑,我选用的模块是下面这种:

原理图如下:

在AD9833的输出增加了一个数字电位器MCP41010和运放AD8051进行输出波形幅度的调节。

但是,这个模块的设计是有问题的,主要在于MCP41010数字电位器的带宽不够!会造成输出频率较高时,波形幅度大幅减小,完全起不到调节波形幅度的作用。

如下图是MCP41010的增益随频率的变化曲线,可以看到,频率到1MHz以上时,衰减会变得很明显,频率越高衰减越大:

所以在频率比较高的时候,这种模块是不适用的。

好了,本节关于DDS波形发生器AD9833的使用就讲到这里了。

如果觉得有用,可以关注我的微 信 公众号“小白白学电子”,可以找到所有源码和参考资料:


http://chatgpt.dhexx.cn/article/pi49wyuH.shtml

相关文章

2.电赛进行时......(AD9833(DDS)模块的学习使用)

文章目录 前言一、DDS是什么(信号发生器)?二、AD9833模块介绍1.概述2.模块移植3、效果展示![在这里插入图片描述](https://img-blog.csdnimg.cn/2b0d29939275403f9248339c894965a0.png#pic_center) 前言 如果是玫瑰,它总会开花的…

AD9833介绍与应用(C语言实现)

1.特性 低功耗、可编程波形发生器,能产生正弦波、三角波和方波的输出; 主频时钟为25MHz时,可实现0.1Hz的分辨率;主频时钟为1MHz时,可实现0.004Hz的分辨率; 三线式串行接口(SDATA、SCLK、FSYNC)写入数据&a…

2021电赛预测—手把手带你玩转DDS模块AD9833

1、电赛预测 摘要:原定于7月28日才发布的器件清单,提前2天在26号就发布。感觉大家现在应该猜题预测,与其猜题,还不如静下心来做题。盲目猜题是没有必要的,熟悉相关器件倒尤为重要。不要到处去水群聊天,听风…

幻方....

c语言上机。。。。 c写的幻方。 1 /*************************************************************************2 > File Name: code/class/7.c3 > Author: 111qqz4 > Email: rkz2013126.com 5 > Created Time: 2015年11月11日 星期三 19时31分5…

Unity脚本生命周期流程图

转载自【无幻】:http://blog.csdn.net/akof1314/article/details/39323081 渲染 OnPreCull: 在相机剔除场景之前调用此函数。相机可见的对象取决于剔除。OnPreCull 函数调用发生在剔除之前。 OnBecameVisible/OnBecameInvisible: 在对象对于相机可见/不可见时调用此…

SonicUI在MFC中的使用

SonicUI是一个GUI引擎,提供了一些简单的UI组件实现高效率的UI效果,例如:自绘按钮、异形窗体、动画、超链接和图像操作方法。此项目作者开源到CodeProject,地址为:http://www.codeproject.com/KB/GDI/SonicUI.aspx。下载…

将ribbon主题应用到对话框中去(转载)

原帖地址:这里 找了N久,终于在无幻大神这里找到了将ribbon sdi主题应用到对话框程序中的方法,好像这是一个开源的项目,google code里有,地址在 这里。记录下: 1、下载网页里的资源KofPack0.1,vs里打开工程…

如何制作一个横版格斗过关游戏 Cocos2d-x 2.0.4

本文原创版权归 csdn 无幻 所有,转载请详细标明原创作者及出处,以示尊重! 作者:无幻 原文:http://blog.csdn.net/akof1314/article/details/8549150 本文实践自 Allen Tan 的文章《How To Make A Side-Scrolling Bea…

VC复制HTML格式到剪贴板 HTML Clipboard Format

本文作者:无幻 测试环境:Windows 7 开发环境:Visual Studio 2008 SP1 参照MSDN和帮助,在VC下测试代码如下: C语言: BOOL CBaseDialogDlg::CopyHtmlToClip( const CString &strHtml ) { // 1)转换成UTF-8 CW2A p…

如何制作一个横版格斗过关游戏(2) Cocos2d-x 2.0.4 .

本文原创版权归 csdn 无幻 所有,转载请详细标明原创作者及出处,以示尊重! 作者:无幻 原文:http://blog.csdn.net/akof1314/article/details/8572546 在第一篇《如何制作一个横版格斗过关游戏》基础上,增加…

Cocos2d-x 2.0.1 学习tests示例(二)ActionsTest

作者:无幻 博客: http://blog.csdn.net/akof1314 初学Cocos2d-x,如文章有错误之处,欢迎指出 自上篇《 Cocos2d-x 2.0.1 学习tests示例(一)Manual Transformation》继续学习tests示例。 1 2 3 4 5 6 7 8 9…

改变CMFCRibbonBar高度

本文作者:无幻 测试环境:Windows XP 开发环境:Visual Studio 2010 要改变CMFCRibbonBar的高度,需要重载CalcFixedLayout函数,例如如下: 头文件: #pragma once// // CKofMFCRibbonQuickAccessTo…

Cocos2d-x 2.0.1 学习tests示例(一)Manual Transformation

作者:无幻 博客: http://blog.csdn.net/akof1314 初学Cocos2d-x,如文章有错误之处,欢迎指出 从上次《Cocos2d-x 2.0 从HelloWorld入手》,继续学习tests示例。 1.右键点击“Solution ‘cocos2d-win32.vc2008’"&…

Unity3d好东西应该被看见_分享一个Assetbundle分析工具

关于Assetbundle分析 很多年前获得过搜狐畅玩的代码 不确定是不是腾讯流出版本,反正经历了深圳畅玩,到北京畅玩。 整个中国地图,从南到北,成熟的Unity手游团队,手上几乎都是那一份ASSETBUNDLE处理代码 功能太多&am…

Visual C++ 2008 Feature Pack 示例截图

Visual C 2008 Feature Pack 示例截图 by 无幻 百度文库:http://wenku.baidu.com/view/f09e5575a417866fb84a8eb6.html 豆丁文档:http://www.docin.com/p-55873972.html CSDN下载:http://download.csdn.net/source/2380293 动态图片显示…

CRichEditCtrlEx支持静态表情聊天类的使用

本文作者:无幻 博客地址:http://blog.csdn.net/akof1314 平时我们在做IM聊天之类的软件的时候,一般都会使用Rich Edit控件来作为聊天编辑框和聊天记录框的控件,在之前的VC知识库看过《类似 MSN 信息发送框的制作(上)》、《类似 MS…

方舟服务器文件夹,方舟生存进化文件夹里哪个才是打开游戏 | 手游网游页游攻略大全...

发布时间:2016-04-07 有许多玩家反映在方舟生存进化当中自己在洞穴里只能挖到石头,挖不到水晶,这是怎么回事呢?接下来小编就为大家带来方舟生存进化在洞穴里怎么才能采集到水晶的详细攻略. 答:用铁镐挖才能采集到水晶,用石镐就只能采到石头,希望能帮到 ... 标签&am…

【VC学习】VC2010 Windows Media Player控件的使用技巧

声明:以下博客基于无幻 VC2008 Windows Media Player控件的使用技巧,自行学习整理 附上原地址:http://blog.csdn.net/akof1314/article/details/4900040 本是跟着老师选修课学习,编程都是基于MFC,手动在toolbox里面修…

真Unity3d_分享一个编辑器扩展模型预览视图Mesh Preview Inspector窗口

预览窗口 在 Unity 编辑器界面上可以看到除了 Game 视图、Scene 视图,其他的视图也会出现绘制三维物体的地方,比如检视器的预览窗口,当选中网格时,会对网格进行预览,如下所示: 预览窗口是UnityEditor的底层框架 UnityEditor框架图 可看我之前的博客: https://blog.c…

lookup

这里注意数组 1.{ sum((E3:E11)*(F3*F11) )} 代表数组运算ctrlentershift,因为(E3:E11)*(F3*F11)返回的是数组 2. sum(E3:E11)其中E3:E11也是数组但是直接enter就可以‘ 为什么:因为(E3:E11)是本来就存在的列,(E3:E11)*(F3*F11)是运算出来…