STM32无源蜂鸣器播放音乐

单片机:STM32F407ZGT6
开发软件:MDK+STM32CubeMX


前言

本实验使用的是低电平触发的无源蜂鸣器

无源蜂鸣器是指没有振荡源的蜂鸣器,因此必须使用一定频率的方波才能驱动它发声,所以无源蜂鸣器播放音乐的本质就是使用定时器的PWM,随着节奏拍调节延时、根据音符调节驱动信号的频率,这样就能播放音乐了。

STM32无源蜂鸣器播放孤勇者


一、找一篇音乐的简谱

找一篇稍微简单点的音乐的简谱,我这里找的是孤勇者。
孤勇者简谱

二、确定音调

① 确定音调,区分高中低音很简单,就看数字上方下方有没有点。
高中低音
② 确定音调对应的频率,如下图所示。
简谱音名和频率关系
③ 定义一个常量浮点型数组,把各音名对应的频率放入。

const float pitch_name_frequency[21] = {
	//低音
	//1		2		3		4		5		6		7
	261.63,	293.67,	329.63,	349.23,	391.99,	440,	493.88,//0-6
	//中音
	//1		2		3		4		5		6		7
	532.25,	587.33,	659.25,	698.46,	783.99,	880,	987.76,//7-13
	//高音
	//1		2		3		4		5		6		7
	1046.50,1174.66,1318.51,1396.92,1567.98,1760,	1975.52//14-20
};

④ 开始抄吧,定义一个常量无符号8位类型数组,把乐谱音名对应频率数组序号放入,抄的过程一定仔细,一不小心就可能抄错。怎么抄
0代表休止符,不发声,这里用21表示,方便后续判断处理,抄完结果如下,每一行都与简谱对应。

const uint8_t gu_yong_zhe[] = {
	9,21,21,7,8,7,9,21,7,8,7,8,9,5,7,5,7,5,7,8,7,
	6,21,21,9,21,21,7,8,7,9,21,7,8,7,8,9,5,7,5,7,5,7,9,8,6,21,21,
	5,7,12,12,12,12,11,12,12,11,12,11,12,11,9,9,9,21,21,5,7,12,12,12,11,12,11,13,13,13,12,13,    
	13,12,9,9,21,9,11,9,8,9,8,9,8,9,11,9,11,9,8,9,8,9,8,21,7,8,
	9,5,7,9,8,9,8,7,7,5,21,21,12,13,14,15,13,14,14,14,13,14,15,13,14,14,14,15,
	16,15,16,15,16,16,15,16,18,16,12,13,14,15,13,14,14,14,13,14,15,13,14,14,14,15,
	16,15,16,15,16,16,15,16,18,16,18,16,18,16,18,16,18,19,16,18,18,16,18,16,18,16,18,19,16,18,18,18,
	16,15,15,15,14,16,16,15,15,15,14,14,12,21,21,18,18,16,15,15,15,14,16,16,15,15,15,14,14,12,21,21,
	21,21,21,21,21,21,21,21,21,21,21,21,12,11,12,11,12,11,12,11,12,12,11,12,11,12,11,
	9,9,9,21,21,12,11,12,11,12,11,12,11,13,13,13,12,13,12,9,9,9,21,21,9,11,9,
	8,9,8,9,8,9,11,9,11,9,8,9,8,9,8,21,7,8,9,12,14,16,15,16,15,14,14,12,21,12,13,
	12,5,7,9,13,13,13,13,12,12,12,21,5,7,9,13,13,13,13,12,12,12,21,12,13,12,21,21
};

三、确定节拍

确定音乐的节拍,也就是PWM持续的时间,即延时时间。
节拍
我们看表格的第一列,音符右方、下方的短横线和右方的圆点共同表示音符的时长。
以音符5为例,设音符 5 (即1拍)延时时间tdelay=4x
右方增加1条横线表示延时时间增加1倍,5 - 的延时时间tdelay=8x,加2条横线表示增加2倍,5 - -的延时时间tdelay=12x。
右方增加1个圆点表示延时时间增加一个半拍,5 · 的延时时间tdelay=6x。
下方增加1条横线表示延时时间减少一半,tdelay=2x,下方增加2条横线表示延时时间减少为1/4,tdelay=x。

因为孤勇者中最小的是1/4拍,因此取1/4拍为单位时间,定义一个常量无符号8位类型数组,将简谱上音名对应节拍抄入,又是一个漫长的过程。
抄入节拍
结果如下。

const uint8_t beat[] = {
	8,4,1,1,1,1,8,3,1,1,1,1,1,3,1,3,1,3,1,2,2,
	8,4,4,8,4,1,1,1,1,8,3,1,1,1,1,1,3,1,3,1,3,1,2,2,8,4,4,
	1,1,2,1,1,1,1,2,1,1,1,1,1,1,1,3,4,4,2,1,1,3,1,1,1,1,1,3,1,1,1,2,
	1,2,1,8,1,1,1,1,3,1,3,1,3,1,1,1,1,1,3,1,3,1,4,2,1,1,
	2,2,2,2,3,1,1,1,2,8,4,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,
	1,1,1,1,2,1,1,2,2,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,
	1,1,1,1,2,1,1,2,2,2,2,3,1,3,1,1,1,1,1,2,2,3,1,3,1,1,1,1,1,2,1,1,
	1,1,2,2,1,1,1,1,2,2,1,1,8,4,2,1,1,1,1,2,2,1,1,1,1,2,2,1,1,8,4,4,
	4,4,4,4,4,4,4,4,4,4,4,4,2,1,1,3,1,1,1,1,1,2,1,1,1,1,1,1,
	1,3,4,4,2,1,1,3,1,1,1,1,1,3,1,1,1,1,1,1,3,4,4,1,1,1,1,
	3,1,3,1,3,1,1,1,1,1,3,1,3,1,4,2,1,1,2,2,2,2,3,1,1,1,2,12,2,1,1,
	2,2,2,2,4,2,1,1,1,3,12,2,2,2,2,4,2,1,1,1,3,8,2,1,1,8,4,4
};

四、使用STM32CubeMX生成初始化代码

点击Clock Configuration配置时钟树,F407ZGT6最大时钟为168MHz。
时钟树
点击Pinout & Configuration配置RCC。
RCC
配置SYS。
SYS
配置TIM时钟源为内部时钟,通道1为PWM生成。
在这里插入图片描述
配置参数,PSC设置为0不分频,ARR、Pulse都可以设置为0,因为后面程序中会修改的,注意Mode设置为PWM Mode 1,CH Polarity(通道有效极性)设置为0,因为我使用的是低电平触发的无源蜂鸣器。
参数
将TIM2通道1的GPIO引脚速度改为高。
GPIO
点击Project,配置工程名、位置、IDE及IDE版本。
1
勾选这两项,将所有库文件复制到工程文件夹、每个初始化外设生成一个.c和.h文件,下面这项必勾。
2
生成代码,打开工程。

五、代码分析

ARR寄存器的值控制着PWM的周期、频率,因为F407 TIM2时钟已经配置为不分频,所以fcnt=84M,Tcnt=1/84 * 10-6s,Tpwm = ARR * Tcnt ,所以fcnt = ARR * fpwm,ARR = fcnt / fpwm, fcnt=84M,fpwm音调对应频率pitch_name_frequency[gu_yong_zhe[i]]。开始生成PWM,根据节拍延时一段时间,关闭PWM。注意关闭PWM后清零CNT计数器,不然会发生错误。代码:__HAL_TIM_SetCounter(&htim2, 0);

void play_music(void)
{
	uint32_t i, delay_time, tune;
	for(i=0;i<(sizeof(gu_yong_zhe)/sizeof(gu_yong_zhe[0]));i++)
	{
		delay_time = beat[i] * 250; //250ms 1/4拍, 1s 1拍
		if(gu_yong_zhe[i] != 21) // 不是休止符
		{
			tune = (uint32_t)84*1000*1000/pitch_name_frequency[gu_yong_zhe[i]];
//			__HAL_TIM_SetAutoreload(&htim2, tune); // 和下一句作用一样
			TIM2->ARR = tune; // 改变频率
//			__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, tune/2); // 和下一句作用一样
			TIM2->CCR1 = tune/2; // 占空比为50%
			HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
			HAL_Delay(delay_time); // 根据节拍延时
			HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
			__HAL_TIM_SetCounter(&htim2, 0); // CNT寄存器值清0,不然会发生错误
		}
		else // 是休止符
		{
			HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
			HAL_Delay(delay_time);
		}
	}
}

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: STM32无源蜂鸣器是一种低成本的音频装置,它可以通过振动产生声音。虽然它的音质相对较差,但对于一些简单的音乐播放需求来说,是一种有效的选择。 要在STM32上使用无源蜂鸣器播放音乐,首先需要将音乐转换为适合蜂鸣器播放的格式。蜂鸣器只能发出单音,因此需要将音乐转换为一系列频率不同的音符。 接下来,可以使用STM32的GPIO(通用输入/输出)引脚来控制蜂鸣器。通过改变GPIO引脚的电平,可以产生不同的频率振动,从而发出不同的音符。 编写STM32的程序来控制蜂鸣器播放音乐。首先,配置GPIO引脚为输出模式,并将其设置为低电平以确保蜂鸣器不会一直处于激活状态。 接下来,使用一个循环来依次播放音符。在每个循环中,将GPIO引脚设置为高电平,以产生振动,并保持一段时间来产生音符的持续时间。然后,将GPIO引脚恢复为低电平,以停止振动。 通过循环控制不同音符的播放次数和间隔时间,可以实现音乐的播放。为了控制音乐的速度和节奏,可以调整循环的延迟时间。 需要注意的是,由于无源蜂鸣器的音质受限,播放的音乐可能会有失真或低音不够丰富的问题。如果需要更好的音质,可以考虑使用外部音频芯片或模块来实现音乐播放功能。 ### 回答2: 在STM32微控制器上使用无源蜂鸣器播放音乐可以通过PWM(脉宽调制)技术实现。无源蜂鸣器是一种简单而廉价的电子元件,它可以发出事先设计好的音调。以下是实现步骤: 1. 首先,在STM32开发环境中编写代码,配置IO引脚和定时器以产生PWM信号。为了控制无源蜂鸣器的音调,我们需要使用定时器来生成不同频率的PWM信号。 2. 在代码中定义音符的频率和持续时间。音符的频率决定了所发出的声音,持续时间决定了音符的长度。 3. 在代码中定义一个主循环,在该循环中依次播放每个音符。通过改变PWM信号的频率和持续时间,可以产生不同的音调和音乐效果。 4. 使用延迟函数或定时器中断来控制音符的持续时间。当一个音符播放完毕后,延迟一段时间以控制音符之间的间隔,从而使音乐更加流畅。 5. 在主循环中循环播放所有音符,直到所有音符播放完毕或者接收到停止播放的指令。 通过以上步骤,我们可以使用STM32微控制器和无源蜂鸣器播放音乐。需要注意的是,由于无源蜂鸣器只能发出简单的音调,所以播放的音乐可能会有限制。如果需要播放更复杂的音乐,可能需要使用其他音频设备或者扬声器。 ### 回答3: 要在STM32上使用无源蜂鸣器播放音乐,您可以通过PWM(脉冲宽度调制)的方式来控制蜂鸣器的音调和音乐。下面是实现的步骤: 1. 首先,连接无源蜂鸣器STM32开发板上的GPIO引脚上。确保接线正确。 2. 在STM32的代码中,配置相关的GPIO引脚为PWM输出模式。 3. 初始化一个定时器,用于产生PWM信号,并设置其频率为所需的音调。 4. 创建一个数组,用于存储音乐的音符和其对应的频率。您可以根据需要添加不同的音符和频率。 5. 在代码中使用循环来播放音乐。使用定时器产生的PWM信号来控制蜂鸣器的音高,通过定时器的开启和停止来控制音符的长度和间隔。 6. 在循环中,依次读取音乐数组中的音符和频率,并将当前音符的频率写入定时器的自动重装载寄存器。 7. 播放下一个音符前,通过延时函数来控制音符的持续时间。 8. 重复步骤6和7,直到所有的音乐都播放完毕。 9. 如果您希望播放连续的音乐,可以在播放结束后重新开始播放。 这就是如何在STM32上使用无源蜂鸣器播放音乐的一般步骤。您可以根据实际需求自定义音乐和频率,以实现更多的功能和效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值