《基于51单片机的多功能电子琴的设计.doc》由会员分享,可在线阅读,更多相关《基于51单片机的多功能电子琴的设计.doc(9页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、基于51单片机的多功能电子琴的设计摘要电子琴是现代电子科技与音乐结合的产物,是一种新型的键盘乐器。它在现代音乐扮演着重要的角色,单片机具有强大的控制功能和灵活的编程实现特性,它已经溶入现代人们的生活中,成为不可替代的一部分。本文的主要内容是用AT89C51单片机为核心控制元件,设计一个电子琴。以单片机作为主控核心,与键盘、扬声器等模块组成核心主控制模块,在主控模块上设有16个按键、一排LED灯和扬声器。本系统运行稳定,其优点是硬件电路简单,软件功能完善,控制系统可靠,性价比较高等,具有一定的实用和参考价值。一、总体方案设计1、系统设计要求 本系统分为三个部分,一个是音乐播放,一个是电子琴弹奏,
2、和一个流水灯演示。具体指标如下: 1)要求达到电子琴的基本功能,可以用弹奏出简单的乐曲。 2.)用键盘作出电子琴的按键,每键代表一个音符。 3)各音符按一定的顺序排列,必须符合电子琴的按键排列顺序。 /4)固定音乐播放有按键控制:“播放”、“弹奏/停止”。 5)弹奏电子琴时能播放出准确的声音,不弹奏时可以播放内置音乐。6)弹奏电子琴时,流水灯会不停的亮灭。2、系统设计组成本系统分为两个部分,一个是音乐另一个就是电子琴。 音乐播放部分:乐音实际上是有固定周期的信号。本文介绍用AT89C51的两个定时器(如T0,T1)控制,在P3.7脚上输出方波周期信号,产生乐音,通过矩阵键盘按键产生不同的音符,
3、由此操作人员可以随心所欲的弹奏自己所喜爱的乐曲,同时,那排流水灯会不停的闪烁,当不想弹奏时通过按放歌键可以演奏事先存放在单片机中的几首动听的曲子供消遣。当歌曲演奏完时,通过按复位键便可回到初始状态,这样就做出了一台微型电子琴。 由于一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0来产生这样方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系弄正确即可。乐曲中,每一音符对应着确定的频率,我们将每一音符的时间常数和其相应的节拍常数作为一组,按顺
4、序将乐曲中的所有常数排列成一个表,然后由查表程序依次取出,产生音符并控制节奏,就可以实现演奏效果。 电子琴弹奏部分:实际上就是把每个按键所对应的值经过处理后发给单片机,再在单片机内把数字当作指针指向所对应的音符。3、系统框图该系统通过电子琴按键随意键入所要表达的音符,作为电平送给主体电路,中央处理器通过识别,解码输出音符,在扬声器中发出有效的声音。通过这样可以不断的弹奏音乐。嵌入式电路,按键电路,LED显示电路和两个功能键组成,通过功能键可以选择播放音乐。其主要模块由五个部分组成,具体关系如图二、单元电路设计1、矩阵式键盘的识别行扫描法:1、判断键盘中有无键按下 将全部行线Y0-Y3置低电平,
5、然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。若所有列线均为高电平,则键盘中无键按下。2、判断闭合键所在的位置 在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。2.数码管显示利用共阴数码管显示,0,1,2,3F,代表0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x7
6、7,0x7c, 0x39,0x5e,0x79,0x71。3、流水灯采用一组不同颜色的流水灯放于P1口,注意接限流电阻。下图中的矩阵键盘,从上到下,从左到右,依次为键盘的0-15,在数码管上显示时顺序为0-9和A-F,在按功能键时,图上的两个指示灯会根据功能的不同实现亮/灭状态的切换。在播放内置音乐时,指示灯在一定程度上能指示出曲目的音符。 三、软件设计、整体程序处理流程图在电子琴开始工作时,系统默认电子琴处于弹奏状态,歌曲选择功能键的目的是赋予矩阵键盘第二功能,即对系统内置的歌曲进行选择,在放歌时能且只能通过弹奏/停止键来结束放歌,选歌时必须先按下歌曲选择功能键,在通过矩阵键盘来选择和切换曲目
7、。、音乐播放设计一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0来产生这样方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系弄正确即可。 若要产生音频脉冲,只要算出某一音频的周期(1/频率),再将此周期除以2,即为半周期的时间。利用定时器计时半周期时间,每当计时终止后就将P3.7反相,然后重复计时再反相。就可在P3.7引脚上得到此频率的脉冲。 利用AT89C51的内部定时器使其工作计数器模式(MODE1)下,改变计数值TH0及TL0以产生
8、不同频率的方法产生不同音阶,例如,频率为523Hz,其周期T1/5231912s,因此只要令计数器计时956s/1s956,每计数956次时将I/O反相,就可得到中音DO(523Hz)。 计数脉冲值与频率的关系式是: Nfi2fr 式中,N是计数值;fi是机器频率(晶体振荡器为12MHz时,其频率为1MHz);fr是想要产生的频率。 其计数初值T的求法如下: T65536N65536fi2fr 例如:设K65536,fi1MHz,求低音DO(261Hz)、中音DO(523Hz)、高音DO(1046Hz)的计数值。 T65536N65536fi2fr655362fr65536/fr 低音DO的T
9、65536/26263628 中音DO的T65536/52364580 高音DO的T65536/104665058 音乐的音拍,一个节拍为单位(C调)对于不同的曲调我们也可以用单片机的另外一个定时/计数器来完成。 在这个程序中用到了两个定时/计数器来完成的。其中T0用来产生音符频率,T1用来产生音拍。 四、小结和体会在这次单片机课程设计中,确实折腾了好久,从中也收获颇丰。在对单片机的P0,P1,P2,P3端口接不接电阻上研究了好久。P0口必须接上拉电阻,P1,P2,P3口接外部器件时,要考虑接限流电阻。在对音乐的编码时,要注意音调和节拍的编码。音调有低中高音21个,节拍有1/2,1/4,1/8
10、,1/16拍。最后在调试时,检查了好久,发现一个地线在布线时忘了布。所以,以后做事时要细心啊,播放设备首先选的是蜂鸣器,但播放音乐时,效果不佳,最后用喇叭代替,声音效果得到了很好的改善。 本设计的电子琴可以集多种功能于一体,键盘,数码管,流水灯,喇叭。可以从触觉,视觉和听觉上感受此设计的完美。但此设计美中不足的是在播放音乐时,流水灯没有实现闪烁的功能。可以在原来基础上再加一个流水灯。实现对低、中、高总共个音调的闪烁,每读一个音调时就会有灯闪烁。可以采用而今编码实现。如:低为00001 中1为01000 高1为01111 低2为00010 中2为01001 高2为10000 低3为00011 中
11、3为01010 高3为10001 低4为00100 中4为01011 高4为10010低5为00101 中5为01100 高5为10011 低6为00110 中6为01101 高6为10100 低7为00111 中7为01110 高7为10101 利用五个闪烁灯对灯进行编码,就可在播放音乐时,每读到一个音调时,喇叭就会发声。附录1:源程序:#include #include #include #include #define uchar unsigned char#define uint unsigned int uchar STH0; /定时器计数初值uchar STL0;bit FY=0;
12、 /放乐曲时FY=1, 电子琴弹奏时FY=0uchar Song_Index=0,Tone_Index=0; /放音乐的参数uchar k, key;sbit SPK=P37;sbit LED1=P10;sbit LED2=P11;sbit LED3=P12;sbit LED4=P13;sbit LED5=P14;sbit LED6=P15;uchar code DSY_CODE= 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71; uchar code Song50= /任意选
13、几首音乐的旋律13,12,10,12,15,13,12,13,10,12,13,12,10,8,6,12,10,9,9,10,12,12,13,10,9,8,12,10,9,8,6,8,5,-1,8,9,10,8,8,9,10,8,10,11,12,10,11,12,-1,1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,4,3,1,5,6,5,6,3,1,2,5,1,2,5,1,-1,10,10,10,9,10,9,10,9,9,6,6,7,8,9,8,7,6,5,6,-1,10,10,10,9,10,13,12,13,12,12,9,9,10,11,12,11,10,9,
14、8,10,10,-1,13,14,13,12,12,10,12,10,12,9,13,12,10,9,10,10,-1,9,13,13,13,8,13,13,13,13,14,15,14,13,14,13,14,10,10,-1,13,14,13,12,12,10,12,10,12,13,14,13,14,13,14,10,-1,9,13,13,13,8,13,13,13,13,14,15,14,13,13,14,12,13,-1,12,10,12,15,13,15,12,12,8,9,10,9,8,9,0,0,12,10,12,15,14,13,15,12,12,9,10,11,7,8,0,
15、0,-1,5,5,6,5,8,7,5,5,6,5,9,8,5,5,12,10,8,7,13,11,11,10,8,9,8,3,3,4,3,8,7,3,3,4,3,9,8,5,5,10,10,8,7,6,-1,8,0,8,9,13,5,0,10,9,9,9,0,9,9,8,9,0,0,0,9,0,9,10,11,12,0,11,11,11,11,0,10,11,12,10,0,0,12,8,0,10,11,12,8,12,13,14,6,10,10,10,10,9,8,8,7,6,13,13,13,13,13,12,10,12,12,11,10,10,13,13,12,10,9,8,9,8,7,
16、6,3,-1,13,13,8,13,13,13,13,14,15,14,13,14,13,14,10,10,13,14,13,12,12,10,12,10,12,13,14,13,14,13,14,10,9,13,13,13,8,13,13,13,13,14,15,14,13,13,14,12,13,-1,12,8,0,10,11,12,8,12,13,14,13,0,0,0,15,15,15,14,13,13,12,12,10,11,11,10,9,8,0,0,0,-1,5,8,8,8,8,5,6,7,8,8,0,10,8,9,10,12,12,12,10,10,8,10,12,10,9,9
17、,13,12,9,10,12,10,12,10,9,10,8,9,10,-1 ;uchar code Len50= /上面几首音乐的旋律每个音符对应 1,2,1,1,1,2,2,2,1,2,2,1,1,2,2,2,2,2,1,2,1,2,2,1,1,2,1,2,2,2,2,2,4,-1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,-1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,0,1,0,1,1,1,0,1,0,1,1,1,1,1,2,1,1,2,-1,1,1,1,1,2,1,1,1,1,0,1,1,0,1,1,0,1,1,2,-1,1,1,1,1,0,1,1,1,1
18、,1,0,1,1,0,1,1,0,1,1,3,1,-1,0,1,1,0,1,1,2,1,1,0,1,1,0,1,1,2,-1,0,1,1,2,0,1,1,0,1,1,0,1,1,0,1,1,2,1,-1,0,1,1,0,1,1,2,1,1,0,1,1,0,1,1,4,-1,0,1,1,2,0,1,1,0,1,1,0,1,1,0,1,4,-1,1,1,1,2,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,2,1,1,-1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,2,1,1
19、,1,1,1,2,1,1,1,1,1,-1,1,1,1,1,2,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,2,1,1,1,0,1,0,1,0,1,0,2,1,1,2,1,1,1,1,1,1,1,1,2,-1,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,-1,1,1,2,0,1,1,0,1,1,0,1,1,0,1,1,2,1,0,1,1,0,1,1,2,1,1,0,1,1,0,1,1,4,0,1,1,2,0,1,1,0,1,1,0,1,1,0,1,4,-1,2,1,1,1,1
20、,1,1,1,1,2,1,1,1,1,1,1,1,0,1,0,2,1,1,1,1,1,1,1,1-1,2,1,1,0,0.25,1,0.25,0.25,2,1,1,1,1,0.25,0.25,1,1,1,1,0.25,1,0.25,1,0.25,1,2,1,1,1,1,1,1,1,1,0.25,0.25,1,1,2,-1 ; /* 音符与计数值对应表 */uint code tab= 0,63628,63835,64021,64103,64260,64400,64524, /0,低1,低2,低3,低4,低5,低6, 64580,64684,64777,64820,64898,64968,650
21、30, /中1,中2,中3,中4,中5,中6,中7 65058,65110,65157,65178,65217,65252,65283 ; /高1,高2,高3,高4,高5,高6,高7/播放歌曲时实现节拍的延时函数void delay1(uint ms) uchar t;while(ms-)for (t=0;t0;i-); /* 键扫描函数 */uchar getkey(void) uchar scancode,tmpcode;if (P0&0xf0)=0xf0)return(0);scancode = 0xfe; while(scancode&0x10)!=0) / 逐行扫描 P0 = sca
22、ncode; / 输出行扫描码if (P0&0xf0)!=0xf0) / 本行有键按下 tmpcode = (P0&0xf0)|0x0f; /* 返回特征字节码,为1的位即对应于行和列 */return(scancode)+(tmpcode); else scancode = (scancode1)|0x01; / 行扫描码左移一位 /* 外部中断0 ,这里是弹唱按键*/void EX0_INT() interrupt 0 FY=0; LED1=1; LED2=0; LED3=0;LED4=0;LED5=0;LED6=0; /* 外部中断1 ,这里是播放按键*/void EX1_INT() i
23、nterrupt 2 FY=1; LED1=0; LED2=1; LED3=0;LED4=0;LED5=0;LED6=0; /* 定时器0中断服务子程序 */void time0_int(void) interrupt 1 using 0 /* 设置计数初值 */TH0 = STH0;TL0 = STL0;SPK=!SPK; / 反相,产生输出脉冲P2=DSY_CODEk ; void main(void) LED1=1;LED2=0;P2=0x3f;IE=0x87;TMOD=0x01;IT0=1;IT1=1;while(1) P0 = 0xf0; / 发全0列扫描码if (P0&0xf0)!
24、=0xf0) / 若有键按下 delay(); / 延时去抖动if (P0&0xf0)!=0xf0) / 延时后再判断一次,去除抖动影响 key = getkey(); / 调用键盘扫描函数switch(key) / 根据获取的按键位置得到k值 case 0x11: / 1行1列k = 0; LED3=1; LED4=0;LED5=0;LED6=0; break;case 0x21: / 1行2列k = 1; LED3=1; LED4=0;LED5=0;LED6=0; break;case 0x41: / 1行3列k = 2; LED3=1; LED4=0;LED5=0;LED6=0; bre
25、ak;case 0x81: / 1行4列k = 3; LED3=1; LED4=0;LED5=0;LED6=0; break;case 0x12: / 2行1列k = 4; LED4=1; LED3=0;LED5=0;LED6=0; break;case 0x22: / 2行2列k = 5; LED4=1; LED3=0;LED5=0;LED6=0; break;case 0x42: / 2行3列k = 6; LED4=1; LED3=0;LED5=0;LED6=0; break;case 0x82: / 2行4列k = 7; LED4=1; LED3=0;LED5=0;LED6=0; bre
26、ak;case 0x14: / 3行1列k = 8; LED5=1; LED3=0;LED4=0;LED6=0; break;case 0x24: / 3行2列k = 9; LED5=1; LED3=0;LED4=0;LED6=0; break;case 0x44: / 3行3列k = 10; LED5=1; LED3=0;LED4=0;LED6=0; break;case 0x84: / 3行4列k = 11; LED5=1; LED3=0;LED4=0;LED6=0; break;case 0x18: / 4行1列k = 12; LED6=1; LED3=0;LED4=0;LED5=0;
27、break;case 0x28: / 4行2列k = 13; LED6=1; LED3=0;LED4=0;LED5=0; break;case 0x48: / 4行3列k = 14; LED6=1; LED3=0;LED4=0;LED5=0; break;case 0x88: / 4行4列k = 15; LED6=1; LED3=0;LED4=0;LED5=0; break;default: break;if(FY=0) /* 根据所得的k值设定计数器1的计数初值 */ STH0 = tabk/256;STL0 = tabk%256;TR0 = 1; / 开始计数while (P0&0xf0)!=0xf0); / 若没有松开按键,则等待,等待期间弹奏该音符SPK=1;TR0 = 0; / 若按键松开,则停止计数,不产生脉冲输出else while (FY=1)if (SongkTone_Index=-1)Tone_Index=0;STH0=(tabSongkTone_Index)/256;STL0=(tabSongkTone_Index)%256;P2=DSY_CODESongkTone_Index ;TR0 = 1;delay1(200*LenkTone_Index);Tone_Index+;TR0 = 0;附录2:原理图
限制150内