STM32
直播中

王健

8年用户 1021经验值
私信 关注
[问答]

怎么实现基于STM32的DAC实现音频波形的输出?

怎么实现基于STM32的DAC实现音频波形的输出?

回帖(1)

王坤

2021-11-19 09:39:57
一、DAC相关

1. DAC简介

DAC数模转换器,又称D/A转换器,,它是把数字量转变成模拟的器件。D/A转换器基本上由4个部分组成,即权电阻网络、运算放大器、基准电源和模拟开关。模数转换器中一般都要用到数模转换器,模数转换器即A/D转换器,简称ADC,它是把连续的模拟信号转变为离散的数字信号的器件。
2. DAC的构成与特点

DAC主要由数字寄存器、模拟电子开关、位权网络、求和运算放大器和基准电压源(或恒流源)组成。用存于数字寄存器的数字量的各位数码,分别控制对应位的模拟电子开关,使数码为1的位在位权网络上产生与其位权成正比的电流值,再由运算放大器对各电流值求和,并转换成电压值 。
根据位权网络的不同,可以构成不同类型的DAC,如权电阻网络DAC、R–2R倒T形电阻网络DAC和单值电流型网络DAC等。权电阻网络DAC的转换精度取决于基准电压VREF,以及模拟电子开关、运算放大器和各权电阻值的精度。它的缺点是各权电阻的阻值都不相同,位数多时,其阻值相差甚远,这给保证精度带来很大困难,特别是对于集成电路的制作很不利,因此在集成的DAC中很少单独使用该电路。
它由若干个相同的R、2R网络节组成,每节对应于一个输入位。节与节之间串接成倒T形网络。R–2R倒T形电阻网络DAC是工作速度较快、应用较多的一种。和权电阻网络比较,由于它只有R、2R两种阻值,从而克服了权电阻阻值多,且阻值差别大的缺点 。
电流型DAC则是将恒流源切换到电阻网络中,恒流源内阻极大,相当于开路,所以连同电子开关在内,对它的转换精度影响都比较小,又因电子开关大多采用非饱和型的ECL开关电路,使这种DAC可以实现高速转换,转换精度较高 。
3. DAC功能剖析






参考电压
与 ADC 外设类似,DAC 也使用 VREF+引脚作为参考电压,在设计原理图的时候一般把VSSA接地,把 VREF+和 VDDA 接 3.3V,可得到 DAC 的输出电压范围为:0~3.3V。如果想让输出的电压范围变宽,可以在外部加一个电压调理电路,把 0~3.3V 的 DAC输出抬升到特定的范围即可。
数模转换及输出通道
框图中的―数字至模拟转换器 x‖是核心部件,整个 DAC 外设都围绕它而展开。它以左边的 VREF+作为参考电源,以 DAC 的数据寄存器“DORx”的数字编码作为输入,经过它转换得的模拟信号由右侧的“DAC_OUTx”通道输出。其中各个部件中的―x‖是指设备的标号,在 STM32 中具有 2 个这样的 DAC 部件,每个 DAC 有 1 个对应的输出通道连接到特定的引脚,即:PA4-通道 1,PA5-通道 2,为避免干扰,使用 DAC 功能时,DAC 通道引脚需要被配置成模拟输入功能(AIN)。
触发源及 DHRx 寄存器
在使用 DAC 时,不能直接对上述 DORx 寄存器写入数据,何输出到 DAC 通道 x 的数据都必须写入到 DHRx 寄存器中(其中包含 DHR8RxDHR12Lx 等,根据数据对齐方向和分辨率的情况写入到对应的寄存器中)。数据被写入到 DHRx 寄存器后,DAC 会根据触发配置进行处理,若使用硬件触发,则DHRx 中的数据会在 3 个APB1 时钟周期后传输至 DORx,DORx 随之输出相应的模拟电压到输出通道;若 DAC 设置为外部事件触发,可以使用定时器(TIMx_TRGO)、EXTI_9信号或软件触发(SWTRIGx)这几种方式控制数据 DAC 转换的时机,例如使用定时器触发,配合不同时刻的 DHRx 数据,可实现 DAC 输出正弦波的功能。
二、输出一个周期2khz的正弦波


  本实验是利用DAC功能输出一个正弦波,同样本实验涉及到的源码仍然以官方提供为基础,野火官方提供了有关DAC输出正弦波的代码,可以以此分析修改。
1.DAC输出正弦波原理

这里主要叙述软件设计部分,为了使工程更加有条理,我们把 DAC 控制相关的代码独立分开存储,方便以后移植。这里主要将输出正弦波的第一步:计算获取正弦波数据表。
要输出正弦波,实质是要控制 DAC 以 v=sin(t)的正弦函数关系输出电压,其中 v 为电压输出,t 为时间。而由于模拟信号连续而数字信号是离散的,所以使用 DAC 产生正弦波时,只能按一定时间间隔输出正弦曲线上的点,在该时间段内输出相同的电压值,若缩短时间间隔,提高单个周期内的输出点数,可以得到逼近连续正弦波的图形,如图,若在外部电路加上适当的电容滤波,可得到更完美的图形。





由于正弦曲线是周期函数,所以只需要得到单个周期内的数据后按周期重复即可,而单个周期内取样输出的点数又是有限的,所以为了得到呈 v=sin(t)函数关系电压值的数据通常不会实时计算获取,而是预先计算好函数单个周期内的电压数据表,并且转化成以 DAC寄存器表示的值。 如 sin 函数值的范围为[-1: +1],而 STM32 的 DAC 输出电压范围为[0~3.3]V,按 12 位DAC 分辨率表示的方法,可写入寄存器的最大值为 2^12 = 4096,即范围为[0:4096]。所以,实际输出时,会进行如下处理:
抬升 sin 函数的输出为正值:v = sin(t)+1 ,此时,v 的输出范围为[0:2];
扩展输出至 DAC 的全电压范围: v = 3.3*(sin(t)+1)/2 ,此时,v 的输出范围为[0:3.3], 正是 DAC 的电压输出范围,扩展至全电压范围可以充分利用 DAC 的分辨率;
把电压值以 DAC 寄存器的形式表示:Reg_val = 212/3.3 * v = 211*(sin(t)+1),此时,存储到 DAC 寄存器的值范围为[0:4096];
实践证明,在 sin(t)的单个周期内,取 32 个点进行电压输出已经能较好地还原正弦波形,所以在 t∈[0:2π]区间内等间距根据上述 Reg_val 公式运算得到 32 个寄存器值,即可得到正弦波表;
控制 DAC 输出时,每隔一段相同的时间从上述正弦波表中取出一个新数据进行输出,
即可输出正弦波。改变间隔时间的单位长度,可以改变正弦波曲线的周期。
为方便起见,我们使用了 Python 和 Matlab 脚本制作正弦波表,脚本的代码存储在本
工程的目录下,感兴趣可以打开文件查看,以下列出 Python 脚本代码,
Python 脚本的实现原理就是前面介绍的正弦波数据表的制作过程,运行后,该脚本把
得到的正弦波表数据输出到目录下的 py_dac_sinWav.c 文件中,并且根 据取样点描绘出示意图。
实验过程

打开Audition软件,然后选择文件-新建-音频文件





调节相关参数





选择效果-生成基本音色





调节相关参数然后最后点击确定





导出为wav文件,选择文件–导出-文件





点击确定




使用UltraEdit
Ultraedit下载激活链接:链接
打开Ultraedit,然后打开刚才保存的wav文件
CTRL+A,然后右击选择十六进制复制选定视图,将内容粘贴到一个新建文件夹中





在新建文件夹中,按CTRL+A接着鼠标右击选择范围输入起始号和列号,确定就选择了我们需要的内容





使用notepad+++添加相关内容
下载notepad:
打开该软件,将刚才复制的内容粘贴到这里面




在需要添加内容的地方,alt+c





将编译生成的文件烧录到板子里,将板子PA4或者PA5端连接示波器,打开示波器就如图:
举报

更多回帖

发帖
×
20
完善资料,
赚取积分