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

本文目的是使用STM32的DAC(数模转换)实现音频信号波形的输出。这里分为两个部分:第一部分实现特定频率单音频信号波形的输出;第二部分实现歌曲音频信号波形的输出。

(一)DAC简介

1.STM32的DAC

数字/模拟转换模块(DAC)是12位数字输入,电压输出的数字/模拟转换器。DAC可以配置为8位 或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压VREF+以获得更精确的转换结果。

2.DAC主要特征

  • 2个DAC转换器:每个转换器对应1个输出通道
  • 8位或者12位单调输出
  • 12位模式下数据左对齐或者右对齐
  • 同步更新功能
  • 噪声波形生成
  • 三角波形生成
  • 双DAC通道同时或者分别转换
  • 每个通道都有DMA功能
  • 外部触发转换
  • 输入参考电压VREF+

关于STM32的DAC详细内容可参考《STM32中文参考手册》

3.DAC通道模块框图

1

名称型号类型注释
VREF+输入,正模拟参考电压DAC使用的高端/正极参考电压,2.4V ≤ VREF+ ≤ VDDA (3.3V)
VDDA输入,模拟电源模拟电源
VSSA输入,模拟电源地模拟电源的地线
DAC_OUTx模拟输出信号DAC通道x的模拟输出

(二)单音频正弦波输出

1.实验目的

  • PA4管脚输出一个频率为112khz的正弦波
  • 使用该波形驱动蜂鸣器,检验是否会输出“滴…”的单音

2.DAC 配置

以下操作均在STM32F103开发板上进行,参照野火DAC正弦波输出例程。

  • 使能 PA 口时钟,设置 PA4 为模拟输入。
    STM32F103ZET6 的 DAC 通道 1 在 PA4 上,所以,我们先要使能 PORTA 的时钟,然后设
    置 PA4 为模拟输入。DAC 本身是输出,但是为什么端口要设置为模拟输入模式呢?因为一但
    使能 DACx 通道之后,相应的 GPIO 引脚(PA4 或者 PA5)会自动与 DAC 的模拟输出相连,设
    置为输入,是为了避免额外的干扰。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能 PORTA 时钟

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
  • 使能 DAC1 时钟。
    STM32 的 DAC 模块时钟是由 APB1提供的,所以我们调用函数RCC_APB1PeriphClockCmd()设置 DAC 模块的时钟使能。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能 DAC 通道时钟
  • 初始化 DAC,设置 DAC 的工作模式。
    该部分设置全部通过DAC_CR设置实现,包括:DAC 通道 1 使能、DAC 通道 1 输出缓存
    关闭、不使用触发、不使用波形发生器等设置。这里 DAC 初始化是通过函数DAC_Init完成的:
void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct)

跟前面一样,首先我们来看看参数设置结构体类型 DAC_InitTypeDef 的定义:

typedef struct
{
 uint32_t DAC_Trigger; 
 uint32_t DAC_WaveGeneration; 
 uint32_t DAC_LFSRUnmask_TriangleAmplitude; 
 uint32_t DAC_OutputBuffer; 
}DAC_InitTypeDef;

这个结构体的定义只有四个成员变量:

  • 第一个参数 DAC_Trigger用来设置是否使用触发功能,这里我们需要使用定时器2触发功能,所以值为DAC_Trigger_T2_TRGO
  • 第二个参数 DAC_WaveGeneratio用来设置是否使用波形发生,这里我们不使用。所以值为 DAC_WaveGeneration_None
  • 第三个参数 DAC_LFSRUnmask_TriangleAmplitude用来设置屏蔽/幅值选择器,这个变量只在使
    用波形发生器的时候才有用,这里我们设置为 0 即可,值为 DAC_LFSRUnmask_Bit0
  • 第四个参数 DAC_OutputBuffer是用来设置输出缓存控制位,这里我们不使用输出缓存,所以值为 DAC_OutputBuffer_Disable
DAC_InitTypeDef DAC_InitType;
DAC_InitType.DAC_Trigger=DAC_Trigger_T2_TRGO; //使用TIM2作为触发源
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1 输出缓存关闭
DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化 DAC 通道 1 
DAC_Cmd(DAC_Channel_1, ENABLE); //使能 DAC1
  • 配置TIM2触发源
TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* TIM2基本定时器配置 */
// TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
TIM_TimeBaseStructure.TIM_Period = (20-1);//定时周期 20  
TIM_TimeBaseStructure.TIM_Prescaler = 0x0;//预分频,不分频 72M / (0+1) = 72M
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;//时钟分频系数
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* 配置TIM2触发源 */
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
/* 使能TIM2 */
TIM_Cmd(TIM2, ENABLE);

信号频率计算,IM2配置会影响到输出正弦波的频率,可根据下图中的公式进行计算。
2

3.输出信号

2

3.歌曲音频信号波形输出

  • 生成音频信号
    使用Adobe Audition软件打开自己喜欢的音乐,然后选择一段音乐(3到5s左右)右键选择存储选区为,然后选择格式和更改采样类型,导出为十六进制文件。
    3
  • 用UltraEdit打开导出的十六进制文件
    4
  • 全部选中内容,右键选择十六进制复制所选视图,新建一个文本文件并将复制的内容粘贴进去;然后右键选择选择范围,根据需要复制所选的内容
    5
    6
  • 使用notepad++等文本编辑软件在十六进制之前添加0x,也可使用python编写脚本一键生成。
    下面是一个简易的python转换脚本(这里转换的文件末尾会多一个,直接手动去掉即可)
import re

path=r'C:\Users\G3\Desktop\test.txt'	#文件路径
t=re.compile(r'\d\d')
file=open(path)	
txt=file.read()
print(file.read())
file.close()
test=t.findall(txt)

file=open(path,'w')
j=0
for i in test:
    i=''.join(['0x',str(i),', '])
    if j == 16:
        j = 0
        file.write('\n')	#换行
    file.write(i)
    j = j + 1
file.close()
  • 替换之前产生正弦波的数组
    7
  • 输出波形
    3

(三)总结

通过DAC输出音频信号波形的实验,我了解了如何配置STM32 进行数字信号的模拟化输出DAC信号的波形,这对于我们掌握单片机的模拟信号输入输出的采集具有很大的意义和作用。

参考文章:
1.STM32F103使用TIM DMA DAC实现播放WAV音乐
2.《STM32中文参考手册》

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值