1.蜂鳴器的的原理
1.1、無(wú)源蜂鳴器原理
(1)早期的蜂鳴器都是無(wú)源的
(2)內(nèi)部結(jié)構(gòu)和材料
(3)發(fā)聲原理:兩個(gè)金屬片靠的很近交汤,分別通正電和負(fù)電纤掸,那他們會(huì)相吸,不通電則分開(kāi)拓颓,一吸一分產(chǎn)生聲音。
(4)控制信號(hào)描孟,是高低電平相間的方波
(5)電路圖
(6)音調(diào)如何控制驶睦,音調(diào)受震動(dòng)頻率控制砰左,就等于控制信號(hào)的頻率。頻率越高音調(diào)越高场航,聽(tīng)起來(lái)越刺耳
(7)聲音大小如何控制缠导,由硬件決定的,沒(méi)法寫(xiě)代碼去控制聲音大小旗闽。
1.2酬核、有源蜂鳴器
(1)無(wú)源蜂鳴器的缺陷
(2)內(nèi)置振蕩電路后形成有源蜂鳴器
(3)有源蜂鳴器也可以用頻率信號(hào)驅(qū)動(dòng)
2.讓蜂鳴器想起來(lái)
(1)接線(xiàn)確定。P0.0接到J8上面适室。
(2)最簡(jiǎn)單:使用delay讓蜂鳴器響起來(lái)
(3)調(diào)節(jié)delay時(shí)間感受音調(diào)變化
#include <reg51.h>
sbit BUZZER = P0^0; // buzzer的驅(qū)動(dòng)引腳
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.用定時(shí)器控制蜂鳴器音調(diào)
3.1嫡意、上節(jié)delay驅(qū)動(dòng)方法的問(wèn)題
(1)不容易精準(zhǔn)控制時(shí)間
(2)CPU控制蜂鳴器中不能做其他事
3.2、定時(shí)器控制蜂鳴器響
(1)10kHZ => 1/1000s = 100us => 高電平+低電平一共100us
那么高電平和低電平的時(shí)間都是50us捣辆。所以要定的時(shí)間就是50us蔬螟。
(2)外部晶振12MHZ + 12T設(shè)置 => 內(nèi)部時(shí)鐘頻率1MHZ => 1us
#include <reg51.h>
sbit BUZZER = P1^7; // buzzer的驅(qū)動(dòng)引腳
#define XKHZ 1 // 要定多少Khz,就直接寫(xiě)這里
#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定時(shí)器
TL0 = N % 256;
TH0 = N / 256;
TR0 = 1; // T0打開(kāi)開(kāi)始計(jì)數(shù)
ET0 = 1; // T0中斷允許
EA = 1; // 總中斷允許
BUZZER = 1;
while (1);
}
4.蜂鳴器發(fā)出滴滴聲
#include <reg51.h>
sbit BUZZER = P0^0; // buzzer的驅(qū)動(dòng)引腳
#define XKHZ 4 // 要定多少Khz旧巾,就直接寫(xiě)這里
#define US (500/XKHZ)
#define N (65535-US)
unsigned int count;
unsigned char flag = 0; // flag = 0表示有聲音,flag = 1表示沒(méi)聲音
void timer0_isr(void) interrupt 1 using 1
{
TL0 = N % 256;
TH0 = N / 256;
if (count-- == 0)
{
// 說(shuō)明到了翻轉(zhuǎn)的時(shí)候了
// count = 600;
if (flag == 0)
{
// 之前是處于有聲音的忍些,說(shuō)明本次是從有聲音到無(wú)聲音的翻轉(zhuǎn)
flag = 1;
count = 600*10;
}
else
{
// 之前是處于沒(méi)聲音的鲁猩,說(shuō)明本次是從沒(méi)聲音到有聲音的翻轉(zhuǎn)
flag = 0;
BUZZER = !BUZZER;
count = 600;
}
}
else
{
// 常規(guī)情況,也就是不反轉(zhuǎn)時(shí)
if (flag == 0)
{
BUZZER = !BUZZER; // 4999次聲音
}
else
{
// 空的就可以罢坝,因?yàn)椴贿M(jìn)行任何IO操作就是沒(méi)聲音
}
}
}
void main(void)
{
TMOD = 0x01; // T0使用16bit定時(shí)器
TL0 = N % 256;
TH0 = N / 256;
TR0 = 1; // T0打開(kāi)開(kāi)始計(jì)數(shù)
ET0 = 1; // T0中斷允許
EA = 1; // 總中斷允許
BUZZER = 1;
// 設(shè)置響和不響的周期時(shí)間
count = 600; // 5000*100us = 500ms
flag = 0;
while (1);
}
5.讓蜂鳴器唱歌
5.1廓握、為什么蜂鳴器可以唱歌
(1)發(fā)聲音調(diào)可變
(2)發(fā)聲長(zhǎng)度可變
5.2、體驗(yàn)寫(xiě)好的唱歌程序
(1)復(fù)制代碼過(guò)去
(2)修改控制蜂鳴器的IO引腳定義
5.3嘁酿、代碼理解
(1)按照習(xí)慣去調(diào)好代碼風(fēng)格隙券,然后再看
(2)看的過(guò)程中嘗試修改并調(diào)試
/************************************************************************
[文件名] C51音樂(lè)程序(八月桂花)
[功能] 通過(guò)單片機(jī)演奏音樂(lè)
/**********************************************************************/
#include <REG51.H>
//#include <INTRINS.H>
//本例采用89C52, 晶振為11.0592MHZ
//關(guān)于如何編制音樂(lè)代碼, 其實(shí)十分簡(jiǎn)單,各位可以看以下代碼.
//頻率常數(shù)即音樂(lè)術(shù)語(yǔ)中的音調(diào),而節(jié)拍常數(shù)即音樂(lè)術(shù)語(yǔ)中的多少拍;
//所以拿出譜子, 試探編吧!
sbit Beep = P0^0 ; // 要根據(jù)實(shí)際的接線(xiàn)來(lái)修改
unsigned char n = 0; //n為節(jié)拍常數(shù)變量
unsigned char code music_tab[] =
{
0x18, 0x30, 0x1C , 0x10, //格式為: 頻率常數(shù), 節(jié)拍常數(shù), 頻率常數(shù), 節(jié)拍常數(shù),
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定時(shí)控制的是音樂(lè)的節(jié)拍(某一個(gè)音節(jié)持續(xù)的時(shí)間)而不管音調(diào)(頻率)
// 音調(diào)是直接使用delay做出來(lái)的。
void int0() interrupt 1 //采用中斷0 控制節(jié)拍
{
TH0 = 0xd8;
TL0 = 0xef;
n--;
}
void delay (unsigned char m) //控制頻率延時(shí)
{
unsigned i = 3 * m;
while (--i);
}
void delayms(unsigned char a) //豪秒延時(shí)子程序
{
while (--a); //采用while(--a) 不要采用while(a--); 各位可編譯一下看看匯編結(jié)果就知道了!
}
void main()
{
unsigned char p, m; // m為頻率常數(shù)變量
unsigned char i = 0;
TMOD &= 0x0f;
TMOD |= 0x01; // timer0 工作在模式1闹司,16位定時(shí)器下
TH0 = 0xd8;
TL0 = 0xef; // 這個(gè)TH和TL的值合起來(lái)定了1個(gè)10ms左右的一個(gè)時(shí)間
IE = 0x82;
play:
while (1)
{
a: p = music_tab[i];
if (p == 0x00) // 一遍播放完了娱仔,延時(shí)1s后自動(dòng)開(kāi)始下一遍
{
i=0, delayms(1000);
goto play;
} //如果碰到結(jié)束符,延時(shí)1秒,回到開(kāi)始再來(lái)一遍
else if (p == 0xff)
{
i = i + 1;
delayms(100), TR0 = 0;
goto a;
} //若碰到休止符,延時(shí)100ms,繼續(xù)取下一音符
else
{
m = music_tab[i++], n = music_tab[i++];
} // m取頻率常數(shù) 和 n取節(jié)拍常數(shù)
TR0 = 1; //開(kāi)定時(shí)器1
while (n != 0)
{
Beep = ~Beep;
delay(m); //等待節(jié)拍完成, 通過(guò)P1口輸出音頻(可多聲道哦!)
}
TR0 = 0; //關(guān)定時(shí)器1
}
}