蜂鸣器分为有源蜂鸣器和无源蜂鸣器。这里的“源”不是指电源,而是指震荡源。
(1)早期蜂鸣器都是无源的。
(2)内部没有震荡电路,无源蜂鸣器比有源蜂鸣器更便宜。
(3)无源蜂鸣器内部没有震荡源,需要采用一定频率的方波才可以驱动发声。
(4)通过控制方波频率可以控制蜂鸣器的音调。
(5)声音大小由硬件决定,不能通过单片机程序改变。
(6)物体振动越快,频率越高,音调越高尖。
(1)内部有震荡电路,有源蜂鸣器比无源蜂鸣器贵。
(2)只要供电就会发出声音。
(3)不能改音调。
(1)上图为无源蜂鸣器。
(2)三极管的作用是因为单片机引脚驱动能力不够,通过J8引脚控制三级管的开关。
#include
#include
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);
}
(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
#include
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;
}
(1)蜂鸣器有声音一段时间--没声音一端时间--有声音一段时间......
(2)通过调试控制音调和发声时常,无声时常,从而达到自己想要的效果。
(3)代码
/*
*功能:蜂鸣器发出滴滴声
*定时器:使用定时器0
*单片机型号:STC89C516
*/
#include
#include
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;
}
}
为什么蜂鸣器能够模拟唱歌
(1)发声音调可以改变
(2)发声长度可以改变
(3)声音的三个属性:响度、音调、音色。
由于本人没有音乐细胞,对长音短音音符这些不了解,也不想去了解,感兴趣自己百度乐谱和简谱吧。就给出如下示例代码。
/************************************************************************
*功能: 通过单片机演奏音乐(八月桂花)
*MCU:STC89C516
*晶振12MHz,12T(12分频)
**********************************************************************/
#include
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--); 各位可编译一下看看汇编结果就知道了!*/
}