蜂鸣器—STM32驱动有源与无源蜂鸣器的介绍与代码示例

目录

蜂鸣器介绍

模块接线

 有源蜂鸣器

驱动代码

buzzer.h

buzzer.c

无源蜂鸣器

for循环+delay延时实现方波信号

p_buzzer.h

p_buzzer.c

main.c

定时器PWM驱动的代码

p_buzzer.h

p_buzzer.c

main.c


蜂鸣器介绍

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

蜂鸣器按其结构可分为电磁式蜂鸣器和压电式蜂鸣器两种类型。

电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳组成。压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器以及共鸣箱、外壳等组成。压电式蜂鸣器是以压电陶瓷的压电效应,来带动金属片的振动而发声;而电磁式蜂鸣器则是用电磁的原理,通电时将金属振动 膜吸下,不通电时以振动膜的弹力弹回。由于两种蜂鸣器发声原理不同,电压式结构简单耐用但音调单一、音色差,适用于报警器等设备;而电磁式由于音色好,所以多用于语音、音乐等设备。

蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器

左为有源蜂鸣器,右为无源蜂鸣器

区别

有源蜂鸣器

无源蜂鸣器

外形高度

引脚部位

黑胶封闭

绿色电路板

电压

响声

连续发声

响一次停一次

有源蜂鸣器:内部自带振荡源(LCD振荡电路),将正负极接上直流电压即可持续发声,频率固定。

无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音。

注:人耳可以听到的声音频率在20Hz~20kHz之间的声波

模块接线

vcc接工作电压,Gnd接地,信号线接单片机IO口。

GPIO口驱动能力弱,不能直接驱动无源蜂鸣器,使用用三极管开关。

有源:低电平触发就是IO口输入为0就可发声。

无源:低电平时间在一个周期内越长声音越响。

 有源蜂鸣器

 有源蜂鸣器内部包含一个振荡电路,能将恒定的直流电转化为一定频率的脉冲信号,从而实现磁场交变,带动蜂鸣器振动发音。它不需要额外的驱动电路,只要接通直流电源即可工作

TMB12A05电磁式蜂鸣器采用直流电压供电,发声频率为2.4Khz(不可改变)。

驱动代码

该模块与单色LED模块驱动代码一样,将LED改成Buzzer即可

注意:

1.蜂鸣器的触发方式         2.撕掉蜂鸣器贴纸有惊喜!!!

buzzer.h

#ifndef             _BUZZER_H_
#define				_BUZZER_H_
 
#define Buzzer_ON      0
#define Buzzer_OFF     1   
 
void Buzzer_Init(void);
 
void  Buzzer_SetON(void);
 
void  Buzzer_SetOFF(void);
 
void Buzzer_Turn(void);
#endif
 

buzzer.c

#include "stm32f10x.h"                  // Device header
#include "Buzzer.h"
 
void Buzzer_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
 
	GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//GPIO默认输出低电平
	GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)Buzzer_OFF);	//输出高电平 GPIO_SetBits(GPIOA, GPIO_Pin_0)
 
}
void  Buzzer_SetON(void)
{
	GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)Buzzer_ON);	
}
 
void  Buzzer_SetOFF(void)
{
	GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)Buzzer_OFF);
}
 
void Buzzer_Turn(void)
{
	if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_0)==Buzzer_ON)
	{
		Buzzer_SetOFF();
	}
	else
	{
		Buzzer_SetON();
	}
 
}

无源蜂鸣器

无源蜂鸣器内部不带振荡源,因此不能直接将直流电转化为声能。它需要接收 2K~5K 的方波信号才能工作,通过外部电路产生振荡信号来驱动蜂鸣器发音。通过调整输入方波信号的占空比,可以控制蜂鸣器的音量;改变输入方波信号的频率,可以控制蜂鸣器的音调(音量指声音的强弱,即声音的振动幅度;音调指声音的高低,即声音的振动频率)。

for循环+delay延时实现方波信号

乐谱

p_buzzer.h

#ifndef             _P_BUZZER_H_
#define							_P_BUZZER_H_
 
#define Buzzer_ON      0
#define Buzzer_OFF     1   
 
void Buzzer_Init(void);
 
void  Buzzer_SetON(void);
 
void  Buzzer_SetOFF(void);
 
void Buzzer_Turn(void);
void Buzzer_Work(uint16_t Freq,uint16_t Timeout,uint8_t Volume);
#endif


 

p_buzzer.c

#include "stm32f10x.h"                  // Device header
#include "p_buzzer.h"
#include "Delay.h"
void Buzzer_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
 
	GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//GPIO默认输出低电平
	GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)Buzzer_OFF);	//输出高电平 GPIO_SetBits(GPIOA, GPIO_Pin_0)
 
}
void  Buzzer_SetON(void)
{
	GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)Buzzer_ON);	
}
 
void  Buzzer_SetOFF(void)
{
	GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)Buzzer_OFF);
}
 
void Buzzer_Turn(void)
{
	if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_0)==Buzzer_ON)
	{
		Buzzer_SetOFF();
	}
	else
	{
		Buzzer_SetON();
	}
 
}

/**
  * @brief          无源蜂鸣器设置方波
  * @param      		Freq 		频率 范围:(2000~5000)hz 
										Timeout 声音持续时间 单位:ms
										Volume  音量范围:0~99
  * @retval         none				
  */
void Buzzer_Work(uint16_t Freq,uint16_t Timeout,uint8_t Volume)
{
	uint16_t i;
	uint16_t Cycle=1000000.0/Freq;				//一个周期的时间  单位us  范围(2000~5000)us
	uint16_t H_time=Volume/100.0*Cycle;		//高电平时间  	单位us
	uint16_t L_time=Cycle-H_time;					//低电平时间  	单位us
	uint16_t n=Timeout*1000/Cycle;							//多少个周期
	for(i=0;i<n;i++)
	{
		Buzzer_SetON();
		Delay_us(H_time);
		Buzzer_SetOFF();
		Delay_us(L_time);
	}
	
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Buzzer.h"

int main(void)
{

	Buzzer_Init();
	while (1)
	{
		//中音1~7
		Buzzer_Work(523,225,1);//1
		Delay_ms(5);
		Buzzer_Work(587,225,1);//2
		Delay_ms(5);
		Buzzer_Work(659,225,1);//3
		Delay_ms(5);
		Buzzer_Work(698,225,1);//4
		Delay_ms(5);
		Buzzer_Work(784,225,1);//5
		Delay_ms(5);
		Buzzer_Work(880,225,1);//6
		Delay_ms(5);
		Buzzer_Work(988,225,1);//7
		
		//小星星
		Buzzer_Work(523,225,1);//1
		Delay_ms(5);
		Buzzer_Work(523,225,1);//1
		Delay_ms(5);
		Buzzer_Work(784,225,1);//5
		Delay_ms(5);
		Buzzer_Work(784,225,1);//5
		Delay_ms(5);
		
		
		Buzzer_Work(880,225,1);//6
		Delay_ms(5);
		Buzzer_Work(880,225,1);//6
		Delay_ms(5);
		Buzzer_Work(784,225*2,1);//5
		Delay_ms(5);
		Buzzer_Work(698,225,1);//4
		Delay_ms(5);
		Buzzer_Work(698,225,1);//4
		Delay_ms(5);
		Buzzer_Work(659,225,1);//3
		Delay_ms(5);
		Buzzer_Work(659,225,1);//3
		Delay_ms(5);
		Buzzer_Work(587,225,1);//2
		Buzzer_Work(587,225,1);//2
		Buzzer_Work(523,225*2,1);//1
		Delay_ms(5);
		Buzzer_Work(784,225,1);//5
		Delay_ms(5);
		Buzzer_Work(784,225,1);//5
		Delay_ms(5);
		Buzzer_Work(698,225,1);//4
		Delay_ms(5);
		Buzzer_Work(698,225,1);//4
		Delay_ms(5);
		Buzzer_Work(659,225,1);//3
		Delay_ms(5);
		Buzzer_Work(659,225,1);//3
		Delay_ms(5);
		Buzzer_Work(587,225*2,1);//2
		Delay_ms(5);
		Buzzer_Work(784,225,1);//5
		Delay_ms(5);
		Buzzer_Work(784,225,1);//5
		Delay_ms(5);
		Buzzer_Work(698,225,1);//4
		Delay_ms(5);
		Buzzer_Work(698,225,1);//4
		Delay_ms(5);
		Buzzer_Work(659,225,1);//3
		Delay_ms(5);
		Buzzer_Work(659,225,1);//3
		Delay_ms(5);
		Buzzer_Work(587,225*2,1);//2
		Delay_ms(5);
		Buzzer_Work(523,225,1);//1
		Delay_ms(5);
		Buzzer_Work(523,225,1);//1
		Delay_ms(5);
		Buzzer_Work(784,225,1);//5
		Delay_ms(5);
		Buzzer_Work(784,225,1);//5
		Delay_ms(5);
		Buzzer_Work(880,225,1);//6
		Delay_ms(5);
		Buzzer_Work(880,225,1);//6
		Delay_ms(5);
		Buzzer_Work(784,225*2,1);//5
		Delay_ms(5);
		Buzzer_Work(698,225,1);//4
		Delay_ms(5);
		Buzzer_Work(698,225,1);//4
		Delay_ms(5);
		Buzzer_Work(659,225,1);//3
		Delay_ms(5);
		Buzzer_Work(659,225,1);//3
		Delay_ms(5);
		Buzzer_Work(587,225,1);//2
		Delay_ms(5);
		Buzzer_Work(587,225,1);//2
		Delay_ms(5);
		Buzzer_Work(523,225*2,1);//1
		Delay_ms(5);
		
	}
}

定时器PWM驱动的代码

上面代码不断for循环,接下来用定时器PWM驱动驱动无源蜂鸣器

在这之前,我尝试了定时器中断的方法,无论是改变PSC和ARR都会改变方波频率,控制频率比较简单,但是控制占空比(蜂鸣器音量)不易。

1.按照乐谱对应的psc或者arr值进入中断,在中断中反转IO口,但是进入更新中断的都是arr溢出的,无法分时间翻转。

2.1us进一次中断,分段控制IO口,但是频率是固定的,没法改变。

最终我采用定时器的PWM功能,频率和占空比改变容易

乐谱

p_buzzer.h

#ifndef       _BUZZER_H_
#define				_BUZZER_H_



void Buzzer_Init(void);

void Buzzer_Play();
void Buzzer_SetVolume(uint8_t Volume);



#endif

p_buzzer.c

#include "stm32f10x.h"                  // Device header
#include "Buzzer.h"
#include "Delay.h"

//播放速度,值为四分音符的时长(ms)
#define Speed 500

//音符对应定时器分频系数的索引,P:休止符,L:低音,M:中音,H:高音,下划线:升半音符号#
#define P	   0    
#define L1     1
#define L1_    2
#define L2     3
#define L2_    4
#define L3     5
#define L4     6
#define L4_    7
#define L5     8
#define L5_    9
#define L6    10
#define L6_   11
#define L7    12
#define M1    13
#define M1_   14
#define M2    15
#define M2_   16
#define M3    17
#define M4    18
#define M4_   19
#define M5    20
#define M5_   21
#define M6    22
#define M6_   23
#define M7    24
#define H1    25
#define H1_   26
#define H2    27
#define H2_   28
#define H3    29
#define H4    30
#define H4_   31
#define H5    32
#define H5_   33
#define H6    34
#define H6_   35
#define H7    36

//音符对应的分频系数(PSC)
uint16_t FreqBuffer[]=
{
    0,2748,2599,2449,23152182,2063,1946,1837,1735,1636,1545,1452,1377,1300,1227,1158,
    1093,1032,973,918,866,818,773,729,688,649,613,578,546,515,486,459,433,409,386,364
};

//天空之城乐谱
const uint16_t Music[]=
{
//音符,时值,
    P,	4,
	P,	4,
	P,	4,
	M6,	2,
	M7,	2,
	
	H1,	4+2,
	M7,	2,
	H1,	4,
	H3,	4,
	
	M7,	4+4+4,
	M3,	2,
	M3,	2,
	
	//2
	M6,	4+2,
	M5,	2,
	M6, 4,
	H1,	4,
	
	M5,	4+4+4,
	M3,	4,
	
	M4,	4+2,
	M3,	2,
	M4,	4,
	H1,	4,
	
	//3
	M3,	4+4,
	P,	2,
	H1,	2,
	H1,	2,
	H1,	2,
	
	M7,	4+2,
	M4_,2,
	M4_,4,
	M7,	4,
	
	M7,	8,
	P,	4,
	M6,	2,
	M7,	2,
	
	//4
	H1,	4+2,
	M7,	2,
	H1,	4,
	H3,	4,
	
	M7,	4+4+4,
	M3,	2,
	M3,	2,
	
	M6,	4+2,
	M5,	2,
	M6, 4,
	H1,	4,
	
	//5
	M5,	4+4+4,
	M2,	2,
	M3,	2,
	
	M4,	4,
	H1,	2,
	M7,	2+2,
	H1,	2+4,
	
	H2,	2,
	H2,	2,
	H3,	2,
	H1,	2+4+4,
	
	//6
	H1,	2,
	M7,	2,
	M6,	2,
	M6,	2,
	M7,	4,
	M5_,4,
	
	
	M6,	4+4+4,
	H1,	2,
	H2,	2,
	
	H3,	4+2,
	H2,	2,
	H3,	4,
	H5,	4,
	
	//7
	H2,	4+4+4,
	M5,	2,
	M5,	2,
	
	H1,	4+2,
	M7,	2,
	H1,	4,
	H3,	4,
	
	H3,	4+4+4+4,
	
	//8
	M6,	2,
	M7,	2,
	H1,	4,
	M7,	4,
	H2,	2,
	H2,	2,
	
	H1,	4+2,
	M5,	2+4+4,
	
	H4,	4,
	H3,	4,
	H3,	4,
	H1,	4,
	
	//9
	H3,	4+4+4,
	H3,	4,
	
	H6,	4+4,
	H5,	4,
	H5,	4,
	
	H3,	2,
	H2,	2,
	H1,	4+4,
	P,	2,
	H1,	2,
	
	//10
	H2,	4,
	H1,	2,
	H2,	2,
	H2,	4,
	H5,	4,
	
	H3,	4+4+4,
	H3,	4,
	
	H6,	4+4,
	H5,	4+4,
	
	//11
	H3,	2,
	H2,	2,
	H1,	4+4,
	P,	2,
	H1,	2,
	
	H2,	4,
	H1,	2,
	H2,	2+4,
	M7,	4,
	
	M6,	4+4+4,
	P,	4,
	
	0xFF	//终止标志

};

void Buzzer_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

    TIM_InternalClockConfig(TIM2);

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

    TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;  //取反PWM波形
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 50;		//CCR 默认占空比为50,音量50
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);
	
    TIM_Cmd(TIM2, ENABLE);

}


void PWM_SetPrescaler(uint16_t Prescaler)
{
	TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
}



void Buzzer_Play()
{
    static uint16_t MusicSelect=0,FreqSelect=0,TimeSelect=0;

    while(Music[MusicSelect]!=0xFF)
    {
        TIM_Cmd(TIM2, ENABLE);
        FreqSelect=Music[MusicSelect];
        PWM_SetPrescaler(FreqBuffer[FreqSelect]);

        TimeSelect=Music[++MusicSelect];
        Delay_ms(Speed/4*TimeSelect);
        MusicSelect++;

        Delay_ms(5);
    }
    if(Music[MusicSelect]==0xFF) 
    {
        MusicSelect=0;
        TIM_Cmd(TIM2, DISABLE);
    }
        


}

void Buzzer_SetVolume(uint8_t Volume)
{
	TIM_SetCompare1(TIM2, Volume);
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Buzzer.h"


int main(void)
{
    Buzzer_Init();
    Buzzer_SetVolume(1);
    while(1)
    {
        Buzzer_Play();
        Delay_ms(1000);
        Buzzer_SetVolume(99);//增大声音后再播放一次
        Buzzer_Play();
    }

}

参考手册(有源):

DATE (szlcsc.com)icon-default.png?t=O83Ahttps://atta.szlcsc.com/upload/public/pdf/source/20240528/0FE0411ABDE862370F2F0C432EA103D5.pdf

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值