[51单片机学习笔记TWO]----蜂鸣器
扫描二维码
随时随地手机看文章
首先应该了解一下蜂鸣器音乐播放的原理,在这里我只讲一下电磁式蜂鸣器驱动原理(还有一种是压电式蜂鸣器):
电磁式蜂鸣器驱动原理:
蜂鸣器发声原理是电流通过电磁线圈,使电磁圈产生磁场来驱动振动膜发声的。因此需要一定的电流才能驱动它,而单片机I/O引脚输出的电压较小。单片机输出的TTLK电平基本驱动不了蜂鸣器,因需要增加一个放大电路。这里用三极管作为放大电路。下面是原理图:
我这里的J8端是跟芯片的P1^5端口相连,当P1^5输出高电平时,三极管截止,蜂鸣器不发声,反之,输出低电平时,蜂鸣器发声。
而要驱动蜂鸣器能像唱歌一样的发声,其实只要使蜂鸣器发出频率和持续时间不同的声音即可。周期等于频率的倒数,所以可以通过频率知道这段的时间,所以可以通过调用延时函数或者定时器实现,同样的发声的持续时间也可以通过延时函数实现,所以让蜂鸣器唱歌最关键的就是知道要延长多少时间!
用单片机来演奏音乐,,只要搞清楚两个概念就好了,分别是“音调”和“节拍”。
音调表示一个音符该唱的频率。
节拍表示一个音符该唱多少时间。
这里有两种方法来实现该功能:
(1)查表法这个方法复杂的地方在于你要找出每个音符相对应的频率(根据音符;频率对照表找),然后根据公式转换为相应的时间(取半周期),然后通过延时函数实现。最后编程实现。
先上代码好了:
1/***************************************************2实验名称:用蜂鸣器播放生日快乐歌3实验说明:不使用定时器中断,所有频率完全用延时实现4实验时间:2014/12/55***************************************************/67#include8#defineucharunsignedchar9#defineuintunsignedint1011sbitBEEP=P1^5;//蜂鸣器接芯片的P1^5端口1213/*生日快乐歌的音符频率表,不同频率由不同的延时来决定音符频率明显大于数组里面的值,但是因为是8位寄15存器,所以最多只能放511,但是有的频率大于511,所以只能在延时函数中乘上相应的值来接近实际乐谱频率*/17ucharcodeSONG_TONE[]=18{212,212,190,212,159,169,212,212,190,212,142,159,212,19212,106,126,159,169,190,119,119,126,159,142,159,0};2021//生日快乐歌节拍表,节拍决定每个音符的演奏长短,只是取个系数,并非准确的值22ucharcodeSONG_LONG[]=23{9,3,12,12,12,24,9,3,12,12,12,24,9,243,12,12,12,12,12,9,3,12,12,12,24,0};2526//延时27voidDelayMS(uintx)28{29uchart;30while(x--)31for(t=0;t<120;t++);32}3334//播放函数35voidPlayMusic()36{37uinti=0,j,k;38while(SONG_LONG[i]!=0"|SONG_TONE[i]!=0)39{40/*播放各个音符,SONG_LONG为拍子长度,一个节拍大概为400ms-500ms,这里的节拍又受下面一个音符的影响,所以只能根据大概的来取值*/41for(j=0;j整个流程是这样的:
首先根据生日快乐歌的乐谱将各个音调转换为相应的频率。
比如:左边是生日快乐歌乐谱,右边是音符频率转换表
这里先来了解一下乐谱的一点知识,左边乐谱数字下面有点说明是低音,没点说明就是普通的,数字上面有点就是高音,而5的低音就是4.5,高音是5.5,其他音符也是相应的道理。
乐谱的左上方有写“1=F”,而一般的乐谱都是C调,就是“1=C”,注意,乐谱里面的1234567(哆啦咪发索拉西多)相对应的不是ABCDEFG而是CDEFGAB!所以这里规定是F调的话,
那么就说明2就要唱G,3要唱A,……7要唱E,所以这里的低音5对应的应该是低音的1.5!!!!就是所谓的要相应的左移或者右移。如果还是不明白的话,看下面:
1原本对应的应该是C,4原本应该对应的是F,对吧?
然后现在1对应的变成F了,就相当于对应了4,对吧?
那么1.5对应的是什么?
4.5咯!
那2对应的是什么?
5呗!
那么好了咯,低音5是4.5,是不是就是等于1.5?所以半周期就是1803μs。
至于为什么是根据半周期算,那是因为单片机是通过循环对蜂鸣器接的端口置位,复位来使发声的,所以就是半周期。因为我用的是无源的蜂鸣器,有源的蜂鸣器就是全周期了。
然后就是按照上述道理,一个个转换,并用延时函数实现,因为每个音符的转换频率都不一样,要么使用多个延时函数一个个实现准确的音调频率,但是这样太烦,而且单片机本身就不是专门
弄来唱歌的。我们不应该为难他们,所以自己将就一下就算了。所以延时函数为了适应每个音调都有差不多的频率,这个就靠自己计算了,而且不同的歌那个值还不一样,所以这就是这个问题
的难点。
接下来的就是那个唱多久的问题,一般的歌曲默认的一个节拍是400ms-500ms。
同样的看乐谱左上方,它有写“3/4”,意思是以四分音符为节拍,每一个小结有三拍。
而在每个数字下面有一条横线,那时间就是那个节拍的时间乘上0.5,有两条就乘上0.25,三条就乘以0.125。。。音乐的基本知识就别为难我了,我是个音乐白痴。。所以我就这么理解了。。
哈哈哈哈哈~
而至于节拍转换为频率,也是有相应的表的,见下:
同样的也是通过延时函数来实现,当然也是会有误差的。而至于延时函数怎么写,见[51单片机学习笔记ONE]
编程思想的话挺简单的,就是先将音符频率和所要唱的时间转换好,放到两个数组里面。然后在主程序里面,通过延时达到相应频率,唱完一遍,停一会,接着唱就好了。
(2)用工具转码并用计时器实现先上代码好了:
1/*说明**************************************************************************2曲谱存贮格式unsignedcharcodeMusicName{音高,音长,音高,音长....,0,0};末尾:0,0表示结束(Important)34音高由三位数字组成:5个位是表示1~7这七个音符6十位是表示音符所在的音区:1-低音,2-中音,3-高音;7百位表示这个音符是否要升半音:0-不升,1-升半音。89音长最多由三位数字组成:10个位表示音符的时值,其对应关系是:11|数值(n):|0|1|2|3|4|5|612|几分音符:|1|2|4|8|16|32|64音符=2^n13十位表示音符的演奏效果(0-2):0-普通,1-连音,2-顿音14百位是符点位:0-无符点,1-有符点1516调用演奏子程序的格式17Play(乐曲名,调号,升降八度,演奏速度);18|乐曲名:要播放的乐曲指针,结尾以(0,0)结束;19|调号(0-11):是指乐曲升多少个半音演奏;20|升降八度(1-3):1:降八度,2:不升不降,3:升八度;21|演奏速度(1-12000):值越大速度越快;2223***************************************************************************/24#ifndef__SOUNDPLAY_H_REVISION_FIRST__25#define__SOUNDPLAY_H_REVISION_FIRST__2627#include2829//**************************************************************************3031#defineSYSTEM_OSC11059200//12000000//定义晶振频率12000000HZ32#defineSOUND_SPACE4/5//定义普通音符演奏的长度分率,//每4分音符间隔33sbitBeepIO=P1^5;//定义输出管脚3435unsignedintcodeFreTab[12]={262,277,294,311,330,349,369,392,415,440,466,494};//原始频率表36unsignedcharcodeSignTab[7]={0,2,4,5,7,9,11};//1~7在频率表中的位置37unsignedcharcodeLengthTab[7]={1,2,4,8,16,32,64};38unsignedcharSound_Temp_TH0,Sound_Temp_TL0;//音符定时器初值暂存39unsignedcharSound_Temp_TH1,Sound_Temp_TL1;//音长定时器初值暂存40//**************************************************************************41voidInitialSound(void)42{43BeepIO=1;44Sound_Temp_TH1=(65535-(1/1200)*SYSTEM_OSC)/256;//计算TL1应装入的初值(10ms的初装值)45Sound_Temp_TL1=(65535-(1/1200)*SYSTEM_OSC)%256;//计算TH1应装入的初值46TH1=Sound_Temp_TH1;47TL1=Sound_Temp_TL1;48TMOD|=0x11;49ET0=1;50ET1=0;51TR0=0;52TR1=0;53EA=1;54}5556voidBeepTimer0(void)interrupt1//音符发生中断57{58BeepIO=!BeepIO;59TH0=Sound_Temp_TH0;60TL0=Sound_Temp_TL0;61}62//**************************************************************************63voidPlay(unsignedchar*Sound,unsignedcharSignature,unsignedOctachord,unsignedintSpeed)64{65unsignedintNewFreTab[12];//新的频率表66unsignedchari,j;67unsignedintPoint,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;68unsignedcharTone,Length,SL,SH,SM,SLen,XG,FD;69for(i=0;i11)73{74j=j-12;75NewFreTab[i]=FreTab[j]*2;76}77else78NewFreTab[i]=FreTab[j];7980if(Octachord==1)81NewFreTab[i]>>=2;82elseif(Octachord==3)83NewFreTab[i]<<=2;84}8586SoundLength=0;87while(Sound[SoundLength]!=0x00)//计算歌曲长度88{89SoundLength+=2;90}9192Point=0;93Tone=Sound[Point];94Length=Sound[Point+1];//读出第一个音符和它时时值9596LDiv0=12000/Speed;//算出1分音符的长度(几个10ms)97LDiv4=LDiv0/4;//算出4分音符的长度98LDiv4=LDiv4-LDiv4*SOUND_SPACE;//普通音最长间隔标准99TR0=0;100TR1=1;101while(Point>=2;//低音110if(SM==3)CurrentFre<<=2;//高音111Temp_T=65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值112Sound_Temp_TH0=Temp_T/256;113Sound_Temp_TL0=Temp_T%256;114TH0=Sound_Temp_TH0;115TL0=Sound_Temp_TL0+12;//加12是对中断延时的补偿116}117SLen=LengthTab[Length%10];//算出是几分音符118XG=Length/10%10;//算出音符类型(0普通1连音2顿音)119FD=Length/100;120LDiv=LDiv0/SLen;//算出连音音符演奏的长度(多少个10ms)121if(FD==1)122LDiv=LDiv+LDiv/2;123if(XG!=1)124if(XG==0)//算出普通音符的演奏长度125if(SLen0;i--)//发规定长度的音139{140while(TF1==0);141TH1=Sound_Temp_TH1;142TL1=Sound_Temp_TL1;143TF1=0;144}145}146if(LDiv2!=0)147{148TR0=0;BeepIO=1;149for(i=LDiv2;i>0;i--)//音符间的间隔150{151while(TF1==0);152TH1=Sound_Temp_TH1;153TL1=Sound_Temp_TL1;154TF1=0;155}156}157Point+=2;158Tone=Sound[Point];159Length=Sound[Point+1];160}161BeepIO=1;162}163//**************************************************************************164#endif165166167168//挥着翅膀的女孩169unsignedcharcodeMusic_Girl[]={0x17,0x02,0x17,0x03,0x18,0x03,0x19,0x02,0x15,0x03,1700x16,0x03,0x17,0x03,0x17,0x03,0x17,0x03,0x18,0x03,1710x19,0x02,0x16,0x03,0x17,0x03,0x18,0x02,0x18,0x03,1720x17,0x03,0x15,0x02,0x18,0x03,0x17,0x03,0x18,0x02,1730x10,0x03,0x15,0x03,0x16,0x02,0x15,0x03,0x16,0x03,1740x17,0x02,0x17,0x03,0x18,0x03,0x19,0x02,0x1A,0x03,1750x1B,0x03,0x1F,0x03,0x1F,0x03,0x17,0x03,0x18,0x03,1760x19,0x02,0x16,0x03,0x17,0x03,0x18,0x03,0x17,0x03,1770x18,0x03,0x1F,0x03,0x1F,0x02,0x16,0x03,0x17,0x03,1780x18,0x03,0x17,0x03,0x18,0x03,0x20,0x03,0x20,0x02,1790x1F,0x03,0x1B,0x03,0x1F,0x66,0x20,0x03,0x21,0x03,1800x20,0x03,0x1F,0x03,0x1B,0x03,0x1F,0x66,0x1F,0x03,1810x1B,0x03,0x19,0x03,0x19,0x03,0x15,0x03,0x1A,0x66,1820x1A,0x03,0x19,0x03,0x15,0x03,0x15,0x03,0x17,0x03,1830x16,0x66,0x17,0x04,0x18,0x04,0x18,0x03,0x19,0x03,1840x1F,0x03,0x1B,0x03,0x1F,0x66,0x20,0x03,0x21,0x03,1850x20,0x03,0x1F,0x03,0x1B,0x03,0x1F,0x66,0x1F,0x03,1860x1B,0x03,0x19,0x03,0x19,0x03,0x15,0x03,0x1A,0x66,1870x1A,0x03,0x19,0x03,0x19,0x03,0x1F,0x03,0x1B,0x03,1880x1F,0x00,0x1A,0x03,0x1A,0x03,0x1A,0x03,0x1B,0x03,1890x1B,0x03,0x1A,0x03,0x19,0x03,0x19,0x02,0x17,0x03,1900x15,0x17,0x15,0x03,0x16,0x03,0x17,0x03,0x18,0x03,1910x17,0x04,0x18,0x0E,0x18,0x03,0x17,0x04,0x18,0x0E,1920x18,0x66,0x17,0x03,0x18,0x03,0x17,0x03,0x18,0x03,1930x20,0x03,0x20,0x02,0x1F,0x03,0x1B,0x03,0x1F,0x66,1940x20,0x03,0x21,0x03,0x20,0x03,0x1F,0x03,0x1B,0x03,1950x1F,0x66,0x1F,0x04,0x1B,0x0E,0x1B,0x03,0x19,0x03,1960x19,0x03,0x15,0x03,0x1A,0x66,0x1A,0x03,0x19,0x03,1970x15,0x03,0x15,0x03,0x17,0x03,0x16,0x66,0x17,0x04,1980x18,0x04,0x18,0x03,0x19,0x03,0x1F,0x03,0x1B,0x03,1990x1F,0x66,0x20,0x03,0x21,0x03,0x20,0x03,0x1F,0x03,2000x1B,0x03,0x1F,0x66,0x1F,0x03,0x1B,0x03,0x19,0x03,2010x19,0x03,0x15,0x03,0x1A,0x66,0x1A,0x03,0x19,0x03,2020x19,0x03,0x1F,0x03,0x1B,0x03,0x1F,0x00,0x18,0x02,2030x18,0x03,0x1A,0x03,0x19,0x0D,0x15,0x03,0x15,0x02,2040x18,0x66,0x16,0x02,0x17,0x02,0x15,0x00,0x00,0x00};205//同一首歌206unsignedcharcodeMusic_Same[]={0x0F,0x01,0x15,0x02,0x16,0x02,0x17,0x66,0x18,0x03,2070x17,0x02,0x15,0x02,0x16,0x01,0x15,0x02,0x10,0x02,2080x15,0x00,0x0F,0x01,0x15,0x02,0x16,0x02,0x17,0x02,2090x17,0x03,0x18,0x03,0x19,0x02,0x15,0x02,0x18,0x66,2100x17,0x03,0x19,0x02,0x16,0x03,0x17,0x03,0x16,0x00,2110x17,0x01,0x19,0x02,0x1B,0x02,0x1B,0x70,0x1A,0x03,2120x1A,0x01,0x19,0x02,0x19,0x03,0x1A,0x03,0x1B,0x02,2130x1A,0x0D,0x19,0x03,0x17,0x00,0x18,0x66,0x18,0x03,2140x19,0x02,0x1A,0x02,0x19,0x0C,0x18,0x0D,0x17,0x03,2150x16,0x01,0x11,0x02,0x11,0x03,0x10,0x03,0x0F,0x0C,2160x10,0x02,0x15,0x00,0x1F,0x01,0x1A,0x01,0x18,0x66,2170x19,0x03,0x1A,0x01,0x1B,0x02,0x1B,0x03,0x1B,0x03,2180x1B,0x0C,0x1A,0x0D,0x19,0x03,0x17,0x00,0x1F,0x01,2190x1A,0x01,0x18,0x66,0x19,0x03,0x1A,0x01,0x10,0x02,2200x10,0x03,0x10,0x03,0x1A,0x0C,0x18,0x0D,0x17,0x03,2210x16,0x00,0x0F,0x01,0x15,0x02,0x16,0x02,0x17,0x70,2220x18,0x03,0x17,0x02,0x15,0x03,0x15,0x03,0x16,0x66,2230x16,0x03,0x16,0x02,0x16,0x03,0x15,0x03,0x10,0x02,2240x10,0x01,0x11,0x01,0x11,0x66,0x10,0x03,0x0F,0x0C,2250x1A,0x02,0x19,0x02,0x16,0x03,0x16,0x03,0x18,0x66,2260x18,0x03,0x18,0x02,0x17,0x03,0x16,0x03,0x19,0x00,2270x00,0x00};228//两只蝴蝶229unsignedcharcodeMusic_Two[]={0x17,0x03,0x16,0x03,0x17,0x01,0x16,0x03,0x17,0x03,2300x16,0x03,0x15,0x01,0x10,0x03,0x15,0x03,0x16,0x02,2310x16,0x0D,0x17,0x03,0x16,0x03,0x15,0x03,0x10,0x03,2320x10,0x0E,0x15,0x04,0x0F,0x01,0x17,0x03,0x16,0x03,2330x17,0x01,0x16,0x03,0x17,0x03,0x16,0x03,0x15,0x01,2340x10,0x03,0x15,0x03,0x16,0x02,0x16,0x0D,0x17,0x03,2350x16,0x03,0x15,0x03,0x10,0x03,0x15,0x03,0x16,0x01,2360x17,0x03,0x16,0x03,0x17,0x01,0x16,0x03,0x17,0x03,2370x16,0x03,0x15,0x01,0x10,0x03,0x15,0x03,0x16,0x02,2380x16,0x0D,0x17,0x03,0x16,0x03,0x15,0x03,0x10,0x03,2390x10,0x0E,0x15,0x04,0x0F,0x01,0x17,0x03,0x19,0x03,2400x19,0x01,0x19,0x03,0x1A,0x03,0x19,0x03,0x17,0x01,2410x16,0x03,0x16,0x03,0x16,0x02,0x16,0x0D,0x17,0x03,2420x16,0x03,0x15,0x03,0x10,0x03,0x10,0x0D,0x15,0x00,2430x19,0x03,0x19,0x03,0x1A,0x03,0x1F,0x03,0x1B,0x03,2440x1B,0x03,0x1A,0x03,0x17,0x0D,0x16,0x03,0x16,0x03,2450x16,0x0D,0x17,0x01,0x17,0x03,0x17,0x03,0x19,0x03,2460x1A,0x02,0x1A,0x02,0x10,0x03,0x17,0x0D,0x16,0x03,2470x16,0x01,0x17,0x03,0x19,0x03,0x19,0x03,0x17,0x03,2480x19,0x02,0x1F,0x02,0x1B,0x03,0x1A,0x03,0x1A,0x0E,2490x1B,0x04,0x17,0x02,0x1A,0x03,0x1A,0x03,0x1A,0x0E,2500x1B,0x04,0x1A,0x03,0x19,0x03,0x17,0x03,0x16,0x03,2510x17,0x0D,0x16,0x03,0x17,0x03,0x19,0x01,0x19,0x03,2520x19,0x03,0x1A,0x03,0x1F,0x03,0x1B,0x03,0x1B,0x03,2530x1A,0x03,0x17,0x0D,0x16,0x03,0x16,0x03,0x16,0x03,2540x17,0x01,0x17,0x03,0x17,0x03,0x19,0x03,0x1A,0x02,2550x1A,0x02,0x10,0x03,0x17,0x0D,0x16,0x03,0x16,0x01,2560x17,0x03,0x19,0x03,0x19,0x03,0x17,0x03,0x19,0x03,2570x1F,0x02,0x1B,0x03,0x1A,0x03,0x1A,0x0E,0x1B,0x04,2580x17,0x02,0x1A,0x03,0x1A,0x03,0x1A,0x0E,0x1B,0x04,2590x17,0x16,0x1A,0x03,0x1A,0x03,0x1A,0x0E,0x1B,0x04,2600x1A,0x03,0x19,0x03,0x17,0x03,0x16,0x03,0x0F,0x02,2610x10,0x03,0x15,0x00,0x00,0x00};262263unsignedcharcodeMusic_birth[]={0x0F,0x03,0x0F,0x03,0x10,0x02,0x0F,0x02,0x15,0x02,0x11,0x01,0x0F,0x03,2640x0F,0x03,0x10,0x02,0x0F,0x02,0x16,0x02,0x15,0x01,0x0F,0x03,0x0F,0x03,2650x19,0x02,0x17,0x02,0x15,0x02,0x11,0x0C,0x10,0x02,0x18,0x03,0x18,0x03,2660x17,0x02,0x15,0x02,0x16,0x02,0x17,0x01,0x0F,0x02,0x0F,0x03,0x10,0x03,2670x0F,0x02,0x15,0x02,0x11,0x01,0x0F,0x03,0x0F,0x03,0x10,0x02,0x0F,0x02,2680x16,0x02,0x15,0x01,0x0F,0x03,0x0F,0x03,0x19,0x02,0x17,0x02,0x15,0x02,2690x11,0x0C,0x10,0x02,0x18,0x03,0x18,0x03,0x17,0x02,0x15,0x02,0x16,0x02,2700x10,0x01,0x00,0x00};271272voidmain()273{274275InitialSound();276277278while(1)279{280Play(Music_Girl,0,2,350);281Play(Music_Same,0,2,350);282Play(Music_Two,0,2,350);283Play(Music_birth,0,2,350);284}285}