基于STM32的DAC实现音频波形的输出
本文目的是使用STM32的DAC(数模转换)实现音频信号波形的输出。这里分为两个部分:第一部分实现特定频率单音频信号波形的输出;第二部分实现歌曲音频信号波形的输出。目录(一)DAC简介1.STM32的DAC2.DAC主要特征3.DAC通道模块框图(二)单音频正弦波输出1.实验目的2.ADC 配置3.输出信号3.歌曲音频信号波形输出(三)总结(一)DAC简介1.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通道模块框图
名称 | 型号类型 | 注释 |
---|---|---|
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配置会影响到输出正弦波的频率,可根据下图中的公式进行计算。
3.输出信号
3.歌曲音频信号波形输出
- 生成音频信号
使用Adobe Audition
软件打开自己喜欢的音乐,然后选择一段音乐(3到5s左右)右键选择存储选区为
,然后选择格式和更改采样类型,导出为十六进制文件。
- 用UltraEdit打开导出的十六进制文件
- 全部选中内容,右键选择
十六进制复制所选视图
,新建一个文本文件并将复制的内容粘贴进去;然后右键选择选择范围
,根据需要复制所选的内容
- 使用
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()
- 替换之前产生正弦波的数组
- 输出波形
(三)总结
通过DAC输出音频信号波形的实验,我了解了如何配置STM32 进行数字信号的模拟化输出DAC信号的波形,这对于我们掌握单片机的模拟信号输入输出的采集具有很大的意义和作用。
参考文章:
1.STM32F103使用TIM DMA DAC实现播放WAV音乐
2.《STM32中文参考手册》
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)