STM32弄一个的音乐播放器,用PWM控制蜂鸣器
目录
效果展示
基于STM32用PWM控制蜂鸣器
前言
音乐播放器项目,我使用PWM输出捕获的方式控制无源蜂鸣器响,这样可以解放主函数的空间,用来控制其他外设。 (PWM的介绍在STM32学习笔记中我做了详细的介绍和应用实例)
一、设计背景
1.1、知识储备
用到了蜂鸣器、独立按键、LED、PWM输出捕获、引脚重映射、定时器中断等方面的知识。同时还要了解STM32内部时钟树,我用到的开发工具有:STM32 CubeMX和MDK kile5,并且我使用的是HAL库进行的编程。为什么不用标准库主要是因为,HAL库是ST公司一直维护和支持更新的库,它的支持性更好,标准库在2011年就已经停止了维护,但是HAL库的调用更抽象,所以我在学习时用标准库,更加形象具体,能快速的打好基础,而做项目则用的HAL库,可以用cubeMX进行图形化编程,效率更高。两种库各有利弊,不存在谁好谁坏。 而且HAL库只是支持ST公司的单片机,这变相限制了开发移植性。
二、系统设计方案
2.1、实现功能
1.开发板通电,蜂鸣器能正常播放音乐;
2.通过按键可以向前\向后切换歌曲;
3.LED指示灯随着按键的按下进行翻转指示;
2.2、硬件部分
使用的是正点原子精英开发板,芯片是STM32F103ZET6,内部时钟为72M。蜂鸣器是无源蜂鸣器,无内部振荡电路,可以改变其频率,使其播放音乐。独立按键控制音乐的播放并且可以切歌。LED做为指示灯,用来判断独立按键是否按下。
2.3、软件部分
PE5、PB5为LED引脚,PB7为PWM输出捕获引脚(TIM4、CH2),PE3、PE4为独立按键控制引脚(开启中断),开启定时器TIM2;
三、软件设计
3.1、设计流程图
3.2、音乐频率的设置
这个项目的难点就是设置音乐频率,按照我之前使用51单片机制作音乐播放器的经验,音乐频率,主要是音乐的音符,音调和节拍之间的关系。
音符决定发音单元,音调决定音量的高低,节拍决定音符发音的时间长短。
3.3、编程主要思路
因为我采用PWM和定时器控制蜂鸣器,主要关系是这样的:定时器把握音乐的节拍,PWM把握音调和音符。
还是得说一下PWM。PWM 周期由定时器分频系数和重装载值共同决定,STM32F103ZET6的主频为72MHZ,设置分频为9,所以最大是8MHZ。而我们所需要的最小频率是262HZ,所以我们只需要计算得到的重装载值不大于定时器的重装载最大值(65535)即可。
所以每次转换音符时,动态修改重装载值即可实现 PWM 输出频率的变化,进而控制无源蜂鸣器发声。定时器将进行 ms 中断,判断每拍时间是否到达,到达则播放下一拍。
四、程序设计
篇幅有限,只能展示部分代码,需要全部代码,请私信博主,谢谢。
music.c程序如下:
-
-
-
uint16_t C_FREQ[]={0,262,294,330,349,392,440,
-
494,523,587,659,698,784,880,988,
-
1046,1175,1318,1397,1568,1760,1976};
-
-
/*-------------------两只老虎--------------------*/
-
-
/*频率*/
-
uint8_t music_two_tiger_f[]={
-
1,2,3,1,
-
1,2,3,1,
-
3,4,5,
-
3,4,5,
-
5,6,5,6,3,1,
-
5,6,5,4,3,1,
-
1,5,1,
-
1,5,1,
-
};
-
-
/*1/4拍长*/
-
u16 music_two_tiger_t_echo=150;
-
-
/*长度*/
-
u16 music_two_tiger_len=(sizeof(music_two_tiger_f)/sizeof(uint8_t));
-
-
/*拍长*/
-
uint8_t music_two_tiger_t[]={
-
P_1,P_1,P_1,P_1,
-
P_1,P_1,P_1,P_1,
-
P_1,P_1,P_2,
-
P_1,P_1,P_2,
-
P_4_3,P_4_1,P_4_3,P_4_1,P_1,P_1,
-
P_4_3,P_4_1,P_4_3,P_4_1,P_1,P_1,
-
P_1,P_1,P_2,
-
P_1,P_1,P_2,
-
};
-
-
/*-------------------春节序曲--------------------*/
-
-
/*频率*/
-
uint8_t music_happy_newyear_f[]={
-
3,2,3,5,5,6,
-
7,6,7,7,
-
3,7,6,5,3,5,
-
6,5,6,5,
-
5,6,1,6,1,2,
-
1,6,5,3,
-
5,6,1,2,1,7,
-
6,5,6,5,
-
3,2,3,5,5,6,
-
1,6,3,1,
-
};
-
-
/*1/4拍长*/
-
u16 music_happy_newyear_t_echo=200;
-
-
/*长度*/
-
u16 music_happy_newyear_len=(sizeof(music_happy_newyear_f)/sizeof(uint8_t));
-
-
/*拍长*/
-
uint8_t music_happy_newyear_t[]={
-
P_2_1,P_1,P_2_1,P_2_1,P_1,P_2_1,
-
P_1,P_2_1,P_2_1,P_2,
-
P_2_1,P_1,P_2_1,P_2_1,P_1,P_2_1,
-
P_4_3,P_4_1,P_1,P_2,
-
P_4_3,P_4_1,P_1,P_2_1,P_1,P_2_1,
-
P_1,P_2_1,P_2_1,P_2,
-
P_4_3,P_4_1,P_1,P_2_1,P_1,P_2_1,
-
P_4_3,P_4_1,P_1,P_2,
-
P_2_1,P_1,P_2_1,P_2_1,P_1,P_2_1,
-
P_1,P_2_1,P_2_1,P_2,
-
};
-
-
/*-------------------难忘今宵--------------------*/
-
-
/*频率*/
-
uint8_t music_bitter_unforget_f[]={
-
2,3,2,1,2,3,2,5,
-
5,5,5,2,4,3,2,
-
7,1,2,3,1,7,1,2,3,5,
-
5,4,3,4,3,2,1,
-
-
5,6,5,4,1,3,4,6,5,5,
-
2,6,5,6,4,6,5,
-
3,4,3,2,5,3,4,3,2,1,
-
-
5,4,3,4,3,2,1,
-
6,5,4,1,4,6,5,5,
-
6,5,4,1,4,6,5,5,
-
-
3,2,1,5,1,3,2,2,
-
3,2,1,5,1,3,5,5,
-
3,2,1,5,1,3,1,1,
-
};
-
-
/*1/4拍长*/
-
u16 music_bitter_unforget_t_echo=300;
-
-
/*长度*/
-
u16 music_bitter_unforget_len=(sizeof(music_bitter_unforget_f)/sizeof(uint8_t));
-
-
/*拍长*/
-
uint8_t music_bitter_unforget_t[]={
-
P_2_1,P_4_1,P_4_1,P_1,P_2_1,P_4_1,P_4_1,P_1,
-
P_2_1,P_2_1,P_4_1,P_4_1,P_4_1,P_4_1,P_2,
-
P_4_1,P_4_1,P_4_1,P_4_1,P_1,P_4_1,P_4_1,P_4_1,P_4_1,P_1,
-
P_2_1,P_2_1,P_4_1,P_4_1,P_4_1,P_4_1,P_2,
-
-
P_2_1,P_4_1,P_4_1,P_2_1,P_2_1,P_4_1,P_4_1,P_4_1,P_4_1,P_1,
-
P_2_1,P_2_1,P_4_1,P_4_1,P_4_1,P_4_1,P_2,
-
P_4_1,P_4_1,P_4_1,P_4_1,P_1,P_4_1,P_4_1,P_4_1,P_4_1,P_1,
-
-
P_2_1,P_2_1,P_4_1,P_4_1,P_4_1,P_4_1,P_2,
-
P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_2_1,P_2,
-
P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_2_1,P_2,
-
-
P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_2_1,P_2,
-
P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_2_1,P_2,
-
P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_4_1,P_2_1,P_2,
-
};
-
-
struct MUSIC_T music_t;
-
-
u8 B0[]="stop";
-
u8 B1[]="two tigers";
-
u8 B2[]="happy newyear";
-
u8 B3[]="bitter_unforget";
-
-
void music_tea_seeds(u8 n){
-
switch(n){
-
case 0:{
-
music_t.f=NULL;
-
music_t.t=NULL;
-
music_t.len=0;
-
music_t.t_each=0;
-
music_t.name=B0;
-
};break;
-
case 1:{
-
music_t.f=music_two_tiger_f;
-
music_t.t=music_two_tiger_t;
-
music_t.len=music_two_tiger_len;
-
music_t.t_each=music_two_tiger_t_echo;
-
music_t.name=B1;
-
}; break;
-
case 2:{
-
music_t.f=music_happy_newyear_f;
-
music_t.t=music_happy_newyear_t;
-
music_t.len=music_happy_newyear_len;
-
music_t.t_each=music_happy_newyear_t_echo;
-
music_t.name=B2;
-
};break;
-
case 3:{
-
music_t.f=music_bitter_unforget_f;
-
music_t.t=music_bitter_unforget_t;
-
music_t.len=music_bitter_unforget_len;
-
music_t.t_each=music_bitter_unforget_t_echo;
-
music_t.name=B3;
-
};break;
-
case 4:{
-
-
}; break;
-
case 5:{
-
-
};break;
-
}
-
}
-
beep.c
-
-
-
-
-
-
-
/*
-
蜂鸣器根据频率发声音
-
note_f:频率,取值来自于数组
-
vol:声音,取值范围区间:[0,100]
-
*/
-
-
void my_passive_buzzer_set(uint16_t note_f)
-
{
-
/*计算自动重装载值,计算新的频率*/
-
uint16_t Autoreload=(80000.0/(float)C_FREQ[note_f])-1;
-
/*计算音量*/
-
uint16_t volume=(((float)Autoreload)/100.0)*TEA_VOL;
-
/*设置自动重装载值*/
-
__HAL_TIM_SET_AUTORELOAD(&htim4,Autoreload);
-
/*设置音量*/
-
__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,volume);
-
/*情况计算值*/
-
__HAL_TIM_SET_COUNTER(&htim4,0);
-
}
-
-
u32 paly_delay_ms=0;
-
void my_buzzer_play()
-
{
-
static u8 last_flg=255;//记录上一首歌
-
-
/*歌曲切换*/
-
if(last_flg!=music_t.now_flg)
-
{
-
music_t.now_len=0;
-
music_code_get(music_t.now_flg);
-
last_flg=mymusic_t.now_flg;
-
}
-
if(music_t.now_flg==0)
-
{
-
passive_buzzer_set(0);
-
return;
-
}
-
if(paly_delay_ms==0)
-
{
-
paly_delay_ms=music_t.t_each*music_t.t[music_t.now_len];
-
passive_buzzer_set(music_t.f[music_t.now_len]);
-
-
if(music_t.now_len>=(music_t.len-1))
-
{
-
music_t.now_len=0;
-
}else
-
{
-
music_t.now_len ;
-
}
-
}else
-
{
-
paly_delay_ms--;
-
}
-
}
-
-
/*定时器1ms中断*/
-
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
-
{
-
if(htim->Instance == TIM2)
-
{
-
buzzer_play();
-
}
-
}
-
-
tim.c
-
/* USER CODE BEGIN Header */
-
/**
-
******************************************************************************
-
* @file tim.c
-
* @brief This file provides code for the configuration
-
* of the TIM instances.
-
******************************************************************************
-
* @attention
-
*
-
* Copyright (c) 2022 STMicroelectronics.
-
* All rights reserved.
-
*
-
* This software is licensed under terms that can be found in the LICENSE file
-
* in the root directory of this software component.
-
* If no LICENSE file comes with this software, it is provided AS-IS.
-
*
-
******************************************************************************
-
*/
-
/* USER CODE END Header */
-
/* Includes ------------------------------------------------------------------*/
-
-
-
/* USER CODE BEGIN 0 */
-
-
/* USER CODE END 0 */
-
-
TIM_HandleTypeDef htim2;
-
TIM_HandleTypeDef htim4;
-
-
/* TIM2 init function */
-
void MX_TIM2_Init(void)
-
{
-
-
/* USER CODE BEGIN TIM2_Init 0 */
-
-
/* USER CODE END TIM2_Init 0 */
-
-
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
-
TIM_MasterConfigTypeDef sMasterConfig = {0};
-
-
/* USER CODE BEGIN TIM2_Init 1 */
-
-
/* USER CODE END TIM2_Init 1 */
-
htim2.Instance = TIM2;
-
htim2.Init.Prescaler = 7200-1;
-
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
-
htim2.Init.Period = 9;
-
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
-
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
-
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
-
{
-
Error_Handler();
-
}
-
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
-
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
-
{
-
Error_Handler();
-
}
-
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
-
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
-
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
-
{
-
Error_Handler();
-
}
-
/* USER CODE BEGIN TIM2_Init 2 */
-
-
/* USER CODE END TIM2_Init 2 */
-
-
}
-
/* TIM4 init function */
-
void MX_TIM4_Init(void)
-
{
-
-
/* USER CODE BEGIN TIM4_Init 0 */
-
-
/* USER CODE END TIM4_Init 0 */
-
-
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
-
TIM_MasterConfigTypeDef sMasterConfig = {0};
-
TIM_OC_InitTypeDef sConfigOC = {0};
-
-
/* USER CODE BEGIN TIM4_Init 1 */
-
-
/* USER CODE END TIM4_Init 1 */
-
htim4.Instance = TIM4;
-
htim4.Init.Prescaler = 9-1;
-
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
-
htim4.Init.Period = 65535-1;
-
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
-
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
-
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
-
{
-
Error_Handler();
-
}
-
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
-
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
-
{
-
Error_Handler();
-
}
-
if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
-
{
-
Error_Handler();
-
}
-
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
-
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
-
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
-
{
-
Error_Handler();
-
}
-
sConfigOC.OCMode = TIM_OCMODE_PWM1;
-
sConfigOC.Pulse = 0;
-
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
-
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
-
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
-
{
-
Error_Handler();
-
}
-
/* USER CODE BEGIN TIM4_Init 2 */
-
-
/* USER CODE END TIM4_Init 2 */
-
HAL_TIM_MspPostInit(&htim4);
-
-
}
-
-
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
-
{
-
-
if(tim_baseHandle->Instance==TIM2)
-
{
-
/* USER CODE BEGIN TIM2_MspInit 0 */
-
-
/* USER CODE END TIM2_MspInit 0 */
-
/* TIM2 clock enable */
-
__HAL_RCC_TIM2_CLK_ENABLE();
-
-
/* TIM2 interrupt Init */
-
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
-
HAL_NVIC_EnableIRQ(TIM2_IRQn);
-
/* USER CODE BEGIN TIM2_MspInit 1 */
-
-
/* USER CODE END TIM2_MspInit 1 */
-
}
-
else if(tim_baseHandle->Instance==TIM4)
-
{
-
/* USER CODE BEGIN TIM4_MspInit 0 */
-
-
/* USER CODE END TIM4_MspInit 0 */
-
/* TIM4 clock enable */
-
__HAL_RCC_TIM4_CLK_ENABLE();
-
-
/* TIM4 interrupt Init */
-
HAL_NVIC_SetPriority(TIM4_IRQn, 0, 0);
-
HAL_NVIC_EnableIRQ(TIM4_IRQn);
-
/* USER CODE BEGIN TIM4_MspInit 1 */
-
-
/* USER CODE END TIM4_MspInit 1 */
-
}
-
}
-
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
-
{
-
-
GPIO_InitTypeDef GPIO_InitStruct = {0};
-
if(timHandle->Instance==TIM4)
-
{
-
/* USER CODE BEGIN TIM4_MspPostInit 0 */
-
-
/* USER CODE END TIM4_MspPostInit 0 */
-
-
__HAL_RCC_GPIOB_CLK_ENABLE();
-
/**TIM4 GPIO Configuration
-
PB7 ------> TIM4_CH2
-
*/
-
GPIO_InitStruct.Pin = GPIO_PIN_7;
-
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
-
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
-
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
-
/* USER CODE BEGIN TIM4_MspPostInit 1 */
-
-
/* USER CODE END TIM4_MspPostInit 1 */
-
}
-
-
}
-
-
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
-
{
-
-
if(tim_baseHandle->Instance==TIM2)
-
{
-
/* USER CODE BEGIN TIM2_MspDeInit 0 */
-
-
/* USER CODE END TIM2_MspDeInit 0 */
-
/* Peripheral clock disable */
-
__HAL_RCC_TIM2_CLK_DISABLE();
-
-
/* TIM2 interrupt Deinit */
-
HAL_NVIC_DisableIRQ(TIM2_IRQn);
-
/* USER CODE BEGIN TIM2_MspDeInit 1 */
-
-
/* USER CODE END TIM2_MspDeInit 1 */
-
}
-
else if(tim_baseHandle->Instance==TIM4)
-
{
-
/* USER CODE BEGIN TIM4_MspDeInit 0 */
-
-
/* USER CODE END TIM4_MspDeInit 0 */
-
/* Peripheral clock disable */
-
__HAL_RCC_TIM4_CLK_DISABLE();
-
-
/* TIM4 interrupt Deinit */
-
HAL_NVIC_DisableIRQ(TIM4_IRQn);
-
/* USER CODE BEGIN TIM4_MspDeInit 1 */
-
-
/* USER CODE END TIM4_MspDeInit 1 */
-
}
-
}
-
-
/* USER CODE BEGIN 1 */
-
-
/* USER CODE END 1 */
谢谢支持~
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhegbieg
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13