STM32—NB-IOT蜂鸣器定时器控制PWM放歌

实现蜂鸣器播放音乐

PWM(脉冲宽度调制)

脉冲宽度调制(PWM)是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。

多数负载(无论是电感性负载还是电容性负载)需要的调制频率高于10Hz,通常调制频率为1kHz到200kHz之间。

许多微控制器内部都包含有PWM控制器。例如,Microchip公司的PIC16C67内含两个PWM控制器,每一个都可以选择接通时间和周期。占空比是接通时间与周期之比;调制频率为周期的倒数。执行PWM操作之前,这种微处理器要求在软件中完成以下工作:

1、设置提供调制方波的片上定时器/计数器的周期

2、 在PWM控制寄存器中设置接通时间

3、设置PWM输出的方向,这个输出是一个通用I/O管脚

4、启动定时器

5、使能PWM控制器

如今几乎所有市售的单片机都有PWM模块功能,若没有(如早期的8051),也可以利用定时器及GPIO口来实现。更为一般的PWM模块控制流程为(笔者使用过TI的2000系列,AVR的Mega系列,TI的LM系列):

1、使能相关的模块(PWM模块以及对应管脚的GPIO模块)。

2、配置PWM模块的功能,具体有:

①:设置PWM定时器周期,该参数决定PWM波形的频率。

②:设置PWM定时器比较值,该参数决定PWM波形的占空比。

③:设置死区(deadband),为避免桥臂的直通需要设置死区,一般较高档的单片机都有该功能。

④:设置故障处理情况,一般为故障是封锁输出,防止过流损坏功率管,故障一般有比较器或ADC或GPIO检测。

⑤:设定同步功能,该功能在多桥臂,即多PWM模块协调工作时尤为重要。

3、设置相应的中断,编写ISR,一般用于电压电流采样,计算下一个周期的占空比,更改占空比,这部分也会有PI控制的功能。

4、使能PWM波形发生。

cubemx配置

在这里插入图片描述
原理图中蜂鸣器对应引脚PA1
在这里插入图片描述
PA1引脚可以使用通用定时器2的2号通道,所以我们把相应的通道设置为PWM输出模式,这样我们就能对蜂鸣器进行输出频率改变了,从而达到改变音调,其实也可以改变占空比,做呼吸灯的时候需要改变占空比,这里我们占空比设为%50。
在这里插入图片描述

红尘情歌

int tone[]={247,262,294,330,349,392,440,294,523,587,659,698,784,1000};//音调对应的频率

int yindiao[]=
{ 
	5,5,6,8,7,6,5,6,13,13,
	5,5,6,8,7,6,5,3,13,13,
	2,2,3,5,3,5,6,3,2,1,
	6,6,5,6,5,3,6,5,13,13,
	5,5,6,8,7,6,5,6,13,13,
	5,5,6,8,7,6,5,3,13,13,
	2,2,3,5,3,5,6,3,2,1,
	6,6,5,6,5,3,6,1,
	13,8,9,10,10,9,8,10,9,8,6,
	13,6,8,9,9,8,6,9,8,6,5,
	13,2,3,5,5,3,5,5,6,8,7,6,
	6,10,9,9,8,6,5,6,8
};

int dtime[]=    //节拍
{
	2,4,2,2,2,2,2,8,4, 4,
	2,4,2,2,2,2,2,8,4, 4,
	2,4,2,4,2,2,4,2,2,8,
	2,4,2,2,2,2,2,8,4 ,4, 
	2,4,2,2,2,2,2,8,4, 4,
	2,4,2,2,2,2,2,8,4, 4, 
	2,4,2,4,2,2,4,2,2,8,
	2,4,2,2,2,2,2,8,
	4, 2,2,2, 4, 2,2,2, 2,2,8,
	4, 2,2,2, 4, 2,2,2, 2,2,8,
	4, 2,2,2,4,2,2,5,2,6,2,4,
	 2,2 ,2,4,2,4,2,2,12
	
};

void sound(int freq)
{
	if(freq!=1000)//每个音调重新初始化
	{
		int Arr;
	
		TIM_OC_InitTypeDef sConfigOC = {0};
		Arr = 500000/freq;
		htim2.Init.Period = Arr;//改变频率来改变计数器周期
		HAL_TIM_PWM_Init(&htim2);
		sConfigOC.Pulse = Arr/4;
		sConfigOC.OCMode = TIM_OCMODE_PWM1;
  
		sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
		sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
		if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
		{
			Error_Handler();
		}
		HAL_TIM_MspPostInit(&htim2);
		HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);//定时器使能
	}
	else
		buzzer_quit();
}

void buzzer_quit()//停止定时器使能
{
	HAL_TIM_PWM_Stop(&htim2,TIM_CHANNEL_2);
}

void play_mus()//播放音乐
{
	int i;
	for(i=0;i<sizeof(yindiao);i++)
	{

			sound(tone[yindiao[i]]);
			HAL_Delay(150*dtime[i]);
			buzzer_quit();
			HAL_Delay(20);


	}
	
}

这样我们就能欣赏红尘情歌了…

猜你喜欢

转载自blog.csdn.net/qq_40215005/article/details/88633136