欢迎大家来到IT世界,在知识的湖畔探索吧!
1. 基于proteus的51单片机开发实例(3)–简易电子琴
简易电子琴电路
1.1. 实验目的
本实例将让我们了解使用51单片机来实现简易电子琴的设计,本例中使用蜂鸣器来模拟发出乐音,通过按下不同的按键,发出“do、re、mi、fa、so、la、ti、do”的音符,并且还可以通过播放键播放一小段音乐。
1.2. 设计思路
本实例涉及到以下内容:
1、发声器件的选择–蜂鸣器,如何使用51单片机控制蜂鸣器发出我们想要的各种声音;
2、如何编写基本音符的编程代码;
3、如何控制不同的按键发出不同的音符声音。
4、单片机端口如何驱动大电流器件。
1.3. 基础知识
1.3.1. 蜂鸣器的基础知识
本实例中我们使用蜂鸣器作为发出各种声音的器件。下面就来了解一下蜂鸣器的相关知识。
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
根据工作原理,蜂鸣器分为有源蜂鸣器(又称为压电式蜂鸣器)和无源蜂鸣器(又称电磁式蜂鸣器)两种。图1所示为有源蜂鸣器。图2所示为无源蜂鸣器。
图1 无源蜂鸣器
图2 有源蜂鸣器
有源或者无源蜂鸣器中的“源”不是指的电源,而是指振荡源。有源蜂鸣器和无源蜂鸣器的最大区别是有源蜂鸣器只需要在蜂鸣器的两端加上固定的电压差,它就可以发声了,而无源蜂鸣器必须在其两端加上一定频率的振荡信号,它才能够发声。
1.有源蜂鸣器(压电式蜂鸣器)主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。
多谐振荡器由晶体管或集成电路构成。当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1500~2500HZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。
2.电磁式蜂鸣器(无源蜂鸣器)主要由由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
一般情况下,蜂鸣器发声时需要比较大的电流(一般要大于10mA),而单片机端口的驱动能力是有限的(一般小于10mA),所以需要设计专门的驱动电路来驱动蜂鸣器。本例中使用三极管来驱动蜂鸣器。
图3是典型的蜂鸣器驱动电路。其工作原理是,当单片机的P3.7口输出高电平时,三极管导通,电流从VCC经过三极管驱动蜂鸣器,从而使蜂鸣器发声,当单片机的P3.7口输出低电平时,三极管截止,蜂鸣器不能发声,这样实际上单片机的端口只是起到了控制三极管的导通或截止的作用。
图3 蜂鸣器驱动电路
1.3.2. 51单片机控制蜂鸣器发出乐音
首先我们都知道,乐音是有规律的声音,而本例中简易电子琴所要播放的声音就是乐音。
简易电子琴所使用的乐音范围通常从每秒振动16次(最低音)到振动4186次(最高音),这个范围可以划分成97个等级。
我们都知道“do、re、mi、fa、so、la、ti、do”的音符,对应简谱中的“1,2,3,4,5,6,7”。对应乐音的持续时间使用节拍数来表示。对于一段音乐来说,它是由许多不同的音符组成的,而每个音符对应不同的频率,所以简易电子琴可以使用发声系统进行不同频率的发声,并且加上以节拍数对应的延时,从而产生音乐。
由于乐音是由不同的频率构成的,所以可以使用51单片机的定时器来产生不同的脉冲,用这些脉冲来驱动蜂鸣器,进而得到对应的音符。
我们假设51单片机的工作时钟为12MHz,使用定时器的工作方式1来实现定时操作,其初始化值和音符的对应关系如图4所示。
图4 音符和定时器的初值的关系
另外,一段音乐除了和音符有关系外,和节拍也有关系。也就是51单片机驱动蜂鸣器发出乐音的长度,可以使用延时来实现。图5所示是各个节拍对应的延时长度。
图5 各个节拍对应的延时长度
1.4. 电路设计
本实例的电路所用器件较多,所以需要合理划分51单片机的I/O端口,以使不同的端口控制、驱动不同的器件。
本实例的电路主要由51单片机、播放按键、播放指示灯、蜂鸣器等几部分组成,各部分详细说明如下。
1、51单片机:简易电子琴系统的核心控制器;
2、按键:本电路中共9个按键,其中k1~k8是音符按键,分别对应音调“1”~“#7”,及按下按键,会发出相应的音符声音。而K9按键是音乐播放按键,按下K9,会播放一段音乐;
3、发声器件:本例中的发声器件是蜂鸣器,蜂鸣器的驱动采用三极管驱动;
4、指示灯:本例中共8个LED指示灯,采用“灌电流”的驱动方式,为保护单片机端口,采用了一个排阻。
本实例的电路如图6所示。
图6 简易电子琴电路
细心的大家可能会发现,按键K1~K8与单片机端口的连接电路与按键K9与单片机的连接电路不一样,这是因为51单片机P1管脚内部接有上拉电阻,而P2端口内部是漏极开路,所以必须外接上拉电阻,外接电阻的阻值一般选择3~10K欧姆,如果电阻太小,则电流就可能过大,从而会烧毁单片机的P2管脚。
1.5. 程序设计
本实例的程序代码如下。程序中使用了数组这样一个51单片机C语言中的重要数据类型,并且使用了一维数组和两维数组,其中二维数组freq[][2]用来存放不同音符对应的定时器的初始化值,一位数组MUSIC[]存放了一段音乐对应的音符数据。主循环中通过对不同按键的状态判断进行不同的处理。
#include<AT89X52.h>
#define KeyPort P1
unsigned char High,Low; //定时器预装值的高8位和低8位
sbit SPK=P3^7; //定义蜂鸣器接口
sbit playSongKey=P0^0; //音乐播放按键
//不同音符对应的定时器的初始化值
unsigned char code freq[][2]={
0xD8,0xF7,//00440HZ 1
0xBD,0xF8,//00494HZ 2
0x87,0xF9,//00554HZ 3
0xE4,0xF9,//00587HZ 4
0x90,0xFA,//00659HZ 5
0x29,0xFB,//00740HZ 6
0xB1,0xFB,//00831HZ 7
0xEF,0xFB,//00880HZ `1
};
unsigned char Time;
//“世上只有妈妈好“数据表
unsigned char code YINFU[9][1]={{' '},{'1'},{'2'},{'3'},{'4'},{'5'},{'6'},{'7'},{'8'}};
//音阶频率表高8位
unsigned char code MUSIC[]={ 6,2,3, 5,2,1, 3,2,2, 5,2,2, 1,3,2, 6,2,1, 5,2,1,
6,2,4, 3,2,2, 5,2,1, 6,2,1, 5,2,2, 3,2,2, 1,2,1,
6,1,1, 5,2,1, 3,2,1, 2,2,4, 2,2,3, 3,2,1, 5,2,2,
5,2,1, 6,2,1, 3,2,2, 2,2,2, 1,2,4, 5,2,3, 3,2,1,
2,2,1, 1,2,1, 6,1,1, 1,2,1, 5,1,6, 0,0,0
};
////音阶频率表高低位
unsigned char code FREQH[]={
0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,
0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, //1,2,3,4,5,6,7,8,i
0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,
}
// Òô½×ƵÂÊ±í µÍ°Ëλ
unsigned char code FREQL[]={
0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, //1,2,3,4,5,6,7,8,i
0xEE,0x44, 0x6B,0xB4,0xF4,0x2D,
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,
};
void Init_Timer0(void);//¶¨Ê±Æ÷³õʼ»¯
//ÑÓʱº¯Êý´óÔ¼Ô¼2*z+5us
void delay2xus(unsigned char z)
{
while(z--);
}
// ÑÓʱº¯Êý´óÔ¼Ô¼1ms
void delayms(unsigned char x)
{
while(x--)
{
delay2xus(245);
delay2xus(245);
}
}
/*------------------------------------------------
½ÚÅÄÑÓʱº¯Êý
¸÷µ÷1/4½ÚÅÄʱ¼ä£º
µ÷4/4 125ms
µ÷2/4 250ms
µ÷3/4 187ms
------------------------------------------------*/
void delayTips(unsigned char t)
{
unsigned char i;
for(i=0;i<t;i++)
{
delayms(250);
}
TR0=0;
}
//²¥·ÅÒôÀֵĺ¯Êý
void PlaySong()
{
TH0=High;//¸³Öµ¶¨Ê±Æ÷ʱ¼ä£¬¾ö¶¨ÆµÂÊ
TL0=Low;
TR0=1; //´ò¿ª¶¨Ê±Æ÷
delayTips(Time); //ÑÓʱËùÐèÒªµÄ½ÚÅÄ
}
//¶¨Ê±Æ÷T0³õʼ»¯×Ó³ÌÐò
void Init_Timer0(void)
{
TMOD |= 0x01; //ʹÓÃģʽ1£¬16λ¶¨Ê±Æ÷£¬Ê¹ÓÃ"|"·ûºÅ¿ÉÒÔÔÚʹÓöà¸ö¶¨Ê±Æ÷ʱ²»ÊÜÓ°Ïì
EA=1; //×ÜÖжϴò¿ª
ET0=1; //¶¨Ê±Æ÷Öжϴò¿ª
}
//¶¨Ê±Æ÷T0ÖжÏ×Ó³ÌÐò
void Timer0_isr(void) interrupt 1
{
TH0=High;
TL0=Low;
SPK=!SPK;
}
//Ö÷º¯Êý
int main (void)
{
unsigned char num,k,i;
Init_Timer0(); //³õʼ»¯¶¨Ê±Æ÷0£¬Ö÷ÒªÓÃÓÚÊýÂë¹Ü¶¯Ì¬É¨Ãè
SPK=0; //ÔÚδ°´¼üʱ£¬À®°ÈµÍµçƽ£¬·ÀÖ¹³¤ÆÚ¸ßµçƽËð»µÀ®°È
while (1)
{
switch(KeyPort) //¶Ô°´¼ü½øÐд¦Àí
{
case 0xfe:num= 1;break;
case 0xfd:num= 2;break;
case 0xfb:num= 3;break;
case 0xf7:num= 4;break;
case 0xef:num= 5;break;
case 0xdf:num= 6;break;
case 0xbf:num= 7;break;
case 0x7f:num= 8;break; //·Ö±ð¶ÔÓ¦²»ÓõÄÒôµ÷
default:num= 0;break;
}
P2 = KeyPort;
if(num==0)
{
TR0=0;
SPK=0; //ÔÚδ°´¼üʱ£¬À®°ÈµÍµçƽ£¬·ÀÖ¹³¤ÆÚ¸ßµçƽËð»µÀ®°È
}
else
{
High=freq[num-1][1];
Low =freq[num-1][0];
TR0=1;
}
if(playSongKey==0) //Èç¹û²¥·ÅÒôÀÖ°´¼ü±»°´ÏÂ
{
delayms(10);
if(playSongKey==0)
{
i=0;
while(i<100)
{
k=MUSIC[i]+7*MUSIC[i+1]-1;//È¥Òô·ûÕñµ´ÆµÂÊËùÐèÊý¾Ý
High=FREQH[k];
Low=FREQL[k];
Time=MUSIC[i+2]; //½ÚÅÄʱ³¤
i=i+3;
if(P1!=0xff)//³¤°´ÈÎÒâ8Òô¼üÍ˳ö²¥·Å
{
delayms(10);
if(P1!=0xff)
i=101;
}
PlaySong();
}
TR0=0;
}
}
}
}
欢迎大家来到IT世界,在知识的湖畔探索吧!
1.6. 实例仿真
将程序编译后生成的HEX文件,载入到proteus环境下51单片机中,然后开始仿真,仿真结果如下所示。
1.7. 总结
本例中,我们有如下收获:
1、从实际应用中了解了51单片机P0口和P2口不同的内部结构,以及实际电路中的差别;
2、还了解了51单片机如何用管脚驱动大功率器件的方法和电路;
3、如何使用定时器让蜂鸣器发出不一样的声音。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/18270.html