特定频率激活无源蜂鸣器,发出对应音调

蜂鸣器是什么?

蜂鸣器是什么呢?相信大家在做项目中肯定多多少少都会用到蜂鸣器,蜂鸣器呢是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。比如台式电脑的主机开机会"滴"一声、洗衣机按下按键及洗衣完成都会有声响,以上这些声音都是通过蜂鸣器来发出的。

蜂鸣器按驱动方式可分为有源蜂鸣器(内含驱动线路)和无源蜂鸣器(外部驱动)。这里的“源”指的是激励源。

无源蜂鸣器内部没有激励源,只有给它一定频率的方波信号,才能让蜂鸣器的振动装置起振,从而实现发声,同时,输入的方波频率不同,发出的声音也不同(所以无源蜂鸣器可以模拟曲调实现音乐效果)。

有源蜂鸣器则不需要外部的激励源,只需要接入直流电源,即可自动发出声音(声音频率相对固定)。

由于有源蜂鸣器较为简单,只需要单片机给出高低电平即可控制其工作发声(还需借助三极管放大电路),与点亮LED很类似,所以本节就不重点讨论有源蜂鸣器,只分享如何控制无源蜂鸣器按照预设的频率发出相对应的音调。
分享一篇文章详细介绍蜂鸣器,里面介绍了蜂鸣器的种类和一些简单的硬件知识,感兴趣的可以看看,传送门:(蜂鸣器)

无源蜂鸣器工作原理


无源蜂鸣器需要1.5~2.5kHz(与蜂鸣器种类有关)的音频信号,这个音频信号即一个高低变化频率为1.5-2.5kHz的方波。实际上频率小于1.5kHz也是有声音的,只是不那么准了,可能是嘟嘟声。

单片机产生音乐音调的原理:
       音乐音调的产生主要是通过单片机的I/O口输出高低不同的脉冲信号来控制蜂鸣器发音,要想产生音频脉冲信号,需要算出某音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。利用单片机定时器计时这个半周期的时间,每当计时到后就输出脉冲的I/O口反相,这样就在此I/O口上得到此脉冲的频率。

通常,利用单片机的内部定时器0,工作在方式一下,改变计数初始值TH0和TL0来产生不同的率。

 例如,若单片机采用12MHzs晶振,要产生频率为587Hzs的音频脉冲时,其音频信号的脉冲周期T=1/587=1703.5775us,半周期时间为852us,因此总要令计时器计数=852us/1us=852,在每计数852时将I/O口反相,就得到C大调的中调Re。

 由于定时器0的在方式一计数方式为16位计数器,最多只能装载的数为2的16次方即65536个,也就是说定时器计数到65536就会进入中断函数,而在中断函数中将输出脉冲的I/O口反相即可,故只需设置好定时器0的初值就可以了发出特定的音频了。初值与音频的对应关系见下表所示:

音频

定时器初值

低1do

63628

低2re

63835

低3mi

64021

低4fa

64103

低5so

64260

低6la

64400

低7si

64524

中1do

64580

中2re

64684

中3mi

64777

中4fa

64820

中5so

64898

中6la

64968

中7si

65030

高1do

65058

高2re

65110

高3mi

65157

高4fa

65160

高5so

65217

高6la

65252

高7si

65282

如何实现无源蜂鸣器发出特定的频率呢

ps:本文使用的例程芯片是MS51FB9AE

 BEEP.H

#ifndef __BEEP__H___
#define __BEEP__H___

typedef struct __BEEP
{
  uint8_t select;
  uint8_t Music[20];
  uint8_t Stop_Index;
  uint8_t OpenBeep_Flag;               
}BEEP_DATA; 

extern BEEP_DATA BEEP_Data;  

void BEEP_GPIO_INIT(void);
void BEEP_Poll(void);
void BEEP_INIT(void);

void Timer0Init(void);

void BEEP_Start(void);
void Clear_Music_Buf(void);

void PowerON_Beep(void);
void PowerOFF_Beep(void);

#endif



BEEP_BOT.C

#include "MS51FB9AE.h"
#include "beep.h"

unsigned int code FreqTable[]={0,//停止符
//do    do#     re   re#    mi   fa    fa#   so    so#   la    la#    si   
//1	     2 		3     4     5    6      7    8      9     10    11    12  
63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64524, //低音 
//13    14    15    16    17   18    19    20     21   22    23    24  
64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030, //中音 
//25    26    27    28    29   30    31    32   33     34   35    36
65058,65085,65110,65134,65157,65178,65198,65217,65235,6525,65268,65283, //高音                  
};
/*****************************************
  * @description:
  * @param:void
  * @retval:void
  ****************************************/
void BEEP_GPIO_INIT()
{
  P05=0;P05_PUSHPULL_MODE;P05=0;//配置蜂鸣器引脚
	Timer0Init();//定时器初始化
}
/*****************************************
  * @description:
  * @param:void
  * @retval:void
  ****************************************/
void Timer0Init()
{
	ENABLE_TIMER0_MODE1;                  //Timer 0 and Timer 1 mode configuration
	
	clr_T0M;
 
	TL0 = FreqTable[BEEP_Data.select]%256;
	TH0 = FreqTable[BEEP_Data.select]/256;

    set_ET0;                                    //enable Timer0 interrupt
	set_EA;                                     //enable interrupts
	set_TR0;                                    //Timer0 run
}
/*****************************************
  * @description:
  * @param:void
  * @retval:void
  ****************************************/
void Timer0_TSR(void) interrupt 1
{ 
		if(FreqTable[BEEP_Data.select])
		{
			TL0 = FreqTable[BEEP_Data.select]%256;
			TH0 = FreqTable[BEEP_Data.select]/256;
			P05 = !P05;
		}
}

BEEP_MID.C

#include "MS51FB9AE.h"
#include "BEEP.h"

/*****************************************
  * @description:
  * @param:void
  * @retval:void
  ****************************************/
void Clear_Music_Buf(void)
{
  uint8_t i =0;
	for(i=0;i<22;i++)
	   BEEP_Data.Music[i]=0x00;

}
/*****************************************
  * @description:
  * @param:void
  * @retval:void
  ****************************************/
void BEEP_Start(void)
{
  uint8_t MusicSelect = 0x00,i=0;
	for(i=0;i<=BEEP_Data.Stop_Index;i++)
	{
		BEEP_Data.select=BEEP_Data.Music[MusicSelect++];
		delay_ms(20);
		TR0=0;
		delay_ms(5);
		TR0=1;
	}
	Clear_Music_Buf();
}

BEEP_TOP.C

#include "MS51FB9AE.h"
#include "beep.h"

BEEP_DATA BEEP_Data;  
/*****************************************
  * @description:
  * @param:void
  * @retval:void
  ****************************************/
void BEEP_INIT(void)
{
	BEEP_Data.select =0x00;
    BEEP_GPIO_INIT();
	BEEP_Data.OpenBeep_Flag=0x01;
}
/*****************************************
  * @description: 
  * @param:void
  * @retval:void
  ****************************************/
void BEEP_Poll(void)  
{

	uint8_t MusicSelect = 0x00,i=0;

	if(BEEP_Data.OpenBeep_Flag)
	{ 
		BEEP_Data.OpenBeep_Flag=0x00;
		for(i=0;i<=BEEP_Data.Stop_Index;i++)
		{
			BEEP_Data.select=BEEP_Data.Music[MusicSelect++];
			delay_ms(20);
			TR0=0;
			delay_ms(5);
			TR0=1;
		}
		Clear_Music_Buf();
	}
}
/*****************************************
  * @description:
  * @param:void
  * @retval:void
  ****************************************/
void PowerON_Beep(void)  
{
	BEEP_Data.Stop_Index=3; 
	BEEP_Data.Music[0]=13;
    BEEP_Data.Music[1]=15;
	BEEP_Data.Music[2]=17;
	BEEP_Data.Music[3]=0;
}
/*****************************************
  * @description:
  * @param:void
  * @retval:void
  ****************************************/
void PowerOFF_Beep(void)  
{
	BEEP_Data.Stop_Index=3; 
	BEEP_Data.Music[0]=17;
    BEEP_Data.Music[1]=15;
	BEEP_Data.Music[2]=13;
	BEEP_Data.Music[3]=0;
	BEEP_Start();
}

/*****************************************
  * @description:
  * @param:void
  * @retval:void
  ****************************************/
void ChangeSpeedUnit_Beep(void)  
{
    
    BEEP_Data.Stop_Index=2; 
    BEEP_Data.Music[0]=6;
    BEEP_Data.Music[1]=8;
    BEEP_Data.Music[2]=0; 	
	BEEP_Start();
}


最后在main函数中初始化蜂鸣器BEEP_INIT(),每25ms调用一次BEEP_Poll()函数,在你需要的地方填写相对用的函数即可。例如,关机的时候调用PowerOFF_Beep(),开机的时候调用PowerOn_Beep()。

物联沃分享整理
物联沃-IOTWORD物联网 » 特定频率激活无源蜂鸣器,发出对应音调

发表评论