基于单片机数字音乐盒的设计.docx
《基于单片机数字音乐盒的设计.docx》由会员分享,可在线阅读,更多相关《基于单片机数字音乐盒的设计.docx(18页珍藏版)》请在冰豆网上搜索。
基于单片机数字音乐盒的设计
单片机实物设计
题目:
单片机音乐盒设计
班级:
K0312416-17
姓名:
湛俊朱斌杨裕庆
学号:
摘要
本设计是一个基于STC89C51RC系列单片机的音乐盒,依据单片机技术原理,通过硬件电路制作以及软件编译,设计制作出一个多功能多功能音乐盒。
该音乐盒主要由按键电路、复位电路、时钟电路以及蜂鸣器组成。
本音乐盒共有四首歌曲,用4个按键控制。
播放歌曲时,蜂鸣器发出某个音调。
本设计利用KEIL编程软件对音乐盒源程序进行编程并调试,配合PROTEUS仿真软件对硬件进行仿真调试,节约了设计时间。
【关键词】STC89C51RC按键蜂鸣器LCD1602液晶
前言
第一章工作原理
1.1设计目标
第二章软件设计与分析
2.1软件设计的组成
2.2各部分软件分析
2.2.1延时165MS,即十六分音符子函数
2.2.2延时1MS子函数
2.2.3定时器0中断子函数
2.2.4播放音乐子函数
2.5定时器1中断子函数
2.6按键扫描子函数
2.2.7主函数
2.3总源程序
第三章软件仿真
3.仿真图
3.1元件清单
总结
参考文献
第一章工作原理
1.1设计目标
具体要求是:
以单片机为核心,设计一个数字音乐盒:
利用I/O口产生一定频率的方波,驱动蜂鸣器,发出不同的音调,从而演奏乐曲(最少3首乐曲,每首不少于30s)。
采用LCD显示信息。
a.开机时有英文欢迎提示字符,播放时显示歌曲序号(或名称)。
b.可通过功能键选择乐曲、暂停、播放。
第二章软件设计与分析
2.1软件设计的组成
该系统由延时165MS,即十六分音符子函数、延时1MS子函数、按键扫描子函数、播放音乐子函数、定时器1中断子函数、定时器0中断子函数、主函数和数据定义这几部分组成。
2.2各部分软件分析
2.2.1延时165MS,即十六分音符子函数
//延时165MS,即十六分音符子函数
voiddelay1(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=19000;y>0;y--);
}
2.2.2延时1MS子函数
//延时1MS子函数
voiddelay2(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
2.2.3定时器0中断子函数
//定时器0中断子函数
voidt0()interrupt1//用于产生各种音调
{
TH0=a;
TL0=b;
BEEP=~BEEP;
}
2.2.4播放音乐子函数
//播放音乐子函数
voidsong()
{
uinttemp;
ucharaa;//aa是简谱
c=0;
while
(1)
{
if(count2==0)
{
break;
}
if(count2==1)//选曲
temp=table1[c];
if(count2==2)
temp=table2[c];
if(count2==3)
temp=table3[c];
if(count2==4)
temp=table4[c];
if(temp==0xff)
break;
aa=temp/16;//取数的高4位
if(aa!
=0)
{
a=cuzhi[aa*2];
b=cuzhi[aa*2+1];
}
else
{
TR1=0;
BEEP=1;//关蜂鸣器
}
delay1(temp%16);//取数的低4位
TR1=0;//唱完一个音停10MS
BEEP=1;
delay2(10);
TR1=1;
c++;
}
TR1=0;
BEEP=1;
}
2.2.5定时器1中断子函数
//定时器1中断子函数
voidt1()interrupt3//用于产生各种音调
{
key();
}
2.2.6按键扫描子函数
voidkey()
{
if(k3==0)
{
delay2(10);
if(k3==0)
{
num1++;
if(num1==1)
{
TR1=0;
aa=count2;
count2=0;
}
if(num1==2)
{
num1=0;
count2=aa;
TR1=1;
}
while(!
k3);
}
}
if(k4==0)
{
delay2(10);
if(k4==0)
{
TR1=0;
count2=0;
c=0;
write_com(0x01);//清屏
write_com(0x80+0);
write_date('W');
write_com(0x80+1);
write_date('e');
write_com(0x80+2);
write_date('l');
write_com(0x80+3);
write_date('c');
write_com(0x80+4);
write_date('o');
write_com(0x80+5);
write_date('m');
write_com(0x80+6);
write_date('e');
write_com(0x80+7);
write_date('');
write_com(0x80+8);
write_date('t');
write_com(0x80+9);
write_date('o');
write_com(0x80+10);
write_date('');
write_com(0x80+11);
write_date('u');
write_com(0x80+12);
2.2.7主函数
//主函数
voidmain()
{
TMOD=0x10;//定时器0工作在方式1
TH1=0;
TL1=0;
ET1=1;
EA=1;//开总中断
EX1=1;//开外部中断1
IT1=1;//下降沿时触发中断
EX0=1;//开外部中断0
IT0=1;//下降沿时触发中断
count2=0;//唱第一首歌
LCD1602_init();
while
(1)//大循环
{
song();
}
}
2.3总源程序
#include//51单片机头文件
typedefunsignedcharuchar;
typedefunsignedintuint;
sbitRS=P2^7;//LCD1602数据/命令选择端(H/L)
sbitRW=P2^6;//LCD1602读/写选择端(H/L)
sbitE=P2^5;//LCD1602使能信号端
sbitBEEP=P2^0;//蜂鸣器接口
sbitk1=P3^2;//下一首
sbitk2=P3^3;//上一首
sbitk3=P2^1;//播放/暂停
sbitk4=P2^2;//复位
charcount2;//歌曲标志
uchara,b,c,aa,num;
ucharnum1,num2;
//---------------------------简谱---------------------------------------
//编程规则:
字节高位是简谱,低位是持续时间,
//代表多少个十六分音符
//1-7代表中央C调,8-E代表高八度,0代表停顿
//最后的0是结束标志
ucharcodetable1[]={//千年之恋
0x12,0x22,0x34,0x84,0x74,0x54,0x38,0x42,0x32,0x22,0x42,0x34,0x84,0x72,0x82,0x94,0xA8,0x08,//前奏
0x32,0x31,0x21,0x32,0x52,0x32,0x31,0x21,0x32,0x62,//竹林的灯火到过的沙漠
0x32,0x31,0x21,0x32,0x82,0x71,0x81,0x71,0x51,0x32,0x22,//七色的国度不断飘逸风中
0x32,0x31,0x21,0x32,0x52,0x32,0x31,0x21,0x32,0x62,//有一种神秘灰色的旋涡
0x32,0x31,0x21,0x32,0x83,0x82,0x71,0x72,0x02,//将我卷入了迷雾中
0x63,0xA1,0xA2,0x62,0x92,0x82,0x52,//看不清的双手
0x31,0x51,0x63,0x51,0x63,0x51,0x63,0x51,0x62,0x82,0x7C,0x02,//一朵花传来谁经过的温柔
0x61,0x71,0x82,0x71,0x62,0xA2,0x71,0x76,//穿越千年的伤痛
0x61,0x71,0x82,0x71,0x62,0x52,0x31,0x36,//只为求一个结果
0x61,0x71,0x82,0x71,0x62,0xA3,0x73,0x62,0x53,//你留下的轮廓指引我
0x42,0x63,0x83,0x83,0x91,0x91,//黑夜中不寂寞
0x61,0x71,0x82,0x71,0x62,0x0A2,0x71,0x76,//穿越千年的哀愁
0x61,0x71,0x82,0x71,0x62,0x52,0x31,0x36,//是你在尽头等我
0x61,0x71,0x82,0x71,0x62,0xA3,0x73,0x62,0x53,//最美丽的感动会值得
0x42,0x82,0x88,0x02,0x74,0x93,0x89,0xff//结束标?
//睾?
};
ucharcodetable2[]={//寂寞沙洲冷
0x12,0x12,0x22,0x32,0x31,0x22,0x21,0x22,//自你走后心憔悴
0x21,0x31,0x51,0x52,0x31,0x52,0x61,0x15,0x14,//白色油桐风中纷飞
0x51,0x52,0x31,0x52,0x62,0x13,0x11,0x13,0x32,0x28,0x08,0x28,//落花似人有情这个季节
0x31,0x32,0x31,0x32,0x11,0x21,0x51,0x52,0x51,0x52,//河畔的风放肆拼命地吹
0x51,0x51,0x31,0x32,0x31,0x32,0x81,0x72,0x63,//不断拨弄离人的眼泪
0x62,0x71,0x81,0x72,0x61,0x61,0x52,0x31,0x21,0x32,0x51,0x54,//那样浓烈的爱再也无法给
0x22,0x12,0x11,0x12,0x11,0x12,0x12,0x14,0x26,0x32,0x26,//伤感一夜一夜
0x32,0x61,0x51,0x51,0x31,0x31,0x21,0x31,0x51,0x61,0x51,0x31,0x51,//当记忆的线缠绕过往支离破碎
0x02,0x32,0x81,0x81,0x81,0x81,0x62,0x52,0x34,//是慌乱占据了心扉
0x31,0x81,0x81,0x81,0x61,0x91,0x82,//有花儿伴着蝴蝶
0x51,0x51,0x51,0x51,0x31,0x61,0x53,//孤雁可以双飞
0x21,0x11,0x21,0x11,0x22,0x11,0x21,0x26,//夜深人静独徘徊
0x32,0x61,0x51,0x51,0x31,0x31,0x21,0x31,0x51,0x61,0x51,0x31,0x51,0x52,//当幸福恋人寄来红色分享喜悦
0x31,0x31,0x81,0x81,0x81,0x61,0x91,0x81,0x61,0x31,0x56,//闭上双眼难过头也不敢回
0x32,0x32,0x81,0x81,0x81,0x81,0x91,0x81,0x61,0x81,0x61,0x51,0x31,0x51,0x34,//仍然捡尽寒枝不肯安歇微带着后悔
0x21,0x31,0x51,0x31,0x21,0x11,0x61,0x21,0x16,//寂寞沙洲我该思念谁
0xff
};
ucharcodetable3[]={
0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,
0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,
0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,
0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,
0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,
0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,
0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,
0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,
0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,
0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,
0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,
0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0xff,
};
ucharcodetable4[]={
0x30,0x1C,0x10,0x20,0x40,0x1C,0x10,0x18,0x10,0x20,0x10,0x1C,0x10,0x18,0x40,0x1C,
0x20,0x20,0x20,0x1C,0x20,0x18,0x20,0x20,0x80,0xFF,0x20,0x30,0x1C,0x10,0x18,0x20,
0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,
0x30,0x80,0xFF,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,
0x20,0x2B,0x40,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,
0x20,0x2B,0x40,0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,
0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0x20,0x30,0x1C,0x10,0x20,
0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x15,0x1F,
0x05,0x20,0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,
0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,
0x20,0x26,0x20,0x20,0x20,0x30,0x30,0x20,0x30,0x1C,0x10,0x18,0x40,0x1C,0x20,0x20,
0x20,0x26,0x40,0x13,0x60,0x18,0x20,0x15,0x40,0x13,0x40,0x18,0x80,0xff,
};
//简谱音调对应的定时器初值
//适合12的晶振
ucharcodecuzhi[]={
0xff,0xff,//占位
0xFC,0x8E,//中央C调1-7
0xFC,0xED,
0xFD,0x43,
0xFD,0x6A,
0xFD,0xB3,
0xFD,0xF3,
0xFE,0x2D,
0xFE,0x47,//高八度1-7
0xFE,0x76,
0xFE,0xA1,
0xFE,0xC7,
0xFE,0xD9,
0xFE,0xF9,
0xFF,0x16
};
ucharcodeyinyue[]={0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0x00,0x00};
//将音调转化为对应的LED样式
//延时165MS,即十六分音符子函数
voiddelay1(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=19000;y>0;y--);
}
//延时1MS子函数
voiddelay2(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//LCD1602液晶写命令子函数
voidwrite_com(ucharcom)
{
RS=0;//选择写指令
RW=0;
E=0;
P0=com;
E=1;
delay2(5);//无延时不能正常工作
E=0;
}
//LCD1602液晶写数据子函数
voidwrite_date(uchardate)
{
RS=1;//选择写数据
RW=0;
E=0;
P0=date;
E=1;
delay2(5);//无延时不能正常工作
E=0;
}
//LCD1602液晶初始化子函数
voidLCD1602_init()//初始化
{
delay2(15);
//主函数
voidmain()
{
TMOD=0x11;//定时器0工作在方式1
TH1=0;
TL1=0;
ET1=1;
TH0=0;
TL0=0;
ET0=1;
TR0=1;
EA=1;//开总中断
EX1=1;//开外部中断1
IT1=1;//下降沿时触发中断
EX0=1;//开外部中断0
IT0=1;//下降沿时触发中断
count2=0;//唱第一首歌
LCD1602_init();
while
(1)//大循环
{
song();
}
}
//定时器0中断子函数
voidt0()interrupt1
{
num2++;
if(num2==5)
{
num2=0;
key();
}
}
//定时器1中断子函数
voidt1()interrupt3//用于产生各种音调
{
TH1=a;
TL1=b;
BEEP=~BEEP;
}
voidwb0()interrupt0
{
TR1=0;
if(k1==0)
{
delay2(10);
if(k1==0)
{
count2++;
c=0;//从头开始唱
if(count2==1)
{
write_com(0x01);
delay2(10);
write_com(0x80+0);
write_date('');
write_com(0x80+1);
write_date('');
write_com(0x80+2);
write_date('');
write_com(0x80+3);
write_com(0xc0+8);
write_date('');
write_com(0xc0+9);
write_date('f');
write_com(0xc0+10);
write_date('l');
write_com(0xc0+11);
write_date('o');
write_com(0xc0+12);
write_date('w');
write_com(0xc0+13);
write_date('e');
write_co