STM32CubeMx使用教程(五)—— 使用PWM控制蜂鸣器演唱孤勇者

本章节将讲解如何使用STM32CubeMx配置定时器,并使用PWM控制无源蜂鸣器频率演奏

 前言

1.软件准备:STM32CubeMx、Keil5_ MDK

2.硬件准备:STM32F103最小系统板、无源蜂鸣器模块、杜邦线若干

本实验所使用的所有器件清单和工程源码已上传至百度网盘

链接:https://pan.baidu.com/s/11HC05dnI-CEzDaU9OL2ugA?pwd=80o8 
提取码:80o8

一、蜂鸣器发声原理

STM32CubeMx使用教程(五)—— 使用PWM控制蜂鸣器演唱孤勇者_第1张图片

 如图所示为蜂鸣器电路。

一般来说,3.3V直流产生的电信号功率很小,不足以驱动蜂鸣器发出可听见的响声,所以整个模块中有一个电流放大模块,这便是图中的晶体三极管。图中的放大电路是典型的共发射极接法,蜂鸣器接在集电极上,就实现了电流的放大(详细的晶体管放大电路原理请见《模拟电子技术》)

蜂鸣器分为有源和无源两种。所谓的源,指的是其中内部的振荡源,有源蜂鸣器中的振荡器一般是多谐振荡器,其原理就是模拟电路中RC振荡器的一般原理(放大电路、正反馈、相位差90°、稳压电路),有源蜂鸣器内部的振荡源频率是固定的,所以使用时不可调频,且输入的电信号必须是直流。

相比之下,无源蜂鸣器没有内部振荡源,发声的基本原理是电磁感应,其内部的基本结构是一匝匝线圈以及一个微型扬声器。由于没有振荡源,且内部的主要结构是线圈,所以其工作时输入的电信号必须是交流,而不能是频率很低的直流(直流不能通过无负载的线圈,负责线圈会因为短路而被烧坏)。与有源蜂鸣器一样,无源蜂鸣器也必须使用放大电路来增大输入信号的功率。

二、PWM脉冲宽度调制信号

脉冲宽度调制(PWM) 是一种数字信号,最常用于控制电路。该信号在预定义的时间和速度中设置为高(5v或3.3v)和低(0v)。通常,我们将PWM的高电平称为1,低电平为0。

PWM主要有 PWM频率(f)、 PWM周期(T)、 PWM占空比等参数。

PWM频率:是指一秒钟内从高电平时间在到低电平时间,再从低电平跳到高电平的瞬间次数,也就是一秒钟内有多少个PWM的周期。f = T / 1(HZ)。

PWM周期:是指一秒钟内从高电平时间在到低电平时间,T = f / 1(s)。

 PWM占空比:是指一个周期内高电平时间和总时间的比值。

例如:PWM的周期为1ms,高电平时间为0.5ms,低电平时间为0.5ms,则频率就为1kHz,占空比就为百分之五十。

如图所示,为示波器

pwm的调节作用来源于对“占周期”的宽度控制,“占周期”变宽,输出的能量就会提高,通过阻容变换电路所得到的平均电压值也会上升,“占周期”变窄,输出的电压信号的电压平均值就会降低,通过阻容变换电路所得到的平均电压值也会下降

也就是,在一定的频率下,通过不同的占空比即可得到不同的输出模拟电压,由此,我们可以通过控制PWM输出频率控制蜂鸣器发出不同音调。

三、音调的转化

STM32CubeMx使用教程(五)—— 使用PWM控制蜂鸣器演唱孤勇者_第2张图片

如图所示为不同音调对应的频率,我们通过修改定时器psc即可修改不同频率对应的音调。

 

为计算所得产生中断周期,其中为自动重装载值,为预分频,为对应时钟频率。

若要使音调对应定时器频率,以低音DO为例,将 带入上述公式,即可求出的值,修改不同的对应不同的音调。 

由定时器周期计算公式我们可知,Tclk为定时器挂靠时钟总线频率,arr为设定定时器自动重装载值,f已知为不同音调频率,图中“dao”频率为262,通过计算得出psc赋给定时器以获得不同音调。

将所有音调计算出来,放在.h文件宏定义。

四、简单的乐谱知识

(一)音调

STM32CubeMx使用教程(五)—— 使用PWM控制蜂鸣器演唱孤勇者_第3张图片

音阶分为中音、高音、低音,点在上面为高音,没有点为中音,点在下面为低音

(二)音长

简谱对应音阶下无横线为一拍,有单横线为半拍,双横线为1/4拍。音阶数字后有点加半拍音长,有横线加一拍。

五、程序实现

本次实验同样通过STM32CubeMx实现,

打开之前创建的工程

STM32CubeMx使用教程(五)—— 使用PWM控制蜂鸣器演唱孤勇者_第4张图片

STM32CubeMx使用教程(五)—— 使用PWM控制蜂鸣器演唱孤勇者_第5张图片

STM32CubeMx使用教程(五)—— 使用PWM控制蜂鸣器演唱孤勇者_第6张图片

设置psc和arr,因为本次实验是通过修改psc控制定时器频率,所以初始化psc的值可任意 ,arr的值会影响到占空比的大小,一般设置为1000,方便自己计算即可。

STM32CubeMx使用教程(五)—— 使用PWM控制蜂鸣器演唱孤勇者_第7张图片

 设置占空比为50%,其余设置保持默认即可。设置完成后生成代码。

根据音调表对应频率宏定义音调

#define  proport          72000 	//Tclk/(arr+1)=72000000/(1000)

//根据Tout= ((arr+1)*(psc+1))/Tclk推出psc值就是本句define定义的值,Tout为音调频率131Hz的倒数,Tclk=72MHz                                                
#define  L1       ((proport/262)-1)//低调 do 的频率
#define  L2       ((proport/296)-1)//低调 re 的频率
#define  L3       ((proport/330)-1)//低调 mi 的频率
#define  L4       ((proport/349)-1)//低调 fa 的频率
#define  L5       ((proport/392)-1)//低调 sol 的频率
#define  L6       ((proport/440)-1)//低调 la 的频率
#define  L7       ((proport/494)-1)//低调 si 的频率
                                               
#define  M1       ((proport/523)-1)//中调 do 的频率
#define  M2       ((proport/587)-1)//中调 re 的频率
#define  M3       ((proport/659)-1)//中调 mi 的频率
#define  M4       ((proport/699)-1)//中调 fa 的频率
#define  M5       ((proport/784)-1)//中调 sol的频率
#define  M6       ((proport/880)-1)//中调 la 的频率
#define  M7       ((proport/988)-1)//中调 si 的频率

#define  H1       ((proport/1048)-1)//高调 do 的频率
#define  H2       ((proport/1176)-1)//高调 re 的频率
#define  H3       ((proport/1320)-1)//高调 mi 的频率
#define  H4       ((proport/1480)-1)//高调 fa 的频率
#define  H5       ((proport/1640)-1)//高调 sol的频率
#define  H6       ((proport/1760)-1)//高调 la 的频率
#define  H7       ((proport/1976)-1)//高调 si 的频率

#define  Z0       0//

 到此为止,底层基本书写完毕,接下来就是寻找歌曲简谱,实现功能

这里推荐乐谱查询网址陈奕迅《孤勇者》吉他谱_G调吉他弹唱谱_高清六线谱_玩吉他 (wanjita.com)

STM32CubeMx使用教程(五)—— 使用PWM控制蜂鸣器演唱孤勇者_第8张图片

 对应音调编写以下代码

《孤勇者》

/**
* NAME: void Solitary_brave(void)
* FUNCTION : Solitary_brave
*/
void Solitary_brave(void)
{
	int16_t solitary_brave[]=
	{
		M6,50,M7,50,H1,50,H2,50,M7,50,H1,50,H1,100,Z0,10,	//爱你孤身走暗巷
		H1,50,M7,50,H1,50,H2,50,M7,50,H1,50,H1,100,Z0,10, 	//爱你不跪的模样
		H1,50,H2,50,H3,50,H2,50,H3,50,H2,50,H3,100,H3,50,H3,50,H2,50,H3,100,H5,100,H3,100,Z0,10 //爱你对峙过绝望不肯哭一场
		
	};
	int length = sizeof(solitary_brave)/sizeof(solitary_brave[0]);
	for(uint8_t i=0;i<(length/2);i++)
	{
		buzzer_on(solitary_brave[i*2],200);
		HAL_Delay(5*solitary_brave[i*2+1]);
	}
}

《起风了》 

void Wind_Rises(void)
{
	int wind_rise[]=
	{	
		//前奏
		L7,25,M1,25,M2,25,M3,25,L3,50,M5,25,M3,25,M3,50,Z0,150, L7,25,M1,25,M2,25,M3,25,L2,50,M5,25,M3,25,M2,25,M3,25,M1,25,M2,25,L7,25,M1,25,L5,25,Z0,25, L7,25,M1,25,M2,25,M3,25,L3,50,M5,25,M3,75,Z0,150,L7,25,M1,25,M2,25,M3,25,L2,50,M5,25,M3,25,M2,25,M3,25,M1,25,M2,25,Z0,20,
		//这一路上走走停停 顺着少年漂流的痕迹
		M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,25,M3,25,M2,25,M1,25,L6,100,Z0,10,
		//迈出车站的前一刻 竟有些犹豫
		M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M3,25,M2,50,M1,50,M2,100,Z0,50,
		//不仅笑着这近乡情怯 仍无法避免
		M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M3,25,M2,50,M1,50,L6,100,Z0,10
		//而长野的天 依旧那么暖 风吹起了从前
		M3,25,M2,25,M1,25,M2,25,M1,100, M3,25,M2,25,M1,25,M2,25,M1,50,M1,50, M5,25,M3,25,M2,25,M1,25,M2,25,M1,100,M1,150,Z0,30
		//从前初识这世间 万般留恋 看着天边似在眼前 也甘愿赴汤蹈火去走它一遍
		M1,50,M2,50,M3,50,M1,50,M6,50,M5,25,M6,25,M6,50,M6,50, M1,25,M7,50,M6,25,M7,25,M7,100,Z0,5, M7,50,M6,25,M7,25,M7,50,M3,50,H1,25,H2,25,H1,25,M7,25,M6,50,M5,50, M6,50,M5,25,M6,25,M6,25,M5,25,M6,25,M5,25,M6,50,M5,25,M2,25,M2,25,M5,50,M5,50,M3,100,M3,100,Z0,25,
		//如今走过这世间 万般留恋 翻过岁月不同侧脸 措不及防闯入你的笑颜
		M1,50,M2,50,M3,50,M1,50,M6,50,M5,25,M6,25,M6,50,M6,50, M1,25,M7,50,M6,25,M7,25,M7,100,Z0,5, M7,50,M6,25,M7,25,M7,50,M3,50,H1,25,H2,25,H1,25,M7,25,M6,50,M5,50, M6,50,H3,25,H3,25,H3,50,M5,50,M6,50,H3,25,H3,25,H3,25,M5,50,M6,25,M6,100,M6,100,M6,100,Z0,25,
		//我曾难自拔于世界之大 也沉溺于其中梦话
		H1,50,H2,50,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,25,H3,25,H3,50, H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,25,H3,50,H3,50,
		//不得真假 不做挣扎 不惧笑话
		H2,50,H1,25,M6,25,M6,25,H1,50, M6,25,H2,25,H1,25,M6,50,M6,25,H1,50,H1,50, H3,100,H3,25,H4,25,H3,50,H3,25,H2,50,H2,50,Z0,25,
		//我曾将青春翻涌成她 也曾指尖弹出盛夏 心之所动且就随缘去吧
		H1,50,H2,50,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,50, H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H1,50,H1,50,H1,100,H1,100,Z0,10,
		//短短的路走走停停  也有了几分的距离
		M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,25,M3,25,M2,25,M1,25,L6,100,Z0,10,
		//不知抚摸的是故事还是段心情
		M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M3,25,M2,50,M1,50,M2,100,Z0,50,
		//也许期待的不过是与时间为敌
		M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M3,25,M2,50,M1,50,L6,100,Z0,10,
		//再次见到你 微凉晨光里 笑的很甜蜜
		M3,25,M2,25,M1,25,M2,25,M1,100, M3,25,M2,25,M1,25,M2,25,M1,50,M1,50, M5,25,M3,25,M2,25,M1,25,M2,25,M1,100,M1,150,Z0,30,
		//从前初识这世间 万般留恋 看着天边似在眼前 也甘愿赴汤蹈火去走它一遍
		M1,50,M2,50,M3,50,M1,50,M6,50,M5,25,M6,25,M6,50,M6,50, M1,25,M7,50,M6,25,M7,25,M7,100,Z0,5, M7,50,M6,25,M7,25,M7,50,M3,50,H1,25,H2,25,H1,25,M7,25,M6,50,M5,50, M6,50,M5,25,M6,25,M6,25,M5,25,M6,25,M5,25,M6,50,M5,25,M2,25,M2,25,M5,50,M5,50,M3,100,M3,100,Z0,25,
		//如今走过这世间 万般留恋 翻过岁月不同侧脸 措不及防闯入你的笑颜
		M1,50,M2,50,M3,50,M1,50,M6,50,M5,25,M6,25,M6,50,M6,50, M1,25,M7,50,M6,25,M7,25,M7,100,Z0,5, M7,50,M6,25,M7,25,M7,50,M3,50,H1,25,H2,25,H1,25,M7,25,M6,50,M5,50, M6,50,H3,25,H3,25,H3,50,M5,50,M6,50,H3,25,H3,25,H3,25,M5,50,M6,25,M6,100,M6,100,M6,100,Z0,25,
		//我曾难自拔于世界之大 也沉溺于其中梦话
		H1,50,H2,50,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,25,H3,25,H3,50, H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,25,H3,50,H3,50,
		//不得真假 不做挣扎 不惧笑话
		H2,50,H1,25,M6,25,M6,25,H1,50, M6,25,H2,25,H1,25,M6,50,M6,25,H1,50,H1,50, H3,100,H3,25,H4,25,H3,50,H3,25,H2,50,H2,50,Z0,25,
		//我曾将青春翻涌成她 也曾指尖弹出盛夏 心之所动且就随缘去吧
		H1,50,H2,50,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,50, H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H1,50,H1,50,H1,100,H1,100,Z0,10,
		//逆着光行走任风吹雨打吧
		M6,25,H3,50,H3,50,H2,50,H1,25,M6,25,M6,25,H3,50,H2,50,H1,25,M6,25,M6,25,H1,50,H1,50,H1,50,H1,100,Z0,25,
		//晚风吹起你鬓间的白发 抚平回忆留下的疤
		H1,50,H2,50,H2,25,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,25, H3,25,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,25,H3,50,H3,50,Z0,5,
		//你的眼中明暗交杂 一笑生花 暮色遮住你蹒跚的步伐
		H2,50,H1,25,M6,25,M6,25,H1,50,M6,25,H2,25,H1,25,M6,50,M6,50, H1,50,H1,50,H3,100,H3,25,H4,25,H3,50,H3,25,H2,50,H2,50,H1,100,H2,100,H3,100,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,50,
		//走进床头藏起的画 画中的你(低着头说话)
		H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H3,100,H3,50,H2,50,H1,25,M6,25,M6,25,H3,50,H3,50,H2,50,H1,25,M6,25,M6,25,H1,100,H1,50,Z0,5,
		//我仍 了 以爱之名你还愿意吗(衔接头有问题)
		H1,50,H2,50,H1,50,H1,100,M6,25,H3,50,H3,50,H2,50,H1,25,H6,25,H6,25,H3,50,H3,50,H2,50,H1,25,H6,25,H6,25,H1,50,H1,50,H1,100,Z0,5
	};
	int length = sizeof(wind_rise)/sizeof(wind_rise[0]);
	
	for(int i=0;i<(length/2);i++)
	{
		buzzer_on(wind_rise[i*2],260);
		HAL_Delay(wind_rise[i*2+1]*5);
	}
}

可以打开视频看到演示效果 

蜂鸣器演奏孤勇者

你可能感兴趣的:(stm32,单片机,arm)