南京工程学院单片机课程设计电子琴文档格式.docx

上传人:b****5 文档编号:19410904 上传时间:2023-01-06 格式:DOCX 页数:20 大小:42.19KB
下载 相关 举报
南京工程学院单片机课程设计电子琴文档格式.docx_第1页
第1页 / 共20页
南京工程学院单片机课程设计电子琴文档格式.docx_第2页
第2页 / 共20页
南京工程学院单片机课程设计电子琴文档格式.docx_第3页
第3页 / 共20页
南京工程学院单片机课程设计电子琴文档格式.docx_第4页
第4页 / 共20页
南京工程学院单片机课程设计电子琴文档格式.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

南京工程学院单片机课程设计电子琴文档格式.docx

《南京工程学院单片机课程设计电子琴文档格式.docx》由会员分享,可在线阅读,更多相关《南京工程学院单片机课程设计电子琴文档格式.docx(20页珍藏版)》请在冰豆网上搜索。

南京工程学院单片机课程设计电子琴文档格式.docx

调用的时间参数为

,该参数用于修改定时器执行时间。

三、原理框图

 

各模块初始化

键盘扫描

是否键盘按下

判别按键

播放音乐

(5个)

弹奏单音节

(8个)

无动作

按键14-16

按键9-13

按键1-8

显示音乐编号

显示对应音符

读取当前第一个音符

调用定时器中断,发出不同频率音调

读取下一个音符

结束标志

读取下一音符

四、系统模块详细设计与调试

(一)键盘扫描模块

1、矩阵键盘工作原理

矩阵键盘的按键设在行、列线的交点上。

行线通过上拉电阻接到+5V电源上。

无键盘按下时,行线出于高电平状态;

当有按键按下时,行线电平状态将由此按键相连接的列线的电平决定。

2、设计思路

通过扫描法识别键盘。

即,先将某一列线置为低电平,其余各列线置为高电平,检查各行线电平的变化,如果某行线电平的为低电平,就可以确立此行此列交叉点处的按键被按下。

(二)数码管显示模块

1、硬件电路

数码管的显示,是通过74LS374锁存器来实现的。

段选和位选分别是P3.5和P3.4。

数据的输出为P0口。

(详见附录一:

硬件原理图)

通过分别控制段选、位选锁存器的导通(低电平)、锁存信号(高电平)。

从而分时给数码管写入数据并锁存。

(三)音调编码读取模块

1、编码规则

2、读取方式

首先读取前两位数,以确定音调。

然后读取最后一位,以确定拍数(时间)。

然后依次递增3位。

音调确定后,通过查表获取定时器初始值,并调用定时器中断。

拍数,即定时器中断执行的循环次数,以此来控制声音的时间。

(四)定时器中断模块

1、定时器的调用

本程序的设计采用定时器中断的方法来使蜂鸣器发出不同的频率声音,从而实现电子琴的音调。

定时器的初始值不同,产生的频率也就不同。

定时器的调用是循环不断的,它的循环包括两类:

一类是一个音节频率的循环,从而控制一个拍数的长短;

另一类是下一个音节的到来,重新写入初值,直至结束标志位的到来,即0,0,0。

如果再调用程序中,再加入一个整体循环,则可以反复执行音乐播放。

即,检测到结束标志后,重新播放音乐而不间断。

(本程序,没有使用该循环。

2、初始值的生成与写入

定时器的初始值,是通过网络搜索得到的,不同的初值代表着会发出不同频率的音调。

将它制成表,以便程序读取。

五、设计总结

我课程设计的题目是电子琴的设计。

主要用的了之前所学的定时器中断、矩阵键盘扫描、数码管显示、C51编程等相关的单片机及接口技术的知识和理论。

在课设中,也充分的做到了学以致用,把之前所学的知识应用的实际当中去。

同时,也通过实践来检验之前所学的理论,发现了很多对理论知识的误解。

这些,也都在实践中得到了很好的弥补。

在设计程序的初始阶段,我本打算一次性完成任务,但每次尝试都以失败告终。

后来,我学会了分模块处理问题,逐一突破。

这也是我在此次课程设计中的一大收获。

让我充分懂得了,如何去处理一个较大的工程项目。

首先,我先实现了使单片机发出不同音调的基本功能,然后开始考虑键盘扫描。

但是在调试时,总是出现BUG。

在部分按键按下后,蜂鸣器会一直响,无法终止。

这个问题一直困扰了我很久,尝试了很多方法都没能成功,终于在一天早上醒来后的第一次尝试,终于成功了,即在键盘扫描中加入一个程序,当音乐执行到结束标志后,此时若没有键盘被按下时,令蜂鸣器停止鸣叫不做任何响应,直至有键盘再被按下。

最后,我将两个模块进行结合,于是便成功的写出了电子琴的程序。

而且成功进行了调试。

第一天验收,老师让我再加入数码管显示功能。

于是,我又写了数码管显示模块的程序。

数码管显示是通过锁存器来完成的。

当我程序写完之后进行调试,数码管没有进行显示,多次调试发现:

只有长时间按下按键才会有相应字符显示。

于是我尝试把段选信号的选通与锁存指令和P0数据写在一起,这样就可以立即显示当前字符了。

第二天验收,顺利通过。

事后,我又采用了外部中断的方法进行电子琴的模式切换等其他功能,从而不断地丰富了电子琴的功能。

同时,也对程序进行了整理,使程序更加规、美观、易读。

总而言之,此次课设,我学的东西很多。

也深深地懂得理论不进行实际,是不行的。

只有通过实践才能检验自己对理论知识的理解和掌握。

在写程序的时候,一定要有良好的习惯,格式要有自己的排版方式,不能混乱。

这样易于检查和调整。

通过这次课设。

大大提高了我对单片机以及编程的能力与信心。

我相信,以后通过自己的不断深入的学习,我一定能够熟练的运用单片机到实际当中去。

六、参考文献

[1]升,《单片机原理与接口技术》,北京:

北京大学,2011年7月;

[2]网友:

lv_xiaowei,《音调与频率对应关系表》,http:

//wenku.baidu./view/d90a081a6edb6f1aff001f45.html,2012年01月03日;

七、附件材料

附录一:

硬件原理图

附录二:

程序清单及说明

附录三:

元器件清单

附录四:

实物图

/***********************************************************

***课程设计:

电子琴(工程学院自动化学院)***

******

***开发平台:

AT80C52***

***程序设计:

施国庆203100423***

***********************************************************/

/*______________________________

/ooooooooooooooo/\

/oooooooooooooo//

/_________________________//

//////I///LOVE//U////////

/___//////////////////////////_//

\____\________________________\_*/

***头文件***

#include<

reg51.h>

#include<

stdio.h>

#defineucharunsignedchar

#defineuintunsignedint

sbitspeaker=P3^6;

sbita0=P2^0;

sbita1=P2^1;

sbita2=P2^2;

sbita3=P2^3;

sbita4=P2^4;

sbitb2=P3^2;

sbitb4=P3^4;

sbitb5=P3^5;

unsignedchartimer0h,timer0l;

voidjian();

//--------------------------------------

***音调设置及数码管编码***

//频率-半周期数据表高八位

codeunsignedcharFREQH[]={

0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,//低音1234567

0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,//1,2,3,4,5,6,7

0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,//高音1234567

0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF};

//超高音1234567

//频率-半周期数据表低八位

codeunsignedcharFREQL[]={

0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,//低音1234567

0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,//1,2,3,4,5,6,7

0x8F,0xEE,0x44,0x6B,0xB4,0xF4,0x2D,//高音1234567

0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16};

unsignedcharconstdisplay[]={0x3f,0x06,0x5b,0x4f,0x66,

0x6d,0x7d,0x07,0x7f,0x6f};

***乐谱及其独立音调***

//-----------------乐谱---------------------//

codeunsignedcharsszymmh[]={

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

codeunsignedchardfc[]={

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

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

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

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

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

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

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

1,2,3,6,1,1,1,2,1,0,0,0};

codeunsignedcharsheng[]={

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

0,0,0};

codeunsignedcharjiang[]={

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

codeunsignedcharsongbie[]={

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,4,

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

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

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,4,

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

//-----------------单音---------------------//

codeunsignedchardou[]={

1,2,1,0,0,0

};

codeunsignedcharre[]={

2,2,1,0,0,0

codeunsignedcharmi[]={

3,2,1,0,0,0

codeunsignedcharfa[]={

4,2,1,0,0,0,

codeunsignedcharso[]={

5,2,1,0,0,0

codeunsignedcharla[]={

6,2,1,0,0,0

codeunsignedcharxi[]={

7,2,1,0,0,0

codeunsignedchardoo[]={

1,3,1,0,0,0

***时间参数:

延时、定时器中断***

voidt0int()interrupt1//T0中断程序,控制发音的音调

{

TR0=0;

//先关闭T0

speaker=!

speaker;

//输出方波,发音

TH0=timer0h;

//下次的中断时间,这个时间,控制音调高低

TL0=timer0l;

TR0=1;

//启动T0

}

voiddelay(unsignedchart)//延时程序,控制发音的时间长度

unsignedchart1;

unsignedlongt2;

for(t1=0;

t1<

t;

t1++)//双重循环,共延时t个半拍

for(t2=0;

t2<

8000;

t2++);

//延时期间,可进入T0中断去发音

//关闭T0,停止发音

voidjpdelay(void)

unsignedchari;

for(i=300;

i>

0;

i--);

}

/***********************************************************

***声频驱动程序***

voidsong(unsignedchartime)//演奏一个音符

{a3=0;

//控制音调

//启动T0,由T0输出方波去发音

delay(time);

//控制时间长度

***声频调用程序***

//---------------------单音节----------------------------//

voidyin1(void)

unsignedchark,i,time;

TMOD=1;

ET0=1;

EA=1;

i=0;

time=1;

while(time){

k=dou[i]+7*dou[i+1]-1;

//第i个是音符,第i+1个是第几个八度

timer0h=FREQH[k];

//从数据表中读出频率数值

timer0l=FREQL[k];

//实际上,是定时的时间长度

time=dou[i+2];

//读出时间长度数值

i+=3;

song(time);

//发出一个音符

}}

voidyin2(void)

k=re[i]+7*re[i+1]-1;

time=re[i+2];

voidyin3(void)

k=mi[i]+7*mi[i+1]-1;

time=mi[i+2];

voidyin4(void)

k=fa[i]+7*fa[i+1]-1;

time=fa[i+2];

voidyin5(void)

k=so[i]+7*so[i+1]-1;

time=so[i+2];

voidyin6(void)

k=la[i]+7*la[i+1]-1;

time=la[i+2];

voidyin7(void)

k=xi[i]+7*xi[i+1]-1;

timer0h=FRE

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

当前位置:首页 > 外语学习 > 法语学习

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

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