八、51单片机之蜂鸣器

1、蜂鸣器的原理

蜂鸣器分为有源蜂鸣器和无源蜂鸣器。这里的“源”不是指电源,而是指震荡源。

1.1、无源蜂鸣器

(1)早期蜂鸣器都是无源的。

(2)内部没有震荡电路,无源蜂鸣器比有源蜂鸣器更便宜。

(3)无源蜂鸣器内部没有震荡源,需要采用一定频率的方波才可以驱动发声。

(4)通过控制方波频率可以控制蜂鸣器的音调。

(5)声音大小由硬件决定,不能通过单片机程序改变。

(6)物体振动越快,频率越高,音调越高尖。

1.2、有源蜂鸣器

(1)内部有震荡电路,有源蜂鸣器比无源蜂鸣器贵。

(2)只要供电就会发出声音。

(3)不能改音调。

2、原理图

(1)上图为无源蜂鸣器。

(2)三极管的作用是因为单片机引脚驱动能力不够,通过J8引脚控制三级管的开关。

3、示例代码

3.1、让无源蜂鸣器响起来

#include <reg52.h>
#include <intrins.h>

sbit BUZZER = P0^0;   /*无源蜂鸣器驱动引脚*/ 

void Delay100us();

void main()
{
	
	while(1)
	{
		/*人耳听力频率范围为20Hz~20000Hz*/
		Delay100us();       /*频率 = 1/200uS = 0.005MHZ = 5KHz*/
		BUZZER = !BUZZER;
	}
}

void Delay100us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	i = 47;
	while (--i);
}

3.2、定时器控制蜂鸣器音调

(1)采用软件延时控制无源蜂鸣器的弊端:

不易精准控制时间;CPU控制蜂鸣器中不能做其他事。

(2)使蜂鸣器在100KHz发声

外部晶振12MHz + 12T设置 => 内部时钟频率1MHz => 时钟周期1uS;

10KHz => 1/10000s => 100us =>高电平+低电平一共100us,那高电平和低电平的时间都是50us,所以要定的时间就是50us。

(3)蜂鸣器音调与TH0、TL0寄存器值有关,如需经常修改音调,可写成宏定义。

例如:

#defien TONE    10000 Hz                                    /*宏定义音调频率*/

#define TimingLength  (1/TONE) *1000000 / 2      /*定时时长uS*/

TH0  =  (TimingLength + 1) / 256 

TL0  =  (TimingLength + 1) % 256 

TH0 = us /256

(4)代码

/*
 *功能:定时器控制蜂鸣器音调
 *定时器:使用定时器0
 *单片机型号:STC89C516
 */
#include <reg52.h>
#include <intrins.h>


sbit BUZZER = P0^0;     /*无源蜂鸣器驱动引脚*/ 


/*函数声明*/
void Timer0Init(void);   /*定时器0初始化,50uS*/


void main()
{
	Timer0Init();
	ET0 = 1;    //打开T0溢出中断
	EA = 1;     //打开总中断
	
	while(1)
	{
		
	}
}


/*
 *功能: 定时器0初始化,50uS
 */
void Timer0Init(void)		//50微秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式,16位定时器/计数器,TL0、TH0全用,工作在定时器模式下
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xCE;		    //设置定时初始值  0xFF-50+1 = 206 = 0xCE
	TH0 = 0xFF;		    //设置定时初始值
	TF0 = 0;		    //定时器溢出标志,清除TF0标志,
	TR0 = 1;		    //定时器运行控制位,定时器0开始计数
}


/*
 *功能:定时器0中断处理函数
 */
void tm0_isr() interrupt 1 using 1
{
	TL0 = 0xCE;		   /*手工重载计数值*/ 
	TH0 = 0xFF;		 
	BUZZER = !BUZZER;
}
 

3.3、蜂鸣器发出滴滴声

(1)蜂鸣器有声音一段时间--没声音一端时间--有声音一段时间......

(2)通过调试控制音调和发声时常,无声时常,从而达到自己想要的效果。

(3)代码

/*
 *功能:蜂鸣器发出滴滴声
 *定时器:使用定时器0
 *单片机型号:STC89C516
 */
#include <reg52.h>
#include <intrins.h>


sbit BUZZER = P0^0;     /*无源蜂鸣器驱动引脚*/ 
unsigned int count = 0;



/*函数声明*/
void Timer0Init(void);   /*定时器0初始化,50uS*/


void main()
{
	Timer0Init();
	ET0 = 1;    //打开T0溢出中断
	EA = 1;     //打开总中断
	
	while(1)
	{
		
	}
}


/*
 *功能: 定时器0初始化,50uS
 */
void Timer0Init(void)		//50毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式,16位定时器/计数器,TL0、TH0全用,工作在定时器模式下
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xCE;		    //设置定时初始值  0xFF-50+1 = 206 = 0xCE
	TH0 = 0xFF;		    //设置定时初始值
	TF0 = 0;		    //定时器溢出标志,清除TF0标志,
	TR0 = 1;		    //定时器运行控制位,定时器0开始计数
}


/*
 *功能:定时器0中断处理函数
 */
void tm0_isr() interrupt 1 using 1
{
	TL0 = 0xCE;		   /*手工重载计数值*/ 
	TH0 = 0xFF;	
	count++;
	if(count <= 4000)   
	{
		BUZZER = !BUZZER;
	}
	else if(count>6000 )
	{
		/*count = 4001~6000没声音*/
		count = 0;
	}
	
	
}
 

3.4、让蜂鸣器唱歌

为什么蜂鸣器能够模拟唱歌

(1)发声音调可以改变

(2)发声长度可以改变

(3)声音的三个属性:响度、音调、音色。

由于本人没有音乐细胞,对长音短音音符这些不了解,也不想去了解,感兴趣自己百度乐谱和简谱吧。就给出如下示例代码。

/************************************************************************  
 *功能: 通过单片机演奏音乐(八月桂花)  
 *MCU:STC89C516
 *晶振12MHz,12T(12分频) 
 **********************************************************************/   
#include <reg52.h>        


sbit BUZZER =  P0^0;     /*无源蜂鸣器驱动引脚*/
unsigned char beat = 0;  /*beat为节拍常数变量*/
/*频率常数即音乐术语中的音调,而节拍常数即音乐术语中的多少拍
 *格式为:频率常数, 节拍常数, 频率常数, 节拍常数......
 */ 
unsigned char code music_tab[] =
{   
	0x18, 0x30, 0x1C, 0x10, 0x20, 0x40, 0x1C, 0x10,   
	0x18, 0x10, 0x20, 0x10, 0x1C, 0x10, 0x18, 0x40,   
	0x1C, 0x20, 0x20, 0x20, 0x1C, 0x20, 0x18, 0x20,   
	0x20, 0x80, 0xFF, 0x20, 0x30, 0x1C, 0x10, 0x18,   
	0x20, 0x15, 0x20, 0x1C, 0x20, 0x20, 0x20, 0x26,   
	0x40, 0x20, 0x20, 0x2B, 0x20, 0x26, 0x20, 0x20,   
	0x20, 0x30, 0x80, 0xFF, 0x20, 0x20, 0x1C, 0x10,   
	0x18, 0x10, 0x20, 0x20, 0x26, 0x20, 0x2B, 0x20,   
	0x30, 0x20, 0x2B, 0x40, 0x20, 0x20, 0x1C, 0x10,   
	0x18, 0x10, 0x20, 0x20, 0x26, 0x20, 0x2B, 0x20,   
	0x30, 0x20, 0x2B, 0x40, 0x20, 0x30, 0x1C, 0x10,   
	0x18, 0x20, 0x15, 0x20, 0x1C, 0x20, 0x20, 0x20,   
	0x26, 0x40, 0x20, 0x20, 0x2B, 0x20, 0x26, 0x20,   
	0x20, 0x20, 0x30, 0x80, 0x20, 0x30, 0x1C, 0x10,   
	0x20, 0x10, 0x1C, 0x10, 0x20, 0x20, 0x26, 0x20,   
	0x2B, 0x20, 0x30, 0x20, 0x2B, 0x40, 0x20, 0x15,   
	0x1F, 0x05, 0x20, 0x10, 0x1C, 0x10, 0x20, 0x20,   
	0x26, 0x20, 0x2B, 0x20, 0x30, 0x20, 0x2B, 0x40,   
	0x20, 0x30, 0x1C, 0x10, 0x18, 0x20, 0x15, 0x20,   
	0x1C, 0x20, 0x20, 0x20, 0x26, 0x40, 0x20, 0x20,   
	0x2B, 0x20, 0x26, 0x20, 0x20, 0x20, 0x30, 0x30,   
	0x20, 0x30, 0x1C, 0x10, 0x18, 0x40, 0x1C, 0x20,   
	0x20, 0x20, 0x26, 0x40, 0x13, 0x60, 0x18, 0x20,   
	0x15, 0x40, 0x13, 0x40, 0x18, 0x80, 0x00   
};   


/*函数声明*/ 
void delay_Hz (unsigned char t);  /*控制频率延时*/  
void delayms(unsigned char t);    /*毫秒延时子程序*/

   
void main()   
{ 
  unsigned char p,m;   /*m为频率常数变量*/    
  unsigned char i=0;   
  TMOD &= 0x0f;   
  TMOD |= 0x01;   
  TH0 = 0xd8;
  TL0 = 0xef;   
  IE = 0x82;
	
play:   
  while(1) 
  {
a: 
    p = music_tab[i];   
    if(p == 0x00)     /*如果碰到结束符,延时1秒,回到开始再来一遍*/     
	{ 
	  i=0;
	  delayms(1000); 
	  goto play;
	}      
	else if(p==0xff)  /*若碰到休止符,延时100ms,继续取下一音符*/  
	{ 
	  i=i+1;
	  delayms(100);
	  TR0=0; 
	  goto a;
	}    
    else             /*取频率常数和节拍常数*/    
	{
	  m=music_tab[i++];
      beat=music_tab[i++];
	}      
    TR0=1;                            /*开定时器0*/    
    while(beat != 0)                  /*等待节拍完成*/
    {
      BUZZER = !BUZZER;
      delay_Hz(m);                    /*m控制频率*/ 
    }           
    TR0=0;                            /*关定时器0*/
  }		 
}  


/*采用中断0 控制节拍*/
void tim0_isr()  interrupt 1      
{  
  TH0=0xd8;      /*手工重载计数值*/  
  TL0=0xef;   
  beat--;        /*控制节拍*/  
}   
  

/*控制频率延时*/
void delay_Hz (unsigned char t)       
{   
  unsigned i=3*t;   
  while(--i);   
}   


/*毫秒延时子程序*/
void delayms(unsigned char t)      
{   
  while(--t);     /*采用while(--a) 不要采用while(a--); 各位可编译一下看看汇编结果就知道了!*/    
}

  • 13
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码织梦师小猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值