音乐盒设计Word文档下载推荐.docx
《音乐盒设计Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《音乐盒设计Word文档下载推荐.docx(12页珍藏版)》请在冰豆网上搜索。
sbitwela=P2^7;
sbitE=P3^4;
sbitRS=P3^5;
sbitRW=P3^6;
sbitBF=P0^7;
//忙碌标志位,,将BF位定义为P0.7引脚
ucharkey1,key2,nn,temp,temp2;
Ucharcode
shu[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
ucharkey[4][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11},{12,13,14,15}};
//--------------------------------------
//单片机晶振采用11.0592MHz
//频率-半周期数据表高八位本软件共保存了四个八度的28个频率数据
codeunsignedcharFREQH[]={
0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,//低音1234567
0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC,//1,2,3,4,5,6,7,i
0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,//高音234567
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF};
//超高音1234567
//频率-半周期数据表低八位
codeunsignedcharFREQL[]={
0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,//低音1234567
0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F,//1,2,3,4,5,6,7,i
0xEE,0x44,0x6B,0xB4,0xF4,0x2D,//高音234567
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16};
//世上只有妈妈好数据表要想演奏不同的乐曲,只需要修改这个数据表
unsignedcharcodesszymmh[4][213]={
//世上只有妈妈好
{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},
//生日快乐
{5,1,1,5,1,1,6,1,2,5,1,2,1,2,2,7,1,4,
5,1,1,5,1,1,6,1,2,5,1,2,2,2,2,1,2,4,
5,1,1,5,1,1,5,2,2,3,2,2,1,2,2,7,1,2,6,1,2,
4,2,1,4,2,1,3,2,2,1,2,2,2,2,2,1,2,4},
//东风破
{6,3,1,3,3,1,5,3,1,2,3,1,3,3,1,1,3,1,2,3,1,
6,2,1,5,2,1,6,2,1,1,3,1,2,3,1,3,3,1,5,3,1,
6,3,4,5,3,2,5,3,2,5,3,2,6,3,3,7,3,1,6,3,2,
5,3,2,3,3,2,3,3,2,3,3,1,2,3,1,2,3,2,2,3,8,
5,3,2,5,3,2,5,3,2,3,3,2,2,3,2,2,3,2,1,3,2,
2,3,2,1,3,2,2,3,2,3,3,2,3,3,10,1,3,2,1,3,2,
2,3,2,3,3,2,2,3,2,3,3,2,5,3,2,6,3,2,5,3,2,
5,3,1,3,3,1,3,3,2,5,3,10,6,3,2,6,3,1,5,3,1,
5,3,2,3,3,3,5,3,1,3,3,1,2,3,1,2,3,4,2,3,2,
2,3,2,1,3,2,3,3,2,2,3,2,1,3,2,6,2,2,1,3,8,
0,0,0},
//简单爱
{5,2,1,1,3,1,2,3,1,3,3,1,2,3,1,3,3,1,4,3,1,
5,3,1,5,3,1,5,3,1,4,3,1,3,3,1,2,3,1,2,3,3,
5,2,1,1,3,1,2,3,1,3,3,1,2,3,1,3,3,1,4,3,1,
5,3,1,5,3,1,5,3,1,6,3,1,5,3,2,3,3,2,1,3,2,
1,3,1,6,2,1,2,3,1,2,3,1,3,3,1,3,3,1,1,3,2,
5,3,1,1,3,1,5,2,1,1,3,1,7,2,1,1,3,3,1,3,1,
6,2,1,2,3,1,2,3,1,3,3,1,3,3,1,4,3,1,4,3,1,
4,3,1,3,3,1,2,3,1,1,3,1,1,3,2,0,0,0}
};
/*****************************************************
函数功能:
延时1ms
***************************************************/
voiddelay1ms()
{
unsignedchara,b;
for(b=1;
b>
0;
b--)
for(a=3;
a>
a--);
}
/*****************************************************
延时若干毫秒
入口参数:
n
voiddelay1(unsignedintn)
{
unsignedinti;
for(i=0;
i<
n;
i++)
delay1ms();
判断液晶模块的忙碌状态
返回值:
result。
result=1,忙碌;
result=0,不忙
bitBusyTest(void)
bitresult;
RS=0;
//根据规定,RS为低电平,RW为高电平时,可以读状态
RW=1;
E=1;
//E=1,才允许读写
_nop_();
//空操作
_nop_();
//空操作四个机器周期,给硬件反应时间
result=BF;
//将忙碌标志电平赋给result
E=0;
returnresult;
将模式设置指令或显示地址写入液晶模块
dictate
voidWrite_com(unsignedchardictate)
{
while(BusyTest()==1);
//如果忙就等待
//根据规定,RS和R/W同时为低电平时,可以写入指令
RW=0;
E=0;
//E置低电平(写指令时,
//就是让E从0到1发生正跳变,所以应先置"
0"
_nop_();
//空操作两个机器周期,给硬件反应时间
P0=dictate;
//将数据送入P0口,即写入指令或地址
//空操作四个机器周期,给硬件反应时间
//E置高电平
//当E由高电平跳变成低电平时,液晶模块开始执行命令
指定字符显示的实际地址
x
voidWriteAddress(unsignedcharx)
Write_com(x|0x80);
//显示位置的确定方法规定为"
80H+地址码x"
将数据(字符的标准ASCII码)写入液晶模块
y(为字符常量)
voidwridata(unsignedchary)
RS=1;
//RS为高电平,RW为低电平时,可以写入数据
//E置低电平(写指令时,,
P0=y;
//将数据送入P0口,即将数据写入液晶模块
对LCD的显示模式进行初始化设置
voidLcdInt(void)
delay1(15);
//延时15ms,首次写指令时应给LCD一段较长的反应时间
Write_com(0x38);
//显示模式设置:
16×
2显示,5×
7点阵,8位数据接口
delay1(5);
//延时5ms
Write_com(0x38);
//3次写设置模式
Write_com(0x0F);
显示开,有光标,光标闪烁
Write_com(0x06);
光标右移,字符不移
Write_com(0x01);
//清屏幕指令,将以前的显示内容清除
voiddis_num(){
Write_com(0x01);
//显示清零
delay1(5);
WriteAddress(0);
switch(key[key1][key2])
case0:
wridata(1+48);
break;
case1:
wridata(2+48);
case2:
wridata(3+48);
case3:
wridata(4+48);
case4:
wridata(5+48);
case5:
wridata(6+48);
case6:
wridata(7+48);
case7:
wridata(8+48);
case8:
wridata(9+48);
case9:
wridata(10+48);
case10:
wridata(11+48);
case11:
wridata(12+48);
case12:
wridata(13+48);
case13:
wridata(14+48);
case14:
wridata(15+48);
case15:
wridata(16+48);
}
/*于键消抖的延时函数*/
voiddelay5()
{uintt;
for(t=400;
t>
t--);
}
voidatime(uintk)
uinti,j;
for(i=k;
i>
i--)
for(j=110;
j>
j--);
voidint_0()interrupt0//紧急情况中断即现实暂停
unsignedchari,k,I,K;
//现场保护
I=i;
K=k;
while(zt);
zt=1;
//回复现场
i=I;
k=K;
//--------------------------------------------------------------------------------------------------------
voidint_1()interrupt2//优先中断即现实继续播放
zt=0;
voidkey_scanf(){
P1=0x0f;
temp=P1;
if(temp!
=0x0f)
delay5();
//消抖
atime(10);
if(temp==P1)
{
nn=temp|0xf0;
P1=nn;
temp2=P1;
temp2=temp2&
0xf0;
switch(temp)
{
case0x0e:
key1=0;
case0x0d:
key1=1;
case0x0b:
key1=2;
case0x07:
key1=3;
}
switch(temp2)
case0xe0:
key2=0;
case0xd0:
key2=1;
case0xb0:
key2=2;
case0x70:
key2=3;
dis_num();
while(P1!
=nn);
}
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中断去发音
key_scanf();
//关闭T0,停止发音
voidsong()//演奏一个音符
//控制音调
//启动T0,由T0输出方波去发音
delay(time);
//控制时间长度
voidmain(void)
unsignedchark,i;
LcdInt();
TMOD=1;
//置T0定时工作方式1
ET0=1;
//开T0中断
EA=1;
//开CPU中断
EX0=1;
//开外部中断0
IT0=0;
EX1=1;
//开外部中断1
IT1=1;
PX1=1;
//开优先中断
while
(1){
i=0;
time=1;
while(time){
k=sszymmh[key[key1][key2]][i]+7*sszymmh[key[key1][key2]][i+1]-1;
//第i个是音符,第i+1个是第几个八度
timer0h=FREQH[k];
//从数据表中读出频率数值
timer0l=FREQL[k];
//实际上,是定时的时间长度
time=sszymmh[key[key1][key2]][i+2];
//读出时间长度数值
i+=3;
song();
}}}//发出一个音符