1、1.2设计意义可以了解音乐的基本知识;加深对单片机的使用;学会自己做项目;1.3 设计任务 实现电子琴发声控制系统;要求电路实现如下功能:利用现成电脑音响作为发声部件,21个音符键,实现高音、中音、低音的1、2、3、4、5、6、7的发音。并在存储几首歌曲的内容,可以实现自动播放。 2.系统总体方案及硬件设计2.1总体设计音乐是有由不同的音阶组成的,而不同的音阶又是由不同的频率发出的,那么产生不同的频率,就可以发出不同的音乐了。而利用单片机就可以产生不同的频率的方波,因此选择单片机为为主来设计。通过程序编写实现单片机输出不同的频率,输出的方波信号再通过接口给电脑音响,让其发声。同时电子琴加入le
2、d用来显示。本设计的主要工作是程序编写,通过程序让电子琴实现音乐演奏,歌曲播放以及记录已按下的音符,并播放,最后实现led显示。而硬件主要有单片机最小系统,键盘模块,发声模块,还有一个电源模块。 总体框图22.2硬件设计电路图1注:本系统有主控单片机、键盘、led显示模块、发声模块以及电源组成。2.2.2单片机的最小工作系统:这里用的单片机的型号是STC90C516RD+,配以12M的晶振,以及复位电路供电电路构成最小系统。2.2.3电源设计:这里电源直接用直流5v电源;2.2.4按键设计: 按键采用4*6扫描;4根行线接P10-P13,六根列线接P14-P17以及P20,P21口共24个按键
3、,0-20代表音符键,0-6代表低音1,2,3,4,5,6,7;7-13代表中音1,2,3,4,5,6,7;14-20代表高音1,2,3,4,5,6,7;21号按键表示播放歌曲键,当按下21号键,进入播放歌曲函数,当按下22号键时,播放下一首歌曲,当按下23键时,退出播放返回主程序。而在主程序中时,代表演奏状态,当按下23号键时,进入录音状态,此时有个绿色的指示灯会亮。而进入录音后,再按一次23键,指示灯灭,退出录音状态,返回主程序。2.2.5LED灯设计:七个红色的LED代表按键的音符DO,RE,MI.分别接到P0口的各个I端口音符DO时,一个LED亮,音符MI时,2个LED亮。同时为了区分
4、高中低音,三个八度LED显示不同,当低音音符播放时,LED闪亮,当是中音时,LED也闪亮,但是闪亮的频率更快,当是高音时,LED全亮,这是通过调节LED亮灭时间来实现,也可以说是PWM吧。还有一个绿色LED指示当前状态,当电子琴处于录音时,LED亮,否则,灭;2.2.6发声模块: 这里没有自己做功放,而是使用电脑的音响。3系统软件的的编写3.1电子琴基本原理 首先的弄清楚电子琴的基本原理:声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单片机的某个口线不断输出“高”“低”电平,则在该口线上就能产生一定频率的方波,讲该方波接上喇叭就能发出一定频率的声音,若再利用程序控制“高”“低”电平的持续
5、时间,就能改变输出波形的频率从而改变音调。乐曲中,每个音符对应着确定的频率,下表给出各音符频率。如果单片机某个口线输出“高”“低”电平的频率和某个音符的频率一样,那么将此口线接上喇叭就可以发出此音符的声音。根据这个原理就能设计出,对于单片机来说要产生一定频率的方波大致是先将某口线输出高电平然后延迟一段时间再输出低电平,如此循环的输出就会产生一定频率的方波,通过改变延迟的时间就可以改变输出方波的频率。单片机内部有两个定时计数器T1和T0,单片机的定时计数器实际上是个计数装置,它既可以对单片机内部晶振驱动时钟计数,也可以对外部输入的脉冲计数,对内部晶振计数时称为定时器,对外部时钟计数时称为计数器。
6、当对单片机内部晶振驱动时钟计数时,每个机器周期定时计数器的计数值就加,当计数值达到计数最大值时计数完毕并通知单片机。音乐中各个音符的频率表如下:音符频率表3弄懂后开始程序的实现3.2主程序模块 N Y KeyNo=21 KeyNo21 KeyNo=23 Y Y主程序框图参数计算发音原理若要产生音频脉冲,只要算出某一音频的周期(1/频率),再将此周期除以2,即为半周期的时间。利用定时器计时半周期时间,每当计时终止后就将P1.0反相,然后重复计时再反相。就可在P1.0引脚上得到此频率的脉冲。利用AT89C51的内部定时器使其工作计数器模式(MODE1)下,改变计数值TH0及TL0以产生不同频率的方
7、法产生不同音阶。计算举例例如,频率为523Hz,其周期T1/5231912s,因此只要令计数器计时956s/1s956,每计数956次时将I/O反相,就可得到中音DO(523Hz)。计数脉冲值与频率的关系式是:Nfi2fr,式中,N是计数值;fi是机器频率(晶体振荡器为12MHz时,其频率为1MHz);fr是想要产生的频率。其计数初值T的求法如下:T65536N65536fifr例如:设K65536,fi1MHz,求中音DO(261Hz)。fr655361000000fr65536500000/fr,中音DO的T65536500000/52364580。3.2.3 计算结果(1)单片机12MH
8、Z晶振,中音符与计数T0相关的计数值如表所示:音符频率(HZ)计数值(T值)低1DO26263628#4FA#74064860#1DO#27763737中5SO78464898低2RE29463835#5SO#83194934#2RE#31163928中6LA88064968低3MI33064021#6LA#93264994低4FA34964103中7SI9686503037064185104665058低SO3926426011096508541564331高2RE117565110低6LA4406440012456513446664463高3MI131865157低7SI49464524高
9、4FA139765178中1DO5236458014906519855464633高5SO156865217中2RE58716616523562264884高6LA176065252中3MI65964732186565268中4FA69864820高7SI196765283采用查表程序进行查表时,可以为这个音符建立一个表格,有助于单片机通过查表的方式来获得相应的数据:低音019之间,中音在2039之间,高音在4059之间。用单片机播放音乐,或者弹奏电子琴,实际上是按照特定的频率,输出一连串的方波。为了输出合适的方波,首先应该知道音符与频率的关系。(2)音调数据表曲调值DELAY调4/4125m
10、s62ms调3/4187ms94ms调2/4250ms上表中的频率数值,有些过多,去掉不常用的黑键频率,只是把白键对应的数据存放在单片机中,即可满足绝大部分的应用需求。定义音调数据表的程序如下:DW 63628,63835,64021,64103,64260,64400,64524 ;64580,低音区:1 2 3 4 5 6 7 DW 64580,64671,64777,64820,64898,64968,65030 65058中音区: DW 65058,65110,65157,65178,65217,65252,65283 65312高音区:把这个数据表,放在程序中,需要播音的时候,就从表
11、中取出一个数据送到定时器,当定时器溢出中断的时候,再对输出引脚取反,那么,在扬声器中,即可听到上表中频率的声音。3.2主程序中涉及的函数讲解:void YinFu_DiZhongGao_Flag(uchar keyval) if(keyval7) flag_yinfu_dizhonggao=1; / 低音 else if(keyval14) flag_yinfu_dizhonggao=2; /中音else if(keyval3) cont=0; 中断函数中的余值在主程序中是这样赋值的:yuzhi=(KeyNo+3)%7; /判断DO RE MI FA.根据yuzhi判断DO、RE。当时DO时,
12、亮一个LED灯,当时RE时,亮两个LED./21个音符的频率对应的T值Uint codeTone_Delay_Table=63628,63835,64021,64103,64260,64400,64524,64580,64684,64777,64820,64898,64968,65030,65058,65110,65157,65178,65217,65252,65283void main() uchar Keystate=0; Timer_Init(); led=0x00; /初始化led led_zhishi=0;指示LED灭(进入演奏状态,若进入录音状态则亮) while(1) Keyst
13、ate=KeyState();/如果有按键按下,返回1 if(Keystate) key_scan(); if(KeyNo4); /取出音符对应的序号,如/Music_One2=0x82,音符代表MusicYinFu8 jiepai=(*(p1+i)&0X0F);/取出节拍数 yinfu_led=yinfu%7; /音符对应LED显示号 if(yinfu!=0) th0=*(p2+(yinfu-1)*2); tl0=*(p2+(yinfu-1)*2+1); TR0=1; ET0=1; else /如Music_One1=0x02,这里的音符为0,表停顿 Beep=1; for(j=jiepai
14、;j0;-j) led=LED_Disyinfu_led-1; Delayms(180);/一拍延时时间 key_scan(); if(KeyNo=23) /退出播放 ET0=1;break; else if(KeyNo=22)/下一曲 if(p1=Music_One) 若正在播放第一首,那么下一曲就是第二首 ET0=0;p1=Music_Two; else if(p1=Music_Two)/若是第二首,下一首是第三首 ET0=0;p1=Music_Three; elsep1=Music_One;/同理 i=0; KeyNo=26; /一定要改变KeyNo的值,否则只播放一个音符 Delaym
15、s(1000);/歌曲切换,停顿一下 break;/跳出之前播放的歌曲,以使播放下一曲 if(*(p1+i+1)=0XFF) /判断歌曲是否播放完毕 ET0=0; Beep=0;/暂停一下 if(p1=Music_One) /如果刚刚结束第一首歌,播放第二首歌 i=0; p1=Music_Two; Delayms(2000); else if(p1=Music_Two) /如果刚刚结束第二首歌,播放第三首歌 p1=Music_Three; else /如果刚刚结束第三首歌,播放第一首歌 p1=Music_One; Delayms(3000); TR0=0; ET0=0; if(KeyNo=23) break; ET0=1;3.4录音函数实现:NYKeyNo21 KeyNo 程序框图:5程序实现:void Record_yinfu() uchar keystate,i=0; uchar history100=0; /记录按下的键
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1