单片机课程设计简易电子琴设计.docx

上传人:b****6 文档编号:4958529 上传时间:2022-12-12 格式:DOCX 页数:19 大小:69.70KB
下载 相关 举报
单片机课程设计简易电子琴设计.docx_第1页
第1页 / 共19页
单片机课程设计简易电子琴设计.docx_第2页
第2页 / 共19页
单片机课程设计简易电子琴设计.docx_第3页
第3页 / 共19页
单片机课程设计简易电子琴设计.docx_第4页
第4页 / 共19页
单片机课程设计简易电子琴设计.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

单片机课程设计简易电子琴设计.docx

《单片机课程设计简易电子琴设计.docx》由会员分享,可在线阅读,更多相关《单片机课程设计简易电子琴设计.docx(19页珍藏版)》请在冰豆网上搜索。

单片机课程设计简易电子琴设计.docx

单片机课程设计简易电子琴设计

单片机课程设计--简易电子琴设计

郑州轻工业学院

计算机与通信工程学院

单片机与接口技术课程设计总结报告

 

设计题目:

简易电子琴设计

学生姓名:

毛二松

系别:

计算机与通信工程学院

专业:

电子信息科学与技术

班级:

09-01

学号:

540907020127

指导教师:

韩雪琴杨永双

 

2011年12月26日

简易电子琴设计

电子琴概述

这次设计的电子琴与市场上的电子琴相比虽然音色逊了一点,但是其物美价廉,功能强大,携带方便,深受大家喜欢。

此次课程设计的电子琴是有4*4矩阵键盘来实现发音,其中4个键是功能键,剩下的12键实现真正的发音。

此外在电子琴的功能上又加上了音乐播放功能、选择歌曲、暂停以及录音回放功能,使电子琴变得更强大。

让电子琴不再是简单的弹出音调简单的电子琴,而是一个功能齐全的电子琴。

本设计功能

1.通过矩阵键盘能够弹出美妙的音乐。

2.通过功能切换,能够切换到音乐播放器功能

3.能够把弹出的音乐录制下来,并且还能够回放出来。

本设计的仿真图

引脚描述:

矩阵键盘接的是P3口,显示部分的段控制口接的是P0口,位控制口接的是P2.0、P2.1、P2.2、P2.4、P2.5,蜂鸣器接的P2.3口。

各种功能键如图所示。

设计的流程图

 

我负责的模块

主程序:

也就是本程序的整体构造、功能构造。

主程序程序:

voidmain()

{

init();//初始化

while

(1)

{

keyscan();//调用键盘扫描

display();//显示

if(key_function==1)//如果选择音乐播放

{

switch(count)

{

case1:

play(music1,music1_L);break;//播放第一首

case2:

play(music2,music2_L);break;//播放第二首

case3:

play(music3,music3_L);break;//播放第三首

}

}

else//否则选择为电子琴

{

if(key_record==2)//判断是否回放

replay(record,record_L);

}

}

}

录音功能。

录音程序和键盘扫描再一个模块中。

功能描述:

它能够把你所弹的音调、按下键盘的时间即音长以及键与键之间的时间给记录下来,它完全模拟了现实中电子琴的功能,功能之强大。

时间的记录是利用定时器1实现的。

定时器0是产生一定频率的方波,使蜂鸣器发出不同的音调。

本功能程序:

voidkeyscan()//键盘扫描:

线反转法

{

ucharh,l;//h:

行l:

if(key_record==1&&flag==0)//记录键与键之间的时间

{

TH1=(65536-5000)/256;

TL1=(65536-5000)%256;

TR1=1;

flag=1;

}

P3=0xf0;//列全置低电平,行全置高电平

h=P3&0xf0;

while(h!

=0xf0)//若有键按下则行会出现低电平

{

delay(10);//按键去抖

P3=0xf0;//列全置低电平,行全置高电平

h=P3&0xf0;

while(h!

=0xf0)

{

if(key_record==1)//如果有按键按下,则把按键前的时间记录下来

{

TR1=0;//关闭计时

record_L[b]=a;//把按键前的时间记录下来

a=0;//时间次数清零

b++;//下标加一

}

h=P3&0xf0;//读入行值

P3=0x0f;//电平反转

l=P3&0x0f;//读入列值

k=h+l;

switch(k)

{

case0xee:

temp=0;key_function++;

if(key_function==2)

key_function=0;

break;//功能选择按钮

case0xed:

temp=0;count++;next_flag=1;

if(count==4)

count=1;

break;//选曲按钮

case0xeb:

temp=0;key_record++;

if(key_record==3)

key_record=0;

break;//录音、回放、返回

case0xe7:

temp=0;pause++;

if(pause==2)

pause=0;

break;//

case0xde:

temp=6;break;//6

case0xdd:

temp=7;break;//7

case0xdb:

temp=11;break;//11

case0xd7:

temp=12;break;//12

case0xbe:

temp=13;break;//13

case0xbd:

temp=14;break;//14

case0xbb:

temp=15;break;//15

case0xb7:

temp=16;break;//16

case0x7e:

temp=17;break;//17

case0x7d:

temp=21;break;//21

case0x7b:

temp=22;break;//22

case0x77:

temp=23;break;//23

}

display();//显示

if(key_record==1&&temp!

=0)//录音时,如果有按键按下且不是功能键

{

record[j]=8;//先把按键前的初始值记下

record[j+1]=temp;//再把此按键的值记下

j=j+2;//下标值加2

TH1=(65536-5000)/256;//装初始值

TL1=(65536-5000)%256;

TR1=1;//启动定时

}

if(temp!

=0)//如果不是功能按键则发出声音

{

TH0=table[temp]/256;

TL0=table[temp]%256;

TR0=1;

}

while(h!

=0xf0)//检查按键是否弹起

{

P3=0xf0;//列全置低电平,行全置高电平

h=P3&0xf0;

}

TR0=0;//弹起后关闭定时

if(key_record==1&&temp!

=0)//录音时,如果有按键按下且不是功能键

{

TR1=0;//关闭计时

record_L[b]=a;//把按键的时间记下

a=0;//时间次数清零

flag=0;

b++;

}

}

}

BUZZER=1;//把蜂鸣器关闭

}

 

回放功能:

就是把录的音给回放出来

源程序:

voidreplay(uint*Song,uint*Song_L)//回放功能

{

uinti;

for(i=0;i

{

temp=Song[i];//把音谱频率赋给n

m=Song_L[i];//把音长赋给m

if(temp==8)//如果此时播放的是键与键之间的空隙时间

{

TR0=0;//定时关闭即不发出声音

BUZZER=1;//关闭蜂鸣器

temp=Song[i-1];

}

else//否则

{

TH0=table[temp]/256;

TL0=table[temp]%256;

TR0=1;

}

delay1(m/2);

}

j=0;a=0;b=0;//把录音清除

TR0=0;//关闭定时

BUZZER=1;//把蜂鸣器关闭

}

实验总结

经过这次课程设计,我真正学会了如何使用单片机,懂得了仿真和用真实的单片机板子实现本功能的差别,仿真毕竟不是真实的现象,有时候仿真能实现,但是把程序下载到板子上后现象可能不是你所想的那样。

做这个设计给我最大的感触就是当一个模块实现了,但是当把各个模块结合到一块后就会变得有点复杂。

当然刚开始做这个程序时,要从实现简单的功能入手,然后一点点把功能做大做强。

在做这个设计时我也遇到了很多问题:

比如,做录音、回放功能的时候,记录键与键之间的时间的设置时,记录的时间很短,原因就是当没有键按下的时候,程序会一直进行键盘扫描,而且每次都会重新进行定时初始值设置,我们希望的现象是定时初始值设置一次就够了,如果每次都重新设置定时器初始值,那么记录的时间就会不准确。

所以这时就要设置一个标志,开始时标志变量为0,如果是第一次设置,则设置完后就令这个标志变量置1,下次循环的时候,程序就不会进行重新设置定时初始值了。

所以这个标志位再程序设计的时候显得很重要。

1和0是二进制数,有时它不仅仅是一个数值,它也可以是代表一件事,1代表这件事做了,0则相反。

标志变量就像是一个站岗放哨的人,只有这个人同意了,你才能进入。

所以当我做这个课程设计所遇到的问题以及我如何解决的过程,我感觉这个过程是如此的美妙,我丝毫感觉不到这是一件痛苦的事情,反而觉得这是一件让人上瘾的趣事。

每当遇到的问题解决了,我都把他们当做是一笔财富。

我觉得我们学习的不仅是单片机本门课的知识,而且是学习获得知识的方法。

授之鱼不如授之渔,这句话也体现了方法的重要性。

7、参考文献

[1]张毅刚彭喜来.《单片机原理与应用设计》[M].电子工业出版社,2011

[2]张毅刚.《MCS-51单片机应用设计》(第二版).哈尔滨大学出版社,2002

8、附录

本课程设计的源程序:

一个.c文件,两个.h文件

主程序源程序:

#include

#include

#include

#include

#defineucharunsignedchar

#defineuintunsignedint

voidinit()//初始化程序

{

TMOD=0X11;//定时器0、1都设为工作方式1

EA=1;//总中断打开

ET0=1;//允许T0定时

ET1=1;//允许T1定时

}

voidmain()

{

init();//初始化

while

(1)

{

keyscan();//调用键盘扫描

display();//显示

if(key_function==1)//如果选择音乐播放

{

switch(count)

{

case1:

play(music1,music1_L);break;

case2:

play(music2,music2_L);break;

case3:

play(music3,music3_L);break;

}

}

else//否则选择为电子琴

{

if(key_record==2)//判断是否回放

replay(record,record_L);

}

}

}

voidT0_time()interrupt1//用于音乐播放器定时产生音调

{

TH0=table[temp]/256;

TL0=table[temp]%256;

BUZZER=!

BUZZER;

}

voidtimer1()interrupt3//用于电子琴录音计时

{

TH1=(65536-10000)/256;

TL1=(65536-10000)%256;

a++;

}

keyscan.h—键盘扫描源程序(录音、显示程序也在里面)

#defineucharunsignedchar

#defineuintunsignedint

uintrecord_replay();//录音/回放

voiddisplay();

sbitBUZZER=P2^3;

//sbitkey3=P2^4;

sbitw1=P2^0;

sbitw2=P2^1;

sbitw3=P2^2;

sbitw5=P2^4;

sbitw6=P2^5;

sbitdula=P2^6;

sbitwela=P2^7;

ucharj,a,b,flag,count=1;

ucharkey_function,key_record,next_flag;

uintrecord[20],record_L[20];//存储回放的音调

ucharn,m,k,temp,pause;

ucharcodeled[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0-f

uintcodetable[]={0,63628,63835,64021,64103,64260,64400,64524,0,0,

0,64580,64684,64777,64820,64898,64968,65030,0,0,

0,65058,65110,65157,65178,65217,65252,65283,0,0};//每个音符的简谱码(T值)

voiddelay1(uintj)

{

while(j--)

{

uintx;

for(x=125;x>0;x--);

display();

}

}

voiddelay(uinta)//1ms延时

{

uintx;

while(a--)

{

for(x=0;x<125;x++);

}

}

voiddisplay()

{

dula=1;

P0=led[key_function];

dula=0;

wela=1;

P0=0xfe;//数码管第一位亮

wela=0;

delay

(2);

dula=1;

P0=led[count];

dula=0;

wela=1;

P0=0xfd;//数码管第二位亮

delay

(2);

dula=1;

P0=led[key_record];

dula=0;

wela=1;

P0=0xfb;//数码管第三位亮

wela=0;

delay

(2);

dula=1;

P0=led[temp/10];

dula=0;

wela=0;

P0=0xef;//数码管第四位亮

wela=1;

delay

(2);

dula=1;

P0=led[temp%10];

dula=0;

wela=0;

P0=0xdf;//数码管第五位亮

wela=1;

delay

(2);

}

voidkeyscan()//键盘扫描:

线反转法

{

ucharh,l;//h:

行l:

if(key_record==1&&flag==0)//记录键与键之间的时间

{

TH1=(65536-5000)/256;

TL1=(65536-5000)%256;

TR1=1;

flag=1;

}

P3=0xf0;//列全置低电平,行全置高电平

h=P3&0xf0;

while(h!

=0xf0)//若有键按下则行会出现低电平

{

delay(10);//按键去抖

P3=0xf0;//列全置低电平,行全置高电平

h=P3&0xf0;

while(h!

=0xf0)

{

if(key_record==1)//如果有按键按下,则把按键前的时间记录下来

{

TR1=0;//关闭计时

record_L[b]=a;//把按键前的时间记录下来

a=0;//时间次数清零

b++;//下标加一

}

h=P3&0xf0;//读入行值

P3=0x0f;//电平反转

l=P3&0x0f;//读入列值

k=h+l;

switch(k)

{

case0xee:

temp=0;key_function++;

if(key_function==2)

key_function=0;

break;//功能选择按钮

case0xed:

temp=0;count++;next_flag=1;

if(count==4)

count=1;

break;//选曲按钮

case0xeb:

temp=0;key_record++;

if(key_record==3)

key_record=0;

break;//录音、回放、返回

case0xe7:

temp=0;pause++;

if(pause==2)

pause=0;

break;//

case0xde:

temp=6;break;//6

case0xdd:

temp=7;break;//7

case0xdb:

temp=11;break;//11

case0xd7:

temp=12;break;//12

case0xbe:

temp=13;break;//13

case0xbd:

temp=14;break;//14

case0xbb:

temp=15;break;//15

case0xb7:

temp=16;break;//16

case0x7e:

temp=17;break;//17

case0x7d:

temp=21;break;//21

case0x7b:

temp=22;break;//22

case0x77:

temp=23;break;//23

}

display();//显示

if(key_record==1&&temp!

=0)//录音时,如果有按键按下且不是功能键

{

record[j]=8;//先把按键前的初始值记下

record[j+1]=temp;//再把此按键的值记下

j=j+2;//下标值加2

TH1=(65536-5000)/256;//装初始值

TL1=(65536-5000)%256;

TR1=1;//启动定时

}

if(temp!

=0)//如果不是功能按键则发出声音

{

TH0=table[temp]/256;

TL0=table[temp]%256;

TR0=1;

}

while(h!

=0xf0)//检查按键是否弹起

{

P3=0xf0;//列全置低电平,行全置高电平

h=P3&0xf0;

}

TR0=0;//弹起后关闭定时

if(key_record==1&&temp!

=0)//录音时,如果有按键按下且不是功能键

{

TR1=0;//关闭计时

record_L[b]=a;//把按键的时间记下

a=0;//时间次数清零

flag=0;

b++;

}

}

}

BUZZER=1;//把蜂鸣器关闭

}

play_music.h—音乐播放源程序(回放功能也在里面)

#defineuintunsignedint

#defineucharunsignedchar

voidplay(uint*Sound,uint*Sound_L);//音乐播放

//第一首音乐:

一分钱

uintcodemusic1[]={15,21,16,21,15,13,15,12,13,15,8,

13,15,16,21,15,16,15,13,15,11,13,12,8,

13,12,11,12,13,16,15,13,15,16,8,

15,21,16,15,13,15,12,15,12,13,12,11,

0x0};//音调

uintcodemusic1_L[]={4,4,2,2,4,2,2,2,2,4,4,

2,2,2,2,2,2,2,2,2,4,2,4,4,

2,2,2,2,4,4,2,2,2,2,4,

4,2,2,2,2,2,2,4,2,2,2,2,4,4,

4};//音长

//第二首音乐:

小兔子乖乖

uintcodemusic2[]={15,21,16,15,15,13,15,16,21,15,15,16,15,13,12,12,13,15,13,12,11,

16,15,16,15,13,16,15,12,15,13,12,11,6,11,12,13,11,

0x0};

uintcodemusic2_L[]={4,2,2,4,4,2,2,2,2,4,4,4,2,2,4,4,4,2,2,4,4,

2,2,2,2,2,2,4,2,2,2,2,4,4,2,2,2,2,4,4,

4};

//第三首音乐:

祝你生日快乐

uintcodemusic3[]={15,15,16,15,21,17,

15,15,16,15,22,21,

15,15,25,23,21,17,16,

24,24,23,21,22,21,

0x0};

uintcodemusic3_L[]={2,2,4,4,4,8,

2,2,4,4,4,8,

2,2,4,4,4,4,8,

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

voidreplay(uint*Song,uint*Song_L)//回放功能

{

uinti;

TR1=0;

for(i=0;i

{

temp=Song[i];//把音谱频率赋给n

m=Song_L[i];//把音长赋给m

if(temp==8)//如果此时播放的是键与键之间的空隙时间

{

TR0=0;//定时关闭即不发出声音

BUZZER=1;//关闭蜂鸣器

temp=Song[i-1];

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

当前位置:首页 > 高等教育 > 军事

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

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