ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

STM32CubeMX配置DAC、TIM播放音乐

2022-02-27 22:58:38  阅读:713  来源: 互联网

标签:定时器 HAL DAC 中断 STM32CubeMX TIM uint32


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

一、STM32CubeMX配置DAC、TIM

1.打开软件(我使用的是v5.5.0),新建工程。
在这里插入图片描述
2.选择芯片型号,点击开始。我手里的芯片是STM32L431CCT6,主频最高80Mhz。
在这里插入图片描述
3.配置时钟树,此次使用最小系统版上外部石英晶振是8Mhz,MCU主频最大80Mhz。此次我们将其配置到最大频率。
在这里插入图片描述
4.配置使用外部石英晶振。
在这里插入图片描述
5.配置Debug为串行线,即使用J-Link进行下载调试,连接VCC、GND、SWDIO、SWCLK即可实现keil程序下载和在线调试。
在这里插入图片描述
6.配置DAC。触发方式我们选择None
在这里插入图片描述
触发方式,指DAC转换可以由某外部事件触发(定时器计数器、外部中断线)。片上定时器信号、外部引脚、软件控制。(此表非本芯片的,仅用来说明用触发方式用)
在这里插入图片描述
每次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的频率播放。
在这里插入图片描述
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 使能

定时器定时计算方法:
在这里插入图片描述
打开定时器中断
在这里插入图片描述

音频为8000hz,则每125us需要播放一个音频数据。定时器时间125us,将分频系数9和自动重装载值999带入,刚好是125us。(也可以是其他值,只要最终结果是125us即可)
8.生成代码。
在这里插入图片描述
在这里插入图片描述

二、测试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模拟电压
在这里插入图片描述

2.烧写程序,使用示波器查看电压。
如下图,测试了n遍都是只有一下的模拟电压,然后就掉下去,甚是郁闷,后来发现是示波器错选了交流模式,无语。(话说用万用表可能就没有这个烦恼了)
在这里插入图片描述
正常的,复位5秒后dac转换,很明显电压直接上来了,没达到5v是因为电路损耗。DAC配置成功
在这里插入图片描述
3.开启TIM2,并填写定时器回调函数。
在这里插入图片描述
在这里插入图片描述
相关函数:
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;
}

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

硬件如下:

在这里插入图片描述

标签:定时器,HAL,DAC,中断,STM32CubeMX,TIM,uint32
来源: https://blog.csdn.net/qq_38893512/article/details/123169760

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有