基于stm32片内Flash数据的DAC输出


前言

使用用Adobe audition音频编辑软件录制“您好欢迎光临!”的几秒钟的声音(8khz采样、8bit量化编码的单声道wav格式),确保音频数据尽量小(最大不超64KB),然后编程将其分批次写入Stm32f103芯片内部flash区域。

然后将数字音频还原播放,编程读取此段音频,我们这里通过stm32f103自带的DAC通道,转换为模拟音频进行播放,并用示波器观察波形,用耳机/喇叭收听,评判音乐还原效果;


一、DAC简介

DAC 为数字/模拟转换模块,故名思议,它的作用就是把输入的数字编码,转换成对应的模拟电压输出,它的功能与 ADC相反。在常见的数字信号系统中,大部分传感器信号被化成电压信号,而 ADC把电压模拟信号转换成易于计算机存储、处理的数字编码,由计算机处理完成后,再由DAC输出电压模拟信号,该电压模拟信号常常用来驱动某些执行器件,使人类易于感知。

如音频信号的采集及还原就是这样一个过程。
STM32 具有片上 DAC 外设,它的分辨率可配置为 8 位或 12 位的数字输入信号,具有两个 DAC输出通道,这两个通道互不影响,每个通道都可以使用 DMA 功能,都具有出错检测能力,可外部触发。

功能框图

在这里插入图片描述
DAC原理

DAC的运行过程,其实就是由定时器定时触发DAC转换数据,每当出现定时器更新事件,由DMA运送新的数据到达DAC的寄存器,DAC输出新的数据,而由于这些数据正是一个周期的正弦波的数字形式(我们使用软件生成),经过一个周期的DAC转换,就能输出一个连续的模拟正弦波数据了。

了解了DAC的工作原理,我们不仅可以控制生成正弦波,通过控制配置定时器分频因子和时钟周期就可以控制正弦波的频率了。

具体公式如下

fsin=1/Tsysclk(TIM_Prescaler+1)(TIM_Period+1)*N
其中N为正弦波单个周期的点数

在这里插入图片描述

二、使用DAC输出单周期的正弦波

我本次用到了野火的例程,野火例程里的正弦波输出,在其代码基础上稍微修改一下,使其输出频率为2KHZ的正弦波

首先我们打开野火关于正弦波的文件,然后打开matlab采样脚本

在这里插入图片描述
使用matlab打开一下文件

在这里插入图片描述
在其中修改采样点数,可以看到matlab绘制的波形图

在这里插入图片描述
我们把这个把输出的采样点数据复制到野火提供的例程代码中

在这里插入图片描述
存放在下面数组中

在这里插入图片描述

然后我们编译,将代码烧到开发板中即可,使用示波器观察PA4、PA5通道即可,这里由于实验条件限制,所以没有使用示波器观测现象。


三、PCM模块输出音频

我们先使用录音软件录制一段“你好,欢迎光临”的声音,然后使用Adobe Audition软件打开录制好的音频,截取片段并生成.wav文件

在这里插入图片描述
上图生成的波形是立体声波形,我们点击右键–提取声道为单声道文件

在这里插入图片描述
然后选中生成的单声道文件,框选想要录制的音频区域,然后右键选择存储选区(注意截取的音频不要太长,STM32内部flash存储空间可能不够)

在这里插入图片描述

配置如下

在这里插入图片描述
将生成的文件使用Ultraedit打开

在这里插入图片描述

然后CTRL+A,接着鼠标右键,选择 十六进制复制选定视图,将内容粘贴到一个新建的UltraEdit文件中

在这里插入图片描述
在新建文件中,CTRL+A,接着鼠标右键,选择范围输入起始的行号和列号,选中我们需要的内容

在这里插入图片描述
然后CTRL+C,将所选文本复制到notepad++所创建的一个新文件去

然后ALT+C,进入列块编辑模式,输入想要插入的内容,如下图所示

在这里插入图片描述
然后将生成的十六进制文件数据放到刚刚的数组中,烧录后观察现象。

参考

STM32 基础系列教程 16 - I2S(模拟)

STM32F103使用TIM DMA DAC实现播放WAV音乐

STM32笔记–DAC(正弦波发生)

STM32F103的DAC——输出声音效果

详细介绍Audition输出一个周期2khz的正弦波(循环)。将一段数字音频歌曲数据转换为模拟音频波形输出(循环)

【Audio】I2S传输PCM音频数据分析总结(二)

### 使用 STM32 DAC 输出正弦波 #### 配置教程 为了使 STM32DAC 能够输出正弦波,需要完成几个主要部分的设置:初始化 DAC 和 DMA 控制器、准备正弦波表以及启动转换过程。 对于 STM32H7 系列微控制器而言,在配置 SPI 数据传输宽度时可以选择 4 到 32 bit 不同长度的数据帧大小[^1]。然而当涉及到通过 DAC 发送信号的情况,则不需要调整 SPI 设置而是关注于 DAC 及其关联外设DMA的操作方式。 具体来说: - **DAC 初始化**:设定所需的通道数(单端或差分)、触发源(软件触发还是定时器等硬件事件触发),并开启相应的中断服务函数以便处理溢出或其他异常情况; - **DMA 配置**:指定存储区地址作为数据缓冲池来装载预计算好的样本点集合;定义每次传输完成后自动更新目标寄存器的功能;确保循环模式被激活从而允许连续不断地重复播放同一组数值直到停止命令下达为止。 - **创建正弦表格**:依据所需频率合成一系列离散时间幅度值构成周期性的变化规律,这些采样点将由 DMA 进行读取并通过 DAC 实现模拟电压级别的转变。 下面给出一段基于 HAL 库编写的 C++ 示例代码用于展示上述流程中的关键环节: ```cpp #include "stm32h7xx_hal.h" // 定义全局变量 uint16_t sine_wave_table[SINE_WAVE_LENGTH]; // 存储正弦波形数组 DMA_HandleTypeDef hdma_dac; DAC_HandleTypeDef hdac; void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void){ /* Reset of all peripherals, Initializes the Flash interface and Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_DAC_Init(&hdac); // 填充正弦波表... fill_sine_wave_table(sine_wave_table); // 启动 DMA 流向 DAC 的传输操作 HAL_DAC_Start_DMA(&hdac,DAC_CHANNEL_1,(uint32_t*)sine_wave_table,SINE_WAVE_LENGTH,CIRCULAR_MODE); while (true){ } } /** * @brief Fill a table with values representing one period of a sinusoidal waveform. * * @param[out] dest Pointer to an array where generated samples will be stored. */ void fill_sine_wave_table(uint16_t* dest){ float amplitude = 3276; // 占满整个范围的一半(0~4095),留有余量防止过载失真 int i; for(i=0;i<SINE_WAVE_LENGTH;++i){ *(dest+i)=(uint16_t)(amplitude*(sin((float)i/(SINE_WAVE_LENGTH/2)*M_PI)+1)); } } ``` 此段程序段展示了如何利用 STM32 微处理器内部资源生成稳定的正弦波输出。需要注意的是实际应用中可能还需要考虑更多细节比如同步机制、噪声抑制措施等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值