单片机原理运用及八音盒设计.docx
《单片机原理运用及八音盒设计.docx》由会员分享,可在线阅读,更多相关《单片机原理运用及八音盒设计.docx(22页珍藏版)》请在冰豆网上搜索。
单片机原理运用及八音盒设计
2009级电子信息工程
单片机八音盒设计报告书
设计题目
单片机八音盒设计
姓名及学号
学院
工程技术学院
专业
电子信息工程
班级
指导教师
2012年5月5日
题目:
利用单片机设计可以发出宜人音乐旋律的八音盒
一、设计要求
(1)基本要求
①I/O口产生一定频率的方波,驱动扬声器,发出不同的音调,从而演奏乐曲;
②用七段数码显示当前播放的歌曲序号;
③可通过功能键选择乐曲,暂停、播放;
④输出功率大于0.5W。
(2)发挥部分
①采用LCD显示信息;
②开机时有英文欢迎提示字符;
指导教师签名:
2012年月日
二、指导教师评语
指导教师签名:
2012年月日
三、成绩
验收盖章
2012年月日
目录
1、单片机设计课程的目的和硬件原理4
1.2硬件原理及设计说明4
2、关于AT89S524
2.1、对于AT89S52的性能介绍4
2.2、AT89S52的管脚介绍5
3、总体设计7
5、程序输入窗口、编码及音乐程序8
5.1程序输入窗口9
5.2编码9
5.3音乐程序10
6、仿真和调试17
7、元器件清单18
8、电路总图18
8.1电路图18
8.2PCB19
8.3实物图19
9、实验总结20
1、单片机设计课程的目的和硬件原理
1.1目的和要求
大学本科生动手能力的培养和提高时大学本科的一个重要内容。
本次课程的设计目的,是让我们通过课程设计建立起单片机应用系统的概念,根据系统设计要求,掌握初步的单片机系统设计方法,让学生的动手能力和对单片机系统从硬件系统和软件系统设计两个方面都得到实际的提高。
为今后的毕业设计打下良好的基础。
课程设计的基本要求有:
(1)在课程设计过程中,学会使用89S52片机及相应绘图软件,根据设计要求设计,编程,运行,调试最后提供课程设计报告;
(2)课程设计应由学生本人独立完成,严禁抄袭;
(3)认真编写课程设计报告。
当键盘有键按下时,判断键值,启动计数器T0,产生一定频率的脉冲,驱动蜂鸣器,放出乐曲。
同时启动定时器T1,显示歌曲号。
1.2硬件原理及设计说明
(1)硬件电路中用
、
分别接S1、S2作为上、下一曲的功能键
(2)用P1.0-P1.6控制七段码a,b,c,d,e,f。
(3)用P2.1口控制喇叭。
(4)电路为12MHZ晶振频率工作,起振电路中C1,C2均为30pf。
2、关于AT89S52
2.1、对于AT89S52的性能介绍
AT89S52是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—FalshProgrammableandErasableReadOnlyMemory)的低电压,高性能CMOS8位微处理器,俗称单片机。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
它可以提供以下的功能标准:
(1)4K的字节闪烁存储器;
(2)128字节随机存取数据存储器;
(3)32个I/O口;
(4)2个16位定时/计数器;
(5)1个5向量两级中断结构;
(6)1个串行通信口;
(7)片内振荡器和时钟电路。
另外AT89S2还可以警醒OHZ的惊涛逻辑操作,并支持两种软件的节点模式。
2.2、AT89S52的管脚介绍
图1.1AT89S52的管脚图
40脚VCC:
供电电压。
20脚GND:
接地。
P0口:
P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
当P1口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。
在FIASH编程时,P0口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:
P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
P2口:
P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将输出电流。
这是由于内部上拉的缘故。
P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。
在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。
P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
P3口:
P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。
当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。
作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
P3口也可作为AT89S52特殊功能口,如下表所示:
口管脚备选功能P3.0RXD(串行输入口)P3.1TXD(串行输出口)P3.2/INT0(外部中断0)P3.3/INT1(外部中断1)P3.4T0(记时器0外部输入)P3.5T1(记时器1外部输入)P3.6/WR(外部数据存储器写选通)P3.7/RD(外部数据存储器读选通)P3口同时为闪烁编程和编程校验接收一些控制信号。
RST:
复位输入。
当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:
当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。
在FLASH编程期间,此引脚用于输入编程脉冲。
在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。
因此它可用作对外部输出的脉冲或用于定时目的。
然而要注意的是:
每当用作外部数据存储器时,将跳过一个ALE脉冲。
如想禁止ALE的输出可在SFR8EH地址上置0。
此时,ALE只有在执行MOVX,MOVC指令是ALE才起作用。
另外,该引脚被略微拉高。
如果微处理器在外部执行状态ALE禁止,置位无效。
/PSEN:
外部程序存储器的选通信号。
在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。
但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
/EA/VPP:
当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。
方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。
在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。
XTAL1:
反向振荡放大器的输入及内部时钟工作电路的输入。
XTAL2:
来自反向振荡器的输出。
3.振荡器特性:
XTAL1和XTAL2分别为反向放大器的输入和输出。
该反向放大器可以配置为片内振荡器。
石晶振荡和陶瓷振荡均可采用。
如采用外部时钟源驱动器件,XTAL2应不接。
有余输入至内部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。
4.芯片擦除:
整个PEROM阵列和三个锁定位的电擦除可通过正确的控制信号组合,并保持ALE管脚处于低电平10ms来完成。
在芯片擦操作中,代码阵列全被写“1”且在任何非空存储字节被重复编程以前,该操作必须被执行。
此外,AT89C51设有稳态逻辑,可以在低到零频率的条件下静态逻辑,支持两种软件可选的掉电模式。
在闲置模式下,CPU停止工作。
但RAM,定时器,计数器,串口和中断系统仍在工作。
在掉电模式下,保存RAM的内容并且冻结振荡器,禁止所用其他芯片功能,直到下一个硬件复位为
3、总体设计
(1)要产生音频脉冲,只要算出某一音频的周期(1/音频),然后将此周期除以2,即为半周期的时间,利用定时器计时这个半周期时间,每当计时到后就将输出脉冲的I/O反相,然后重复计时此半周期时间再对I/O口反相,就可在I/O脚上得到此频率的脉冲
(2)利用8051的内部定时器使其工作在计数器模式MODE1下,改变记数值TH0及TL0以产生不同频率的方法。
例如频率为523HZ,其周期T=1/523=1912微秒,因此只要令计数器定时956/1=956在每记数9次时将I/O口反相,就可得到中音D0(523HZ)。
记数脉冲值与频率的关系公式如下:
N=Fi/2/FrN:
记数值;Fr:
要产生的频率;
Fi:
内部计时一次为1微秒.故其频率为1MH
(3)起记数值的求法如下:
T=65536-N=65536-Fi/2/Fr
例如:
设K=65536,F=1000000=Fi=1MHZ,求低音D0(523HZ),高音的D0(1046HZ)的记数值。
T=65536-N=65536-Fi/2/Fr=65536-100000/2/Fr=65536-50000/Fr
低音D0的T=65536-500000/262=63627
中音D0的T=65536-500000/523=64580
低音D0的T=65536-500000/1047=650
4、软件设计流程图
图1.2软件设计流程图
5、程序输入窗口、编码及音乐程序
5.1程序输入窗口
图1.3keil3境下的程序输入窗口
5.2编码
建立音乐的步骤:
(1)先把乐谱的音符找出,然后建立T值表的顺序;
(2)把T值表建立在TABLE1,构成发音符的计数值放在"TABLE"。
(3)简谱码(音符)为高位,节拍为(节拍数)低四位,音符节拍码放在程序的TABLE处。
表5.1拍与节拍的对照
节拍码
节拍数
节拍码
节拍数
1
1/4节拍
1
1/8拍
2
2/4节拍
2
1/4拍
3
3/4节拍
3
3/8拍
4
1拍
4
1/2拍
5
1又1/4节拍
5
5/8拍
6
1又1/2节拍
6
3/4拍
8
2拍
8
1拍
A
2又1/2节拍
A
1又1/节拍
C
3拍
C
1又1/2节拍
F
3又3/4节拍
表5.2简谱对应的简谱码、T值、节拍数
简谱
发音
简谱码
T值
节拍码
节拍数
5
低音SO
1
64260
1
1/4拍
6
低音LA
2
64400
2
2/4拍
7
低音TI
3
64524
3
3/4拍
1
中音DO
4
64580
4
1拍
2
中音RE
5
64684
5
1又1/4拍
3
中音MI
6
64777
6
1又2/1拍
4
中音FA
7
64820
8
2拍
5
中音SO
8
64898
A
2又1/2拍
6
中音LA
9
64968
C
3拍
7
中音TI
A
65030
F
3又3/4拍
1
高音DO
B
65058
2
高音RE
C
65110
3
高音MI
D
65157
4
高音FA
E
65178
5
高音SO
F
65217
不发音
0
5.3音乐程序
#include
#defineucharunsignedchar
#defineulongunsignedlong
#definetrue1
#definefalse0
sbitspeaker=P2^2;//扬声器驱动位
sbitP1_0=P3^2;//选歌开关
sbitP1_1=P3^3;//选歌开关
sbitpause=P3^5;//暂停开关
uchartemp;
uchartimer_h,timer_l,time;
codeuchartab[]={0x79,0x24,0x30,0x19};//字形表0-3
codeucharfre_h[]={0x00,
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
};//音调表高8位
codeucharfre_l[]={0x00,
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
};//音调表低8位
codeucharptr[][260]={
{
5,1,2,5,1,2,5,1,2,5,1,2,3,1,2,
4,1,2,5,1,6,7,1,6,6,1,2,6,1,2,
6,1,2,6,1,2,4,1,2,6,1,2,5,1,12,
5,1,2,5,1,2,5,1,2,5,1,2,7,1,2,
6,1,2,4,1,6,4,1,4,0,0,2,4,1,2,
4,1,2,4,1,2,4,1,2,3,1,3,2,1,1,
1,1,10,0,0,2,1,2,2,1,2,2,1,2,2,
1,2,2,5,1,2,6,1,2,1,2,4,1,2,2,
3,2,6,2,2,2,2,2,2,2,2,2,2,2,3,
1,2,1,7,1,2,6,1,12,7,1,2,7,1,2,
7,1,2,7,1,2,7,1,2,1,2,2,2,2,6,
5,1,4,0,0,2,7,1,2,7,1,2,1,2,2,
2,2,2,1,2,2,7,1,2,1,2,12,0,0,32,
0,0,0
},//同桌的你
{
0,0,12,6,1,2,7,1,2,1,2,6,7,1,2,
1,2,4,3,2,4,7,1,12,3,1,2,3,1,2,
6,1,6,5,1,2,6,1,4,1,2,4,5,1,12,
3,1,4,4,1,6,3,1,2,6,1,4,1,2,4,
3,1,8,0,0,2,1,2,2,1,2,2,1,2,2,
7,1,6,4,1,2,4,1,4,7,1,4,7,1,8,
0,0,4,6,1,2,7,1,2,1,2,6,7,1,2,
1,2,4,3,2,4,7,1,12,3,1,2,3,1,2,
6,1,6,5,1,2,6,1,4,1,2,4,5,1,12,
2,1,2,3,1,2,4,1,4,1,2,2,7,1,4,
1,2,6,2,2,2,2,2,2,3,2,2,1,2,10,
1,2,2,7,1,2,6,1,2,6,1,2,7,1,4,
5,1,4,6,1,12,0,0,32,0,0,0
},//天空之城
{
6,0,2,6,0,2,1,1,2,2,1,2,3,1,6,
5,1,2,3,1,2,1,1,2,2,1,4,6,0,8,
0,0,2,1,1,2,2,1,2,3,1,2,5,1,6,
5,1,2,6,1,4,2,1,4,3,1,8,3,1,4,
3,1,2,5,1,2,6,1,8,5,1,6,6,1,2,
1,2,2,7,1,1,6,1,1,5,1,2,6,1,2,
3,1,4,1,1,2,2,1,1,2,1,1,3,1,6,
5,1,2,1,1,2,1,1,2,6,0,2,1,1,2,
2,1,1,2,1,1,3,1,2,6,1,2,5,1,12,
0,0,4,3,1,8,6,1,6,6,1,2,5,1,2,
4,1,2,3,1,4,2,1,8,3,1,6,5,1,2,
6,0,2,1,1,2,2,1,4,0,0,4,1,1,2,
2,1,2,3,1,4,3,1,3,5,1,1,6,1,4,
1,2,4,7,1,2,6,1,2,5,1,2,3,1,2,
6,1,32,0,0,32,0,0,0
},//让我们荡起双桨
{
1,1,4,5,1,4,4,1,4,3,1,7,0,0,1,
3,1,4,4,1,2,3,1,9,0,0,1,3,1,4,
4,1,4,3,1,4,4,1,4,3,1,4,2,1,2,
1,1,6,0,0,4,1,1,4,3,1,4,5,1,4,
6,1,11,0,0,1,6,1,2,6,1,2,5,1,4,
2,1,4,2,1,4,4,1,2,3,1,18,1,1,4,
3,1,4,5,1,4,6,1,11,0,0,1,6,1,2,
6,1,2,5,1,4,2,1,4,2,1,4,4,1,4,
3,1,4,4,1,4,3,1,4,2,1,4,1,1,7,
0,0,1,2,1,4,3,1,4,6,0,7,0,0,1,
6,0,4,7,0,4,1,1,8,7,0,4,1,1,20,
0,0,32,0,0,0
}//童话
};
voiddelay(uchart)//延迟函数
{
uchart1;
ulongt2;
for(t1=0;t1for(t2=0;t2<3000;++t2);//6ms
TR0=false;
}
voiddelay50()////去抖延时函数10ms
{
uchari,j;
for(i=20;i>0;i--)
for(j=250;j>0;j--);
}
voidplay()//播放函数
{
TH0=timer_h;//读入初值
TL0=timer_l;
TR0=true;
delay(time);//延时
}
uchargetKey()//按键检测
{
if(P1_0==0)//判断前一曲键是否按下
{
delay50();//10ms延时
if(P1_0==0)
{while(!
P1_0);//判断松手
return1;}
}
if(P1_1==0)//判断后一曲键是否按下
{
delay50();//10ms延时
if(P1_1==0)
{while(!
P1_1);
return2;}
}
if(pause==0)//判断暂停键是否按下
{
delay50();//10ms延时
if(pause==0)
{while(!
pause);
return3;}
}
return0;
}
intmain()
{
uchark,i,lstKey,cnt;//K选音节
ucharstop;
P1=0xff;
TMOD=0x01;
ET0=1;
EA=1;
time=1;
i=0;
while
(1)
{
while(time||k+time==0)
{temp=getKey();
switch(temp)
{
case1:
{if(cnt==0)cnt=3;
elsecnt--;
}break;
case2:
{cnt++;
if(cnt>3)cnt=0;
}break;
case3:
{
stop=~stop;
}break;
}
temp=0;
if(~stop)continue;//若暂停开关打开则不播放
P1=tab[cnt];//更新数码管显示
if(k+time==0)//判断歌曲是否改变及是否播放完
{cnt++;
if(cnt>3)cnt=0;
i=0;//重新定位歌曲到开头
time=1;
lstKey=cnt;
delay
(2);
continue;
}
elseif(cnt!
=lstKey)
{
if(cnt>3)cnt=0;
i=0;//重新定位歌曲到开头
time=1;
lstKey=cnt;
delay
(2);
continue;
}
k=ptr[cnt][i]+7*ptr[cnt][i+1];//取得频率表索引
timer_h=fre_h[k];//取得计时器数据
timer_l=fre_l[k];