基于AT89S51的电子琴设计报告Word格式.docx
- 文档编号:21351840
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:22
- 大小:273.57KB
基于AT89S51的电子琴设计报告Word格式.docx
《基于AT89S51的电子琴设计报告Word格式.docx》由会员分享,可在线阅读,更多相关《基于AT89S51的电子琴设计报告Word格式.docx(22页珍藏版)》请在冰豆网上搜索。
(外部中断0)
P3.3
(外部中断1)
P3.4
T0(定时器0外部输入)
P3.5
T1(定时器1外部输入)
P3.6
WR(外部数据存储器写选通)
P3.7
RD(外部数据存储器读先通)
P3口同时为闪烁编程和编程校验接收一些控制信号。
1.音乐产生的方法
一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0来产生这样方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系弄正确即可。
若要产生音频脉冲,只要算出某一音频的周期(1/频率),再将此周期除以2,即为半周期的时间。
利用定时器计时半周期时间,每当计时终止后就将P0.0反相,然后重复计时再反相。
就可在P0.0引脚上得到此频率的脉冲。
利用AT89S51的内部定时器使其工作计数器模式(MODE1)下,改变计数值TH0及TL0以产生不同频率的方法产生不同音阶,例如,频率为523Hz,其周期T=1/523=1912μs,因此只要令计数器计时956μs/1μs=956,每计数956次时将I/O反相,就可得到中音DO(523Hz)。
计数脉冲值与频率的关系式(如式2-1所示)是:
N=fi÷
2÷
fr
2-1
式中,N是计数值;
fi是机器频率(晶体振荡器为12MHz时,其频率为1MHz);
fr是想要产生的频率。
其计数初值T的求法如下:
T=65536-N=65536-fi÷
fr
例如:
设K=65536,fi=1MHz,求低音DO(261Hz)、中音DO(523Hz)、高音DO(1046Hz)的计数值。
fr=65536-1000000÷
fr=65536-500000/fr
低音DO的T=65536-500000/262=63627
中音DO的T=65536-500000/523=64580
高音DO的T=65536-500000/1046=65059
单片机12MHZ晶振,高中低音符与计数T0相关的计数值如表2-2所示
表2-2音符频率表
音符
频率(HZ)
简谱码(T值)
低1 DO
262
63628
#4FA#
740
64860
#1 DO#
277
63731
中5SO
784
64898
低2 RE
294
63835
#5SO#
831
64934
#2RE#
311
63928
中6LA
880
64968
低3M
330
64021
#6
932
64994
低4FA
349
64103
中7SI
988
65030
370
64185
高1DO
1046
65058
低5SO
392
64260
#1DO#
1109
65085
415
64331
高2RE
1175
65110
低6LA
440
64400
#2RE#
1245
65134
466
64463
高3M
1318
65157
低7SI
494
64524
高4FA
1397
65178
中1DO
523
64580
1480
65198
554
64633
高5SO
1568
65217
中2RE
587
64684
1661
65235
622
64732
高6LA
1760
65252
中3M
659
64777
1865
65268
中4FA
698
64820
高7SI
1967
65283
我们要为这个音符建立一个表格,单片机通过查表的方式来获得相应的数据
低音0-19之间,中音在20-39之间,高音在40-59之间
TABLE:
DW0,63628,63835,64021,64103,64260,64400,64524,0,0
DW0,63731,63928,0,64185,64331,64463,0,0,0
DW0,64580,64684,64777,64820,64898,64968,65030,0,0
DW0,64633,64732,0,64860,64934,64994,0,0,0
DW0,65058,65110,65157,65178,65217,65252,65283,0,0
DW0,65085,65134,0,65198,65235,65268,0,0,0
DW0
音乐的音拍,一个节拍为单位(C调)(如表2-3所示)
表2-3曲调值表
曲调值
DELAY
调4/4
125ms
62ms
调3/4
187ms
94ms
调2/4
250ms
对于不同的曲调我们也可以用单片机的另外一个定时/计数器来完成。
琴键处理程序,根据检测到得按键值,查询音律表,给计时器赋值,发出相应频率的声音。
对音调的控制:
根据不同的按键,对定时器T1送入不同的初值,调节T1的溢出时间,这样就可以输出不同音调频率的方波。
不同音调下各个音阶的定时器。
在这个程序中用到了两个定时/计数器来完成的。
其中T0用来产生音符频率,T1用来产生音拍。
2.4X4行列式键盘识别及显示
组成键盘的按键有机械式、电容式、导电橡胶式、薄膜式多种,但不管什么形式,其作用都是一个使电路接通与断开的开关。
目前微机系统中使用的键盘按其功能不同,通常可分为编码键盘和非编码键盘两种基本类型。
编码键盘:
键盘本身带有实现接口主要功能所需的硬件电路。
不仅能自动检测被按下的键,并完成去抖动、防串键等功能,而且能提供与被按键功能对应的键码(如ASCII码)送往CPU。
所以,编码键盘接口简单、使用方便。
但由于硬件电路较复杂,因而价格较贵。
非编码键盘:
键盘只简单地提供按键开关的行列矩阵。
有关按键的识别、键码的确定与输入、去抖动等功能均由软件完成。
目前微机系统中,一般为了降低成本大多数采用非编码键盘。
键盘接口必须具有去抖动、防串键、按键识别和键码产生4个基本功能。
(1)去抖动:
每个按键在按下或松开时,都会产生短时间的抖动。
抖动的持续时间与键的质量相关,一般为5—20mm。
所谓抖动是指在识别被按键是必须避开抖动状态,只有处在稳定接通或稳定断开状态才能保证识别正确无误。
去抖问
题可通过软件延时或硬件电路解决。
(2)防串键:
防串键是为了解决多个键同时按下或者前一按键没有释放又有新的按键按下时产生的问题。
常用的方法有双键锁定和N键轮回两种方法。
双键锁定,是当有两个或两个以上的按键按下时,只把最后释放的键当作有效键并产生相应的键码。
N键轮回,是当检测到有多个键被按下时,能根据发现它们的顺序依次产生相应键的键码。
(3)被按键识别:
如何识别被按键是接口解决的主要问题,一般可通过软硬结合的方法完成。
常用的方法有行扫描法和线反转法两种。
行扫描法的基本思想是,由程序对键盘逐行扫描,通过检测到的列输出状态来确定闭合键,为此,需要设置入口、输出口一个,该方法在微机系统中被广泛使用。
线反转法的基本思想是通过行列颠倒两次扫描来识别闭合键,为此需要提供两个可编程的双向输入/输出端口。
(4)键码产生:
为了从键的行列坐标编码得到反映键功能的键码,一般在内存区中建立一个键盘编码表,通过查表获得被按键的键码。
用AT89S51的并行口P0接4×
4矩阵键盘,以P0.0-P0.3作输入线,以P0.4-P0.7作输出线;
在数码管上显示每个按键的“0-F”序号。
3.LED数码显示原理:
(1)七段LED显示器内部由七个条形发光二极管和一个小圆点发光二极管组成,根据各管的极管的接线形式,可分成共阴极型和共阳极型。
LED数码管的g~a七个发光二极管因加正电压而发亮,因加零电压而不以发亮,不同亮暗的组合就能形成不同的字形,这种组合称之为字形码,下面给出共阴极的字形码表(如表2-1所示)
“0”
3FH
“8”
7FH
“1”
06H
“9”
6FH
“2”
5BH
“A”
77H
“3”
4FH
“b”
7CH
“4”
66H
“C”
39H
“5”
6DH
“d”
5EH
“6”
7DH
“E”
79H
“7”
07H
“F”
71H
表2-1
字形码表
(2)由于显示的数字0-9的字形码没有规律可循,只能采用查表的方式来完成我们所需的要求了。
这样我们按着数字0-9的顺序,把每个数字的笔段代码按顺序排好!
建立的表格如下所示:
TABLEDB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH。
4.电子琴实现原理
1.电源部分:
是由220V的市电通过变压、整流稳压利用7805来得到+5V电压,维持系统的正常工作;
把7805的3脚输出接到89S51的40引脚上
2.4*4的16个按钮矩阵:
4*4行列式键盘识别;
行线接P0口的P0.0~P0.3,列线P0.4~P0.7,行值和列值的组合就是识别这个按键的编码。
每个按键的状态同样需变成数字量“0”和“1”,开关的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的。
3.晶振模块:
用12MHZ的晶振,及两个30pf的电容,接到单片机的18,19,20脚,电路如图(a)所示
(a)(b)
4.复位模块:
利用开关和一个10uf的极性电容并联接单片机9脚“reset”脚,电路如图(b)所示
5.音频放大模块:
利用三极管将信号放大,由扬声器放出,信号由单片机的17脚“P3.7”口读出,电路如图(c)所示
(c)(d)
6.数码管:
利用AT89S51单片机的P2端口的P2.0-P2.7连接到一个七段数码管的a-h的笔段上,数码管的公共端接地。
在数码管上循环显示0-7数字,时间间隔0.2秒。
三.硬件电路
图3.1硬件电路原理图Protel
图3.2硬件电路PCB
四.系统程序设计流程图
五.Proteus仿真电路
图4.1Proteus仿真电路图
六.源程序
(1)Soundplay调用程序:
/*说明**************************************************************************
曲谱存贮格式unsignedcharcodeMusicName{音高,音长,音高,音长....,0,0};
末尾:
0,0表示结束(Important)
音高由三位数字组成:
个位是表示1~7这七个音符
十位是表示音符所在的音区:
1-低音,2-中音,3-高音;
百位表示这个音符是否要升半音:
0-不升,1-升半音。
音长最多由三位数字组成:
个位表示音符的时值,其对应关系是:
|数值(n):
|0|1|2|3|4|5|6
|几分音符:
|1|2|4|8|16|32|64音符=2^n
十位表示音符的演奏效果(0-2):
0-普通,1-连音,2-顿音
百位是符点位:
0-无符点,1-有符点
调用演奏子程序的格式
Play(乐曲名,调号,升降八度,演奏速度);
|乐曲名:
要播放的乐曲指针,结尾以(0,0)结束;
|调号(0-11):
是指乐曲升多少个半音演奏;
|升降八度(1-3):
1:
降八度,2:
不升不降,3:
升八度;
|演奏速度(1-12000):
值越大速度越快;
***************************************************************************/
#ifndef__SOUNDPLAY_H_REVISION_FIRST__
#define__SOUNDPLAY_H_REVISION_FIRST__
//**************************************************************************
#defineSYSTEM_OSC12000000//定义晶振频率12000000HZ
#defineSOUND_SPACE4/5//定义普通音符演奏的长度分率,//每4分音符间隔
sbitBeepIO=P3^7;
//定义输出管脚
unsignedintcodeFreTab[12]={262,277,294,311,330,349,369,392,415,440,466,494};
//原始频率表
unsignedcharcodeSignTab[7]={0,2,4,5,7,9,11};
//1~7在频率表中的位置
unsignedcharcodeLengthTab[7]={1,2,4,8,16,32,64};
unsignedcharSound_Temp_TH0,Sound_Temp_TL0;
//音符定时器初值暂存
unsignedcharSound_Temp_TH1,Sound_Temp_TL1;
//音长定时器初值暂存
voidInitialSound(void)
{
BeepIO=1;
Sound_Temp_TH1=(65535-(1/1200)*SYSTEM_OSC)/256;
//计算TL1应装入的初值(10ms的初装值)
Sound_Temp_TL1=(65535-(1/1200)*SYSTEM_OSC)%256;
//计算TH1应装入的初值
TH1=Sound_Temp_TH1;
TL1=Sound_Temp_TL1;
TMOD=0x11;
ET0=1;
ET1=0;
TR0=0;
TR1=0;
EA=1;
}
voidBeepTimer0(void)interrupt1//音符发生中断
{BeepIO=0;
BeepIO=!
BeepIO;
TH0=Sound_Temp_TH0;
TL0=Sound_Temp_TL0;
voidPlay(unsignedchar*Sound,unsignedcharSignature,unsignedOctachord,unsignedintSpeed)
{BeepIO=0;
unsignedintNewFreTab[12];
//新的频率表
unsignedchari,j;
unsignedintPoint,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
unsignedcharTone,Length,SL,SH,SM,SLen,XG,FD;
for(i=0;
i<
12;
i++)//根据调号及升降八度来生成新的频率表
{
j=i+Signature;
if(j>
11)
{
j=j-12;
NewFreTab[i]=FreTab[j]*2;
}
else
NewFreTab[i]=FreTab[j];
if(Octachord==1)
NewFreTab[i]>
>
=2;
elseif(Octachord==3)
NewFreTab[i]<
<
}
SoundLength=0;
while(Sound[SoundLength]!
=0x00)//计算歌曲长度
SoundLength+=2;
}
Point=0;
Tone=Sound[Point];
Length=Sound[Point+1];
//读出第一个音符和它时时值
LDiv0=12000/Speed;
//算出1分音符的长度(几个10ms)
LDiv4=LDiv0/4;
//算出4分音符的长度
LDiv4=LDiv4-LDiv4*SOUND_SPACE;
//普通音最长间隔标准
TR1=1;
while(Point<
SoundLength)
SL=Tone%10;
//计算出音符
SM=Tone/10%10;
//计算出高低音
SH=Tone/100;
//计算出是否升半
CurrentFre=NewFreTab[SignTab[SL-1]+SH];
//查出对应音符的频率
if(SL!
=0)
if(SM==1)CurrentFre>
=2;
//低音
if(SM==3)CurrentFre<
//高音
Temp_T=65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);
//计算计数器初值
Sound_Temp_TH0=Temp_T/256;
Sound_Temp_TL0=Temp_T%256;
TH0=Sound_Temp_TH0;
TL0=Sound_Temp_TL0+12;
//加12是对中断延时的补偿
SLen=LengthTab[Length%10];
//算出是几分音符
XG=Length/10%10;
//算出音符类型(0普通1连音2顿音)
FD=Length/100;
LDiv=LDiv0/SLen;
//算出连音音符演奏的长度(多少个10ms)
if(FD==1)
LDiv=LDiv+LDiv/2;
if(XG!
=1)
if(XG==0)//算出普通音符的演奏长度
if(SLen<
=4)
LDiv1=LDiv-LDiv4;
else
LDiv1=LDiv*SOUND_SPACE;
else
LDiv1=LDiv/2;
//算出顿音的演奏长度
LDiv1=LDiv;
if(SL==0)LDiv1=0;
LDiv2=LDiv-LDiv1;
//算出不发音的长度
if(SL!
TR0=1;
for(i=LDiv1;
i>
0;
i--)//发规定长度的音
{
while(TF1==0);
TH1=Sound_Temp_TH1;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 AT89S51 电子琴 设计 报告