STM32CubeMX配置DAC、TIM播放音乐

前言
STM32Cube可以快速实现配置,开发项目很快,如果想深入的掌握底层原理,还是要学会用寄存器配置。STM32cubeMX可以很方便的下载官方文档,包括一些模块说明等,搜索到芯片在"Docs & Resources"中下载即可。
STM32CubeMX配置DAC、TIM播放音乐

一、STM32CubeMX配置DAC、TIM

1.打开软件(我使用的是v5.5.0),新建工程。
STM32CubeMX配置DAC、TIM播放音乐
2.选择芯片型号,点击开始。我手里的芯片是STM32L431CCT6,主频最高80Mhz。
STM32CubeMX配置DAC、TIM播放音乐
3.配置时钟树,此次使用最小系统版上外部石英晶振是8Mhz,MCU主频最大80Mhz。此次我们将其配置到最大频率。
STM32CubeMX配置DAC、TIM播放音乐
4.配置使用外部石英晶振。
STM32CubeMX配置DAC、TIM播放音乐
5.配置Debug为串行线,即使用J-Link进行下载调试,连接VCC、GND、SWDIO、SWCLK即可实现keil程序下载和在线调试。
STM32CubeMX配置DAC、TIM播放音乐
6.配置DAC。触发方式我们选择None
STM32CubeMX配置DAC、TIM播放音乐
触发方式,指DAC转换可以由某外部事件触发(定时器计数器、外部中断线)。片上定时器信号、外部引脚、软件控制。(此表非本芯片的,仅用来说明用触发方式用)
STM32CubeMX配置DAC、TIM播放音乐
每次DAC接口侦测到来自选中的定时器TRGO输出,或者外部中断线9的上升沿,近存放在寄 存器DAC_DHRx中的数据会被传送到寄存器DAC_DORx中。在3个APB1时钟周期后,寄存器 DAC_DORx更新为新值。
如果选择软件触发,一旦SWTRIG位置’1’,转换即开始。在数据从DAC_DHRx寄存器传送到 DAC_DORx寄存器后,SWTRIG位由硬件自动清’0’。
7.配置TIM定时器
配置定时器是为了播放音乐用,音频会有一个采样率,需要按照音频的采样率播出信号才可以还原出原始音频。由于单片机资源有限,本次从网上down了一首采样率为8000hz的单通道的音乐。(其它采样率的音频也可以用Audition另存转换),用定时器制作出播放的频率。
设置如下如,要打开定时器溢出中断,要在每次中断中做DAC转换,从而达到8000hz的频率播放。
STM32CubeMX配置DAC、TIM播放音乐
Clock Source(时钟来源)
选项1 :Internal Clock 内部时钟
选项2 : ETR2 外部触发输入(ETR)(仅适用TIM2,3,4)
Prtscaler (定时器分频系数) : 9
Counter Mode(计数模式) Up(向上计数模式)
Counter Period(自动重装载值) :999
CKD(时钟分频因子) :No Division 不分频
选项:可以选择二分频和四分频
auto-reload-preload(自动重装载) : Enable 使能

定时器定时计算方法:
STM32CubeMX配置DAC、TIM播放音乐
打开定时器中断
STM32CubeMX配置DAC、TIM播放音乐

音频为8000hz,则每125us需要播放一个音频数据。定时器时间125us,将分频系数9和自动重装载值999带入,刚好是125us。(也可以是其他值,只要最终结果是125us即可)
8.生成代码。
STM32CubeMX配置DAC、TIM播放音乐
STM32CubeMX配置DAC、TIM播放音乐

二、测试DAC和TIM配置

1.打开keil测试DAC配置是否成功。
DAC配置完后,使用需要有开启动作,然后向DAC写入数据

/* DAC相关HAL库函数*/
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel); //开启DAC输出
HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef* hdac, uint32_t Channel); //关闭DAC输出
HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment); //需要函数中开启DAC的DMA输出
HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel); //关闭DAC的DMA输出
HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data); //设置DAC输出值
uint32_t HAL_DAC_GetValue(DAC_HandleTypeDef* hdac, uint32_t Channel); //获取DAC输出值

我们需要使用的是开启DAC输出和向DAC写入数值,按12位右对齐写入,12位表示最大值4095,则输出电压计算方法为:
Voltage = VREF x (DOR/4095)
我的板子参考电压VREF接的5V,如下写入4095应当输出5v模拟电压
STM32CubeMX配置DAC、TIM播放音乐

2.烧写程序,使用示波器查看电压。
如下图,测试了n遍都是只有一下的模拟电压,然后就掉下去,甚是郁闷,后来发现是示波器错选了交流模式,无语。(话说用万用表可能就没有这个烦恼了)
STM32CubeMX配置DAC、TIM播放音乐
正常的,复位5秒后dac转换,很明显电压直接上来了,没达到5v是因为电路损耗。DAC配置成功
STM32CubeMX配置DAC、TIM播放音乐
3.开启TIM2,并填写定时器回调函数。
STM32CubeMX配置DAC、TIM播放音乐
STM32CubeMX配置DAC、TIM播放音乐
相关函数:
HAL_TIM_IRQHandler(&htim2);
定时器中断处理函数 在stm32f4xx_it.c的 TIM2_IRQHandler()定时器中断服务函数中
这个函数的具体作用是判断中断是否正常,然后判断产生的是哪一类定时器中断(溢出中断/PWM中断等),然后进入相应的中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
在HAL库中,每进行完一个中断,并不会立刻退出,而是会进入到中断回调函数中,

定时器中断到调用回调函数:
1.void TIM2_IRQHandler(void) //首先进入中断函数
2.HAL_TIM_IRQHandler(&htim2);之后进入定时器中断处理函数
3.判断是哪一类定时器中断(溢出中断/PWM中断等) 和定时器通道
4.进入相对应中断回调函数,在中断回调函数中添加用户代码,这个函数名是固定的。
void HAL_TIM_PeriodElapsedCallback(&htim2);
(stm32f1xx_it.c中找到中也可以找到中断回调函数
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) )

三、播放音乐

1.填写回调函数。
准备好采样率为8000hz,位深度为8bit的音频数据流文件,在定时器中循环给DAC转换即可。

int g_count = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //定时器中断回调函数
{
	//定时器设定为125us溢出中断一次,即8000hz的频率。播放的音频数据也是8000hz采样率。
	DAC->DHR8R1 = DATA[g_count];
	g_count++;
	if (g_count == (SOUND_LENGTH-1))
		g_count = 0;
}

音频数组数据文件
STM32CubeMX配置DAC、TIM播放音乐
2.使用示波器捕获转换后的模拟信号:
STM32CubeMX配置DAC、TIM播放音乐
3.接上耳机,并接上一个功放就可以听到音乐了~~STM32CubeMX配置DAC、TIM播放音乐如果不知道选什么功放,可以用PAM8403,某宝有,将DAC信号接入INL或者INR任意一个即可STM32CubeMX配置DAC、TIM播放音乐

硬件如下:

STM32CubeMX配置DAC、TIM播放音乐

上一篇:【STM32】stm32工程所占内存大小的查看方法


下一篇:STM32的RT-Thread-Nano