蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。
BUZZER蜂鸣器的分类:
1、按其驱动方式的原理分,可分为:有源蜂鸣器(内含驱动线路,也叫自激式蜂鸣器)和无源蜂鸣器(外部驱动,也叫他激式蜂鸣器);
2、按构造方式的不同,可分为:电磁式蜂鸣器和压电式蜂鸣器;
3、按封装的不同,可分为:DIP BUZZER(插针蜂鸣器)和SMD BUZZER(贴片式蜂鸣器);
4、按电流的不同,可分为:直流蜂鸣器和交流蜂鸣器,其中,以直流最为常见压电式蜂鸣器,用的是压电材料,即当受到外力导致压电材料发生形变时压电材料会产生电荷。同样,当通电时压电材料会发生形变。
电磁式蜂鸣器,主要是利用通电导体会产生磁场的特性,用一个固定的永久磁铁与通电导体产生磁力推动固定在线圈上的鼓膜。
由于两种蜂鸣器发音原理不同,压电式结构简单耐用但音调单一,适用于报警器等设备。而电磁式由于音质好,所以多用于语音、音乐等设备。
笔者本次实验用到的是有源蜂鸣器与无源蜂鸣器,见下图所示:
有源蜂鸣器模块:
无源蜂鸣器模块:
有源蜂鸣器模块低电平触发,通过配置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灯的亮度,使其达到一个呼吸灯的效果。
有源蜂鸣器部分代码:(用了一颗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);
}
}
}
(声音可能刺耳,注意调节音量;声音已做过处理)
实验现象:有源蜂鸣器发声鸣叫
有源蜂鸣器
无源蜂鸣器
总结:
根据以上内容,学习有源蜂鸣器,跟LED类似还是容易理解的,给电信号驱动发声。
无源蜂鸣器主要是应用PWM使能方波,驱动发声。
针对可能出现的问题,说明一下:
(1)蜂鸣器模块的触发的电平与代码对应
(2)蜂鸣器声音小,可能是额定电压或功率不够,可适当提高电压;还可能是硬件坏了的问题,或者铜暴露出来导致的短路。
所以要有信心一步步积累理论和实践经验,一起学习加油!
扩展:可通过有源蜂鸣器可以做警报、提醒,如声光报警、人体红外等实验。无源蜂鸣器可以做闹铃、音乐等实验。那么就分享到这,大胆尝试实践探索吧,欢迎讨论。
链接: 参考PWM知乎
链接: 参考PWM视频
链接: 有源蜂鸣器视频
链接: 无源蜂鸣器视频
链接: 源码例程
提取码:3232