1.蜂鸣器的的原理
1.1、无源蜂鸣器原理
(1)早期的蜂鸣器都是无源的
(2)内部结构和材料
(3)发声原理:两个金属片靠的很近,分别通正电和负电,那他们会相吸,不通电则分开,一吸一分产生声音。
(4)控制信号,是高低电平相间的方波
(5)电路图
蜂鸣器电路图
(6)音调如何控制,音调受震动频率控制,就等于控制信号的频率。频率越高音调越高,听起来越刺耳
(7)声音大小如何控制,由硬件决定的,没法写代码去控制声音大小。
1.2、有源蜂鸣器
(1)无源蜂鸣器的缺陷
(2)内置振荡电路后形成有源蜂鸣器
(3)有源蜂鸣器也可以用频率信号驱动
2.让蜂鸣器想起来
(1)接线确定。P0.0接到J8上面。
(2)最简单:使用delay让蜂鸣器响起来
(3)调节delay时间感受音调变化
#include
sbit BUZZER = P0^0; // buzzer的驱动引脚
void delay(void)
{
unsigned char i, j;
for (i=0; i<5; i++)
for (j=0; j<5; j++);
}
void main(void)
{
while (1)
{
BUZZER = 1;
delay();
BUZZER = 0;
delay();
}
}
3.用定时器控制蜂鸣器音调
3.1、上节delay驱动方法的问题
(1)不容易精准控制时间
(2)CPU控制蜂鸣器中不能做其他事
3.2、定时器控制蜂鸣器响
(1)10kHZ => 1/1000s = 100us => 高电平+低电平一共100us
那么高电平和低电平的时间都是50us。所以要定的时间就是50us。
(2)外部晶振12MHZ + 12T设置 => 内部时钟频率1MHZ => 1us
#include
sbit BUZZER = P1^7; // buzzer的驱动引脚
#define XKHZ 1 // 要定多少Khz,就直接写这里
#define US (500/XKHZ) // 1000hz除以2,高低电平各一半
#define N (65535-US)
void timer0_isr(void) interrupt 1 using 1
{
TL0 = N % 256; // 低8位
TH0 = N / 256; // 高8位
BUZZER = !BUZZER;
}
void main(void)
{
TMOD = 0x01; // T0使用16bit定时器
TL0 = N % 256;
TH0 = N / 256;
TR0 = 1; // T0打开开始计数
ET0 = 1; // T0中断允许
EA = 1; // 总中断允许
BUZZER = 1;
while (1);
}
4.蜂鸣器发出滴滴声
#include
sbit BUZZER = P0^0; // buzzer的驱动引脚
#define XKHZ 4 // 要定多少Khz,就直接写这里
#define US (500/XKHZ)
#define N (65535-US)
unsigned int count;
unsigned char flag = 0; // flag = 0表示有声音,flag = 1表示没声音
void timer0_isr(void) interrupt 1 using 1
{
TL0 = N % 256;
TH0 = N / 256;
if (count-- == 0)
{
// 说明到了翻转的时候了
// count = 600;
if (flag == 0)
{
// 之前是处于有声音的,说明本次是从有声音到无声音的翻转
flag = 1;
count = 600*10;
}
else
{
// 之前是处于没声音的,说明本次是从没声音到有声音的翻转
flag = 0;
BUZZER = !BUZZER;
count = 600;
}
}
else
{
// 常规情况,也就是不反转时
if (flag == 0)
{
BUZZER = !BUZZER; // 4999次声音
}
else
{
// 空的就可以,因为不进行任何IO操作就是没声音
}
}
}
void main(void)
{
TMOD = 0x01; // T0使用16bit定时器
TL0 = N % 256;
TH0 = N / 256;
TR0 = 1; // T0打开开始计数
ET0 = 1; // T0中断允许
EA = 1; // 总中断允许
BUZZER = 1;
// 设置响和不响的周期时间
count = 600; // 5000*100us = 500ms
flag = 0;
while (1);
}
5.让蜂鸣器唱歌
5.1、为什么蜂鸣器可以唱歌
(1)发声音调可变
(2)发声长度可变
5.2、体验写好的唱歌程序
(1)复制代码过去
(2)修改控制蜂鸣器的IO引脚定义
5.3、代码理解
(1)按照习惯去调好代码风格,然后再看
(2)看的过程中尝试修改并调试
/************************************************************************
[文件名] C51音乐程序(八月桂花)
[功能] 通过单片机演奏音乐
/**********************************************************************/
#include
//#include
//本例采用89C52, 晶振为11.0592MHZ
//关于如何编制音乐代码, 其实十分简单,各位可以看以下代码.
//频率常数即音乐术语中的音调,而节拍常数即音乐术语中的多少拍;
//所以拿出谱子, 试探编吧!
sbit Beep = P0^0 ; // 要根据实际的接线来修改
unsigned char n = 0; //n为节拍常数变量
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
};
// T0定时控制的是音乐的节拍(某一个音节持续的时间)而不管音调(频率)
// 音调是直接使用delay做出来的。
void int0() interrupt 1 //采用中断0 控制节拍
{
TH0 = 0xd8;
TL0 = 0xef;
n--;
}
void delay (unsigned char m) //控制频率延时
{
unsigned i = 3 * m;
while (--i);
}
void delayms(unsigned char a) //豪秒延时子程序
{
while (--a); //采用while(--a) 不要采用while(a--); 各位可编译一下看看汇编结果就知道了!
}
void main()
{
unsigned char p, m; // m为频率常数变量
unsigned char i = 0;
TMOD &= 0x0f;
TMOD |= 0x01; // timer0 工作在模式1,16位定时器下
TH0 = 0xd8;
TL0 = 0xef; // 这个TH和TL的值合起来定了1个10ms左右的一个时间
IE = 0x82;
play:
while (1)
{
a: p = music_tab[i];
if (p == 0x00) // 一遍播放完了,延时1s后自动开始下一遍
{
i=0, delayms(1000);
goto play;
} //如果碰到结束符,延时1秒,回到开始再来一遍
else if (p == 0xff)
{
i = i + 1;
delayms(100), TR0 = 0;
goto a;
} //若碰到休止符,延时100ms,继续取下一音符
else
{
m = music_tab[i++], n = music_tab[i++];
} // m取频率常数 和 n取节拍常数
TR0 = 1; //开定时器1
while (n != 0)
{
Beep = ~Beep;
delay(m); //等待节拍完成, 通过P1口输出音频(可多声道哦!)
}
TR0 = 0; //关定时器1
}
}