【STM32 基础实验蜂鸣器发声】

一、认识蜂鸣器

(1)蜂鸣器

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。

(2)蜂鸣器分类

BUZZER蜂鸣器的分类:
1、按其驱动方式的原理分,可分为:有源蜂鸣器(内含驱动线路,也叫自激式蜂鸣器)和无源蜂鸣器(外部驱动,也叫他激式蜂鸣器);
2、按构造方式的不同,可分为:电磁式蜂鸣器压电式蜂鸣器
3、按封装的不同,可分为:DIP BUZZER(插针蜂鸣器)和SMD BUZZER(贴片式蜂鸣器);
4、按电流的不同,可分为:直流蜂鸣器交流蜂鸣器,其中,以直流最为常见压电式蜂鸣器,用的是压电材料,即当受到外力导致压电材料发生形变时压电材料会产生电荷。同样,当通电时压电材料会发生形变。
电磁式蜂鸣器,主要是利用通电导体会产生磁场的特性,用一个固定的永久磁铁与通电导体产生磁力推动固定在线圈上的鼓膜。
由于两种蜂鸣器发音原理不同,压电式结构简单耐用但音调单一,适用于报警器等设备。而电磁式由于音质好,所以多用于语音、音乐等设备。

二、基于stm32f10c8t6 基础实验蜂鸣器发声

(1)本实验蜂鸣器型号说明

笔者本次实验用到的是有源蜂鸣器与无源蜂鸣器,见下图所示:
有源蜂鸣器模块:
无源蜂鸣器模块:

(2)蜂鸣器发声原理

有源蜂鸣器模块低电平触发,通过配置I/O口,给它低电平即可发声。可见电路图如下:
有源蜂鸣器电路图:
无源蜂鸣器模块,通过配置方波,方波的话可以联想到PWM,使配置PWM占空比、频率即可驱动发声。可见电路图如下:
无源蜂鸣器电路图:

然后了解一下PWM
我们就以以STM32单片机为例,其IO口只能输出高电平和低电平。

假设高电平为5V、低电平则为0V,那么要输出不同的模拟电压就要用到PWM。通过改变IO口输出的方波的占空比,从而获得使用数字信号模拟成的模拟电压信号。

电压是以一种脉冲序列被加到模拟负载上去的,接通时是高电平1,断开时是低电平0。接通时直流供电输出,断开时直流供电断开。通过对接通和断开时间的控制,理论上来讲,可以输出任意不大于最大电压值5V的模拟电压。

比方说,占空比为50%那就是高电平时间一半,低电平时间一半。在一定的频率下,就可以得到模拟的2.5V输出电压。那么75%的占空比,得到的电压就是3.75V,如下图所示。

在这里插入图片描述

也就是说,在一定的频率下,通过不同的占空比即可得到不同大小的输出模拟电压,PWM就是通过这种原理实现数字模拟信号转换的。

PWM应用
以经常使用的呼吸灯举例。
LED呼吸灯本次实验也使用了一颗LED来实现呼吸灯,衬托无源蜂鸣器的实验现象,

一般人眼睛对于80Hz以上刷新频率则完全没有闪烁感,那么我们平时见到的LED灯,当它的频率大于50Hz的时候,人眼就会产生视觉暂留效果,基本就看不到闪烁了,而是误以为是一个常亮的LED灯。

由于频率很高时看不到闪烁,占空比越大LED越亮,占空比越小LED越暗。所以,在频率一定时,可以用不同占空比改变LED灯的亮度,使其达到一个呼吸灯的效果。

(3)代码部分

有源蜂鸣器部分代码:(用了一颗LED循环闪烁,表示正在跑程序)
beep.c

#include "sys.h"
#include "beep.h"

void BEEP_Init(void)
 {
	GPIO_InitTypeDef  GPIO_InitStructure;//声明结构体——GPIO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//时钟使能GPIOB
	 //RCC APB2PeriphClockcmd(RCC APB2Periph GPIOB | RCC APB2Periph AFIO,ENABLE); 
	 //GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;//定义引脚pin_8 
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出模式
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//频率50Mhz
	GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIOB
	GPIO_SetBits(GPIOB,GPIO_Pin_8);//低电平触发所以置位高电平
 }
 

main.c

#include "stm32f10x.h"
#include "beep.h"
#include "delay.h"
#include "led.h"

int main()
{
	BEEP_Init();
	delay_init();	
	LED_Init();
	
	while(1)
	{

	  shansuo();
		GPIO_SetBits(GPIOB,GPIO_Pin_8);  
		delay_ms(500);
		GPIO_ResetBits(GPIOB,GPIO_Pin_8); 
		delay_ms(500);
		
	}
}



// An highlighted block
var foo = 'bar';

无源蜂鸣器部分代码:(用了一颗LED循环呼吸灯,表示正在跑程序)
pwm.c

#include "stm32f10x.h"


void PWM_Init(void)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;//输出比较的结构体
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//时钟使能GPIOA
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);  //复用时开启
	//GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE); //重映射
	//GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //解除PA15调试功能
	

	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_7;//定义引脚pin_0|Pin_15
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出模式,改变引脚控制权给片上外设
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//频率50Mhz
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	
	TIM_InternalClockConfig(TIM2);
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitStructure.TIM_ClockDivision =TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInitStructure.TIM_Period = 100-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到20为2ms  //ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720-1; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  //psc
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	
	TIM_OCStructInit(&TIM_OCInitStructure);//用StructInit赋初始值函数,可避免语法错误
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出比较的模式
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出比较的极性
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出比较的使能
	TIM_OCInitStructure.TIM_Pulse = 0;//输出比较配置CCR条件码寄存器  //占空比50%  占空比10%   占空比90%  
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);//查看引脚定义表知道,非重映射默认只有PA0输出
	TIM_OC2Init(TIM3,&TIM_OCInitStructure);
	

	
	/*公式:PWM频率:Freq = CK_PSC/(PSC+1)/(ARR+1)
					PWM占空比:Doty = CCR/(ARR+1)
					PWM分辨率:Reso = 1/(ARR+1)   */
  TIM_Cmd(TIM2, ENABLE);  //使能TIMx外设
	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
							 
}

void PWM_SetCompare1(uint16_t Compare1)//单独更改通道1的值对应TIM_OC1Init ,从而改变CCR实现占空比变化
{
	TIM_SetCompare1(TIM2, Compare1);
	
}

void PWM_SetCompare2(uint16_t Compare2)//单独更改通道1的值对应TIM_OC2Init ,从而改变CCR实现占空比变化
{
	TIM_SetCompare2(TIM3, Compare2);
	
}


main.c

#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "pwm.h"

uint8_t i;

int main(void)
{	
	
	delay_init();	    	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	PWM_Init();
	
	
	while(1)
	{
		for(i=0;i<=100;i++)
		{
			PWM_SetCompare1(i);
			PWM_SetCompare2(i);
			delay_ms(20);
		}
		for(i=0;i<=100;i++)
		{
			PWM_SetCompare1(100-i);
			PWM_SetCompare2(100-i);
			delay_ms(20);
		}
	}
}

(4)效果展示

(声音可能刺耳,注意调节音量;声音已做过处理)
实验现象:有源蜂鸣器发声鸣叫

有源蜂鸣器


实验现象:无源蜂鸣器发声鸣叫

无源蜂鸣器

三、总结与扩展

总结:
根据以上内容,学习有源蜂鸣器,跟LED类似还是容易理解的,给电信号驱动发声。
无源蜂鸣器主要是应用PWM使能方波,驱动发声。
针对可能出现的问题,说明一下:
(1)蜂鸣器模块的触发的电平与代码对应
(2)蜂鸣器声音小,可能是额定电压或功率不够,可适当提高电压;还可能是硬件坏了的问题,或者铜暴露出来导致的短路。
所以要有信心一步步积累理论和实践经验,一起学习加油!
扩展:可通过有源蜂鸣器可以做警报、提醒,如声光报警、人体红外等实验。无源蜂鸣器可以做闹铃、音乐等实验。那么就分享到这,大胆尝试实践探索吧,欢迎讨论。

附上参考文献链接与视频链接出处

链接: 参考PWM知乎
链接: 参考PWM视频
链接: 有源蜂鸣器视频
链接: 无源蜂鸣器视频
链接: 源码例程
提取码:3232

  • 66
    点赞
  • 401
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要使用STM32PWM控制蜂鸣器播放音乐,可以按照以下步骤进行设置: 1. 首先需要确定蜂鸣器的频率范围,以便设置PWM的频率范围。一般来说,蜂鸣器的频率范围在几十赫兹到几千赫兹之间。 2. 设置PWM的频率和占空比。对于每个音符,需要设置一个特定的频率和持续时间。可以使用定时器来控制PWM的频率,并使用占空比来控制音符的持续时间。 3. 为音乐编写一个简单的程序,可以使用数组来存储每个音符的频率和持续时间。然后,在主程序中,使用定时器和PWM来播放这些音符,直到音乐结束。 以下是一个简单的示例程序,可以使用STM32PWM控制蜂鸣器播放音乐: ``` #include "stm32f10x.h" // 定义PWM的频率范围和占空比 #define PWM_FREQ_MIN 50 #define PWM_FREQ_MAX 10000 #define PWM_DUTY_CYCLE 50 // 定义音乐数组 uint16_t music[] = {262, 294, 330, 349, 392, 440, 494, 523}; uint16_t duration[] = {500, 500, 500, 500, 500, 500, 500, 500}; uint8_t music_len = 8; // 初始化PWM void PWM_init(void) { // 启动定时器2 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_TimeBaseInitStruct.TIM_Prescaler = 0; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_Period = SystemCoreClock / PWM_FREQ_MAX; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); // 配置PWM输出 TIM_OCInitTypeDef TIM_OCInitStruct; TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStruct.TIM_Pulse = (SystemCoreClock / PWM_FREQ_MAX) * PWM_DUTY_CYCLE / 100; TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM2, &TIM_OCInitStruct); // 启动PWM TIM_Cmd(TIM2, ENABLE); } // 播放音乐 void play_music(void) { int i; for (i = 0; i < music_len; i++) { // 设置PWM的频率和持续时间 TIM2->ARR = SystemCoreClock / music[i]; TIM2->CCR1 = (SystemCoreClock / music[i]) * PWM_DUTY_CYCLE / 100; // 延时 uint32_t j; for (j = 0; j < duration[i]; j++); // 停止PWM TIM2->CCR1 = 0; } } int main(void) { // 初始化PWM PWM_init(); // 播放音乐 play_music(); while (1); } ``` 在这个示例程序中,定义了一个音乐数组,包含了8个音符的频率和持续时间。然后在主程序中,使用PWM来播放这些音符,直到音乐结束。在初始化PWM时,使用定时器2来控制PWM的频率,并设置占空比为50%。在播放音乐时,根据音符的频率和持续时间,调整PWM的频率和占空比。最后,程序进入死循环,保持PWM输出。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值