音乐发生器的设计与实现.docx

上传人:b****5 文档编号:5108723 上传时间:2022-12-13 格式:DOCX 页数:22 大小:451.65KB
下载 相关 举报
音乐发生器的设计与实现.docx_第1页
第1页 / 共22页
音乐发生器的设计与实现.docx_第2页
第2页 / 共22页
音乐发生器的设计与实现.docx_第3页
第3页 / 共22页
音乐发生器的设计与实现.docx_第4页
第4页 / 共22页
音乐发生器的设计与实现.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

音乐发生器的设计与实现.docx

《音乐发生器的设计与实现.docx》由会员分享,可在线阅读,更多相关《音乐发生器的设计与实现.docx(22页珍藏版)》请在冰豆网上搜索。

音乐发生器的设计与实现.docx

音乐发生器的设计与实现

实验课程名称:

监测控制系统应用实验五

实验项目名称:

音乐发生器的设计与实现实验成绩:

实验者:

专业班级:

电信130班

同组者:

实验日期:

周四3~4节课

一.实验内容

掌握单片机片内定时器应用设计技巧,会确定定时器的时间常数,能够进行定时器的初始化编程。

掌握利用微处理器设计音乐发生器的方法

二.探究内容

1.利用定时器产生特定的频率信号,设计一个音乐发生器,可以循环播放音乐,候选乐曲3首。

2.用按键选择播放哪一首音乐。

有音乐播放的启停键。

3.用8个LED灯随节拍闪烁(选做)

4.扩展内容(选做),用7个按键分别产生音阶1、2、3、4、5、6、7,按一下键,即产生一个节拍的相应音符,也就是设计电子琴。

三.实验设计:

1.设计要求

具体任务:

(1)设计一个音乐发生器,候选音乐有三种,K1可启动停止音乐,K2用于选择音乐段;

(2)用proteous仿真电路,保证设计的正确性;

(3)基于开发板完成实物制作。

2.探究内容:

(1)如何利用音阶计算定时器的时间常数?

(2)音乐声音的洪亮稳定如何保证?

(3)节拍如何实现?

 

三、实验设计:

1.设计音乐发生器的基本任务的基本任务:

(1)研究产生音阶1、2、3、4、5、6、7的方法,计算7个音阶对应的时间常数

(2)设计产生单首乐曲循环的软件,调试后下载到开发板

(3)设计产生3首乐曲的音乐发生器,用按键选择循环的单曲,调试后下载到开发板,运行。

2.相关知识介绍

2.3音阶对应频率计数初值的计算

单片机的振荡频率为fosc=12MHz,通过定时器T0溢出后对P3.0口取反产生方波,故定时器溢出时间为1/2f。

由:

,则定时初值为:

以音阶“1”为例:

f=523Hz,则T=1/f

定时初值:

用同一方法可求出其它音阶所对应的频率定时初值,将其制表放在程序中,通过查表向定时器T0装入所要求的定时初值,即可产生某一音阶所对应的频率的方波信号。

C调的音阶及其频率、在单片机中的定时初值对应如下:

四.原理图

1.音乐播放器原理图

因为开发板上面的蜂鸣器为无源蜂鸣器,所以设计时要适应开发板的情况进行设计。

K1、K2按键用来进行上一曲和下一曲的选择,K3为暂停/开始按键,P2.0接蜂鸣器,P1口接LED灯,用LED灯显示节拍。

2.电子琴原理图

上面七个键按下分别发出哆嘞咪发嗦啦嘻的音,第八个按键选择音调的高低。

最下面的按键用来控制使用和暂停。

五.实验结果

音乐播放器仿真和实物都能正常的播放音乐,并且能够实现上一曲、下一曲的选择,并且有暂停和播放的功能,电子琴也能够正常发音,可以演奏音乐。

 

六、结果分析及总结

(1)如何利用音阶计算定时器的时间常数?

单片机的振荡频率为fosc=12MHz,通过定时器T0溢出后对P3.0口取反产生方波,故定时器溢出时间为1/2f。

由:

,则定时初值为:

以音阶“1”为例:

f=523Hz,则T=1/f

定时初值:

用同一方法可求出其它音阶所对应的频率定时初值,将其制表放在程序中,通过查表向定时器T0装入所要求的定时初值,即可产生某一音阶所对应的频率的方波信号。

(2)节拍如何实现?

取乐曲节拍的长度为0.4s,即1拍=0.4s,由定时器T1控制延时。

设置定时器T1的定时中断T=50ms,采用定时方式1。

由:

,则定时初值X=3C0BH

因此1拍=0.4s=8*50ms,即通过定时器T1的定时中断8次,产生8*50ms的定时,就可以满足1节拍的定时要求。

以此类推,通过定时中断N次,可产生N*50ms的定时以满足1/4拍、1/2拍、1拍、2拍等不同节拍的定时要求。

由此可知,节拍值只能是整数值。

(3)音乐声音的洪亮稳定如何保证?

这里的“源”不是指电源。

而是指震荡源。

也就是说,有源蜂鸣器内部带震荡源,所以只要一通电就会叫。

而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。

必须用2K~5K的方波去驱动它。

此次设计初,由于没意识到蜂鸣器驱动分为有源驱动和无源驱动,在使用网上的乐谱和相应的函数设计音乐播放器时,不能正确产生音乐,后来查资料才发现有无源和有源之分,有源和无源蜂鸣器的发声原理不同,故其乐谱会有所不同。

乐谱可以放在一个乐谱表中,通过查表来实现音乐的播放,要想循环播放一首歌,可以加一句查询语句,因为一条语句的执行时间非常短,对乐曲的演奏没有影响,在判断乐曲播放完后,继续回到乐曲开始,便可实现循环播放。

 

附录:

音乐播放器程序

#include

/*------------------------------------------------

硬件端口定义

------------------------------------------------*/

sbitSPK=P2^0;//定义音乐输出端口

sbitkey1=P3^2;//定义按键用于暂停

sbitkey2=P3^3;//定义按键用于切换

unsignedcharW=0,T;//用于选择音乐

unsignedcharTimer0_H,Timer0_L,Time;

 

voiddelay5ms(void)//误差0us

{

unsignedchara,b;

for(b=185;b>0;b--)

for(a=12;a>0;a--);

}

 

voiddelay500ms(void)//误差0us

{

unsignedchara,b,c;

for(c=205;c>0;c--)

for(b=116;b>0;b--)

for(a=9;a>0;a--);

}

//世上只有妈妈好数据表音谱,高中低音,音长

codeunsignedcharMUSIC[102]={

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};

 

//送别数据表音谱,高中低音,音长

codeunsignedcharMUSIC1[174]={

5,2,2,3,2,1,5,2,1,1,3,4,6,2,2,1,3,2,5,2,4,

5,2,2,1,2,1,2,2,1,3,2,2,2,2,1,1,2,1,2,2,8,

5,2,2,3,2,1,5,2,1,1,3,3,7,2,1,6,2,2,1,3,2,

5,2,4,5,2,2,2,2,1,3,2,1,4,2,3,7,1,1,1,2,8,

6,2,2,1,3,2,1,3,4,7,2,2,6,2,1,7,2,1,1,3,4,

6,2,1,7,2,1,1,3,1,6,2,1,6,2,1,5,2,1,3,2,1,

1,2,1,2,2,8,5,2,2,3,2,1,5,2,1,1,3,3,7,2,1,

6,2,2,1,3,2,5,2,4,5,2,2,2,2,1,3,2,1,4,2,3,

7,1,1,1,2,8};

 

//新年好数据表音谱,高中低音,音长

codeunsignedcharMUSIC2[90]={

1,2,1,1,2,1,1,2,2,5,1,2,

3,2,1,3,2,1,3,2,2,1,2,2,

1,2,1,3,2,1,5,2,2,5,2,2,

4,2,1,3,2,1,2,2,4,2,2,1,

3,2,1,4,2,2,4,2,2,3,2,1,

2,2,1,3,2,2,1,2,2,1,2,1,

3,2,1,2,2,2,5,1,2,7,1,1,

2,2,1,1,2,4};

 

//童年数据表音谱,高中低音,音长

codeunsignedcharMUSIC3[423]={

5,1,1,5,1,1,3,1,1,5,1,2,3,1,1,5,1,2,6,1,1,

6,1,1,1,2,1,6,1,2,6,1,1,1,2,2,2,2,1,2,2,1,

3,2,1,2,2,2,5,1,1,6,1,1,5,1,1,1,2,1,1,2,1,

5,1,1,1,2,1,1,2,1,1,2,2,1,2,1,1,2,1,5,1,2,

1,2,1,6,1,1,5,1,1,3,1,1,2,1,1,1,1,2,3,1,1,

5,1,1,5,1,2,5,1,1,3,1,1,6,1,1,6,1,1,1,2,1,

6,1,1,6,1,1,6,1,1,6,1,1,5,1,1,1,2,2,1,2,1,

1,2,1,1,2,1,6,1,1,1,2,1,6,1,1,5,1,2,0,2,1,

3,1,1,6,1,1,1,2,1,6,1,1,5,1,1,3,1,1,2,1,1,

3,1,1,5,1,1,5,1,2,5,1,1,3,1,1,6,1,1,6,1,1,

1,2,1,6,1,1,6,1,1,6,1,1,6,1,1,5,1,1,1,2,2,

1,2,1,1,2,1,1,2,1,6,1,1,6,1,1,1,2,1,2,2,2,

0,2,1,5,1,1,2,2,1,5,2,1,2,2,2,5,2,1,5,2,2,

5,2,1,5,2,1,5,2,1,3,2,1,2,2,1,1,2,1,1,2,2,

6,1,1,6,1,1,1,2,1,6,1,1,1,2,1,2,2,1,2,2,1,

2,2,1,2,2,1,2,2,1,1,2,1,3,2,1,2,2,1,2,2,8,

3,2,1,3,2,2,3,2,1,3,2,2,2,2,2,1,2,1,1,2,2,

1,2,1,2,2,1,1,2,1,6,1,1,5,1,1,5,1,1,5,1,2,

5,1,1,6,1,1,5,1,1,2,2,1,3,2,1,1,2,8,1,2,1,

5,1,2,1,2,1,6,1,1,5,1,1,3,1,1,2,1,1,1,2,6,

0,2,2};

//音阶频率表高八位

codeunsignedcharFREQH[]={

0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,

0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,

};//1,2,3,4,5,6,7,8,i

//音阶频率表低八位

codeunsignedcharFREQL[]={

0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,

0x8F,0xEE,0x44,0x6B,0xB4,0xF4,0x2D,0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,

};//1,2,3,4,5,6,7,8,i

/*------------------------------------------------

uS延时函数,含有输入参数unsignedchart,无返回值

unsignedchar是定义无符号字符变量,其值的范围是

0~255这里使用晶振12M,精确延时请使用汇编,大致延时

长度如下T=tx2+5uS

------------------------------------------------*/

voidDelayUs2x(unsignedchart)

{

while(--t);

}

/*------------------------------------------------

mS延时函数,含有输入参数unsignedchart,无返回值

unsignedchar是定义无符号字符变量,其值的范围是

0~255这里使用晶振12M,精确延时请使用汇编

------------------------------------------------*/

voidDelayMs(unsignedchart)

{

while(t--)

{

//大致延时1mS

DelayUs2x(245);

DelayUs2x(245);

}

}

/*------------------------------------------------

节拍延时函数

各调1/4节拍时间:

调4/4125ms

调2/4250ms

调3/4187ms

------------------------------------------------*/

voiddelay(unsignedchart)

{

unsignedchari;

for(i=0;i

DelayMs(250);

TR0=0;

}

/*------------------------------------------------

定时器0中断

------------------------------------------------*/

voidTIM0_ISR()interrupt1

{

TR0=0;

SPK=!

SPK;

TH0=Timer0_H;

TL0=Timer0_L;

TR0=1;

}

/*------------------------------------------------

歌曲处理函数

------------------------------------------------*/

voidSong()

{

TH0=Timer0_H;//赋值定时器时间,决定频率

TL0=Timer0_L;

TR0=1;//打开定时器

delay(Time);//延时所需要的节拍

}

/*------------------------------------------------

主函数

------------------------------------------------*/

voidled(unsignedchara);

voidmain(void)

{

unsignedinti;

unsignedchark;

TMOD|=0x01;//置定时器0工作方式1

EA=1;//打开全局中断

ET0=1;//打开定时器0中断

EX0=1;//打开外部中断0中断

IT0=1;//设置为下降沿中断

EX1=1;//打开外部中断1中断

IT1=1;//设置为下降沿中断

PX1=1;//设置外部中断1为高优先级

 

while

(1)

{

//i=0;

if(W==0)

{

T=W;

for(i=0;i<100;i=i+3)

{//音乐数组长度,唱完从头再来

led(MUSIC[i]);

k=MUSIC[i]+7*MUSIC[i+1]-1;//去音符振荡频率所需数据

Timer0_H=FREQH[k];

Timer0_L=FREQL[k];

Time=MUSIC[i+2];//节拍时长

//i=i+3;

Song();

if(T!

=W)

break;

}

}

if(W==1)

{

T=W;

for(i=0;i<174;i=i+3)

{//音乐数组长度,唱完从头再来

led(MUSIC1[i]);

k=MUSIC1[i]+7*MUSIC1[i+1]-1;//去音符振荡频率所需数据

Timer0_H=FREQH[k];

Timer0_L=FREQL[k];

Time=MUSIC1[i+2];//节拍时长

//i=i+3;

Song();

if(T!

=W)

break;

}

}

if(W==2)

{

T=W;

for(i=0;i<90;i=i+3)

{//音乐数组长度,唱完从头再来

led(MUSIC2[i]);

k=MUSIC2[i]+7*MUSIC2[i+1]-1;//去音符振荡频率所需数据

Timer0_H=FREQH[k];

Timer0_L=FREQL[k];

Time=MUSIC2[i+2];//节拍时长

//i=i+3;

Song();

if(T!

=W)

break;

}

}

if(W==3)

{

T=W;

for(i=0;i<423;i=i+3)

{//音乐数组长度,唱完从头再来

led(MUSIC3[i]);

k=MUSIC3[i]+7*MUSIC3[i+1]-1;//去音符振荡频率所需数据

Timer0_H=FREQH[k];

Timer0_L=FREQL[k];

Time=MUSIC3[i+2];//节拍时长

//i=i+3;

Song();

if(T!

=W)

break;

}

}

}

}

//频谱函数

voidled(unsignedchara)

{

switch(a)

{

case0:

P1=0xff;break;

case1:

P1=0x7f;break;

case2:

P1=0x7e;break;

case3:

P1=0x7c;break;

case4:

P1=0x78;break;

case5:

P1=0x70;break;

case6:

P1=0x60;break;

case7:

P1=0x40;break;

case8:

P1=0x00;break;

}

}

//外部中断0中断服务程序用于暂停

voidzhongduan0()interrupt0

{

delay5ms();//按键去抖

if(!

key1)

{

while(!

key1);//松手检测

while(key1&&T==W);//检测按键是否按下

delay5ms();//按键去抖

while(key1&&T==W);//检测按键是否按下

while(!

key1&&T==W);//松手检测

}

}

//外部中断1中断服务程序

voidzhongduan1()interrupt2

{

delay5ms();//按键去抖

if(!

key2)

{

if(W==3)

W=0;

else

W++;

while(!

key2);//松手检测

delay500ms();

}

}

 

电子琴程序

#include

#include

#defineucharunsignedchar

#defineuintunsignedint

//*******子函数声明*************//

voidRun();

voidPlayKey();

voidKeyScan();

voidKeyScan1();

//********手动弹奏按键定义****************//

sbitBeep=P1^0;

sbitkey1=P2^0;

sbitkey2=P2^1;

sbitkey3=P2^2;

sbitkey4=P2^3;

sbitkey5=P2^4;

sbitkey6=P2^5;

sbitkey7=P2^6;

sbitkey8=P2^7;//*******播放模式下按键定义***********//

sbits3=P3^5;//暂停/播放键

ucharTh0,Tl0;

ucharkey=0;//按键代号

ucharyinfu,jiepai,i,j,m;

uchargaodi=0;

ucharflag=0;//暂停、开始

 

ucharnum;//全局变量

uchars1num;//暂停/播放键按下的次数

 

//歌曲音符

/*ucharcodeMusicCode[]={0xfc,0x0b,0xfc,0x43,0xfc,0xab,0xfd,0x08,0xfd,

0x33,0xfd,0x81,0xfd,0xc7,0xfe,0x05,0xfe,0x21,0xfb,0x8f,0xfb,0x03};*/

ucharcodeMusicCode[]={0xfc,0x44,0xfc,0xac,0xfd,0x09,0xfd,0x34,0xfd,0x82,

0xfd,0xc8,0xfe,0x06,0xfb,0x04,0xfb,0x90,0xfc,0x0c,0xfe,0x22,0xf9,0x5b,0xfa,0x15};

//按键音符

ucharcodeKeyCode[]={

0xf8,0x8b,0xf9,0x5b,0xfa,0x14,0xfa,0x66,0xfb,0x03,0xfb,0x8f,0xfc,0x0b,

/*低音*/

0xfc,0x43,0xfc,0xab,0xfd,0x08,0xfd,0x33,0xfd,0x81,0xfd,0xc7,0xfe,0x05,

/*中音*/

0xfe,0x21,0xfe,0x55,0xfe,0x84,0xfe,0x99,0xfe,0xc0,0xfe,0xe3,0xff,0x02

/*高音*/};

 

//**********使能中断****************

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 研究生入学考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1