单片机原理与应用课程设计-基于单片机的音乐跑马灯设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单片机原理与应用
课程设计
设计课题:音乐跑马灯
班级:
小组成员:
时间:2013年1月6日
音乐跑马灯的设计
一、实验内容:
1.使用8个发光管作跑马灯,其中有3种亮灭模式。
2.有专门的开关K1~K3用来切换跑马灯的模式。
3.每一种跑马灯模式用LED数码管进行显示1、2、3。
4.当跑马灯处于某种模式时,有对应的音乐响起。
有三首曲子可以选着。
提示:亮灭模式自己设计,可以从速度或者点亮方法上设计。
响音乐的程序可以参考实验手册上《电子音响》部分。
二、实验原理:
用三个开关控制音乐跑马灯的三种模式,每一种模式都是在LED数码管显示模式的号码的同时先响音乐后闪灯。
跑马灯采用P3口作为输入口,外接三个开关用来控制跑马灯的亮灭模式。
P1口做输出口,P1口接的8个发光二极管L1~L8按16进制方式点亮发光二极管,即8个发光管相当于8位的二进制位。
当数值为1时,L1点亮;数值为2=00000010B时,L2点亮;数值为4=00000100时,L3点亮,依次类推。
不同的音符对应不同的频率,所以只要用不同频率的信号驱动喇叭,就能发出不同的音符了,所以转换为使用定时器在P1.7引脚输出某一频率的方波脉冲即可。
单片机演奏音乐基本都是单音频率,它不包含相应幅度的谐波频率,因此单片机奏乐只需弄清楚两个概念,也就是“音调”和“节拍”。
音调表示一个音符唱多高的频率,节拍表示一个音符唱多长的时间,乐谱中每一个音符都与某一个特定的频率相对应,所以只需要产生不同频率的方波信号(产生不同音调),并且延时不同的时间(产生不同节拍),即可完成音乐的播放。
三、硬件原理:
1.跑马灯亮灭模式原理图,如图(1)所示。
图(1) 跑马灯亮灭模式原理图
2.让喇叭响音乐的原理图,如图(2)所示。
图(2) 电子音响原理图
3.使第三个LED数码管显示1、2、3、4、5,如图(3)和(4)所示。
图(3) LED共阳极连接原理图
图(4) LED数据显示示意图
用三个开关(K1~K3)控制音乐跑马灯的三种模式,每一种模式都是在LED 数码管显示模式的号码的同时先响音乐后闪灯。
音乐跑马灯采用P3口作为输入口,外接三个开关用来控制音乐跑马灯的亮灭模式。
P1口作为输出口,P1口接的8个发光二极管L1~L8按16进制方式点亮发光二极管,即8个发光管相当于8位的二进制位。
当数值为1时,L1点亮;数值为2=00000010B时,L2点亮;数值为4=00000100时,L3点亮,依次类推。
不同的音符对应不同的频率,所以只要用不同频率的信号驱动喇叭,就能发出不同的音符了,所以转换为使用定时器在P1.7引脚输出某一频率的方波脉冲即可。
四、软件原理:
1.LED数据显示程序部分
建立LED显示灯数组:
unsigned char code table1[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char code table2[]={0x81,0x42,0x24,0x18};
方式一数码管显示1时LED灯点亮方式:
void liang1()
{
int i;
for(i=0;i<8;i++)
{
if(K1==1)
{P1=table1[i];
delayms(80) ; }
P1=0xFF;
}
}
方式二数码管显示2时LED灯点亮方式
void liang2()
{
int i;
for(i=7;i>=0;i--)
{
if(K2==1)
{P1=table1[i];
delayms(80) ;}
P1=0xFF;
}
}
方式三数码管显示3时LED灯点亮方式
void liang3()
{
int i;
for(i=0;i<4;i++)
{
if(K3==1)
{
P1=table2[i];
delayms(80) ;}
P1=0xFF;
}
}
2.电子音响部分的程序
生日快乐歌的音符频率表:
uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159, 212,212,106,126,159,169,190,119,119,126,159,142,159,0};
生日快乐歌节拍表:
uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,
9,3,12,12,12,12,12,9,3,12,12,12,24,0};
音乐一演奏模式
void PlayMusic1()
{
uint i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
{
if(K1==1)
{
for(j=0;j<SONG_LONG[i]*20;j++)
{
BEEP=~BEEP;
for(k=0;k<SONG_TONE[i]/5;k++);
}
}
delayms(10);
i++;
}
}
音乐二演奏模式
void PlayMusic2()
{
uint i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
{
if(K2==1)
{
for(j=0;j<SONG_LONG[i]*30;j++)
{
BEEP=~BEEP;
for(k=0;k<SONG_TONE[i]/5;k++);
}
}
delayms(10);
i++;
}
}
音乐三演奏模式
void PlayMusic3()
{
uint i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0) {
if(K3==1)
{
for(j=0;j<SONG_LONG[i]*30;j++)
{
BEEP=~BEEP;
for(k=0;k<SONG_TONE[i]/10;k++);
}
}
delayms(10);
i++;
}
}
3.模式选择部分:
sbit K1=P3^0 ;
sbit K2=P3^1 ;
sbit K3=P3^2;
sbit LED0=P1^0 ;
sbit LED1=P1^1 ;
sbit LED2=P1^2 ;
sbit LED3=P1^3 ;
sbit LED4=P1^4 ;
sbit LED5=P1^5 ;
sbit LED6=P1^6 ;
sbit LED7=P1^7 ;
sbit BEEP=P3^3;
五、设计总程序:
#include<reg51.h>
#include<absacc.h>
#define PA XBYTE[0xFF21]
#define PB XBYTE[0xFF22]
#define uchar unsigned char
#define uint unsigned int
unsigned char code table[]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管显示断码,共阳极unsigned char code table1[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//建立8个LED灯每一个的代码。
供点亮方式1和2使用
unsigned char code table2[]={0x81,0x42,0x24,0x18};
// 每次点亮两个LED灯的代码。
供点亮方式3使用
sbit K1=P3^0 ;
sbit K2=P3^1 ;
sbit K3=P3^2;
sbit LED0=P1^0 ;
sbit LED1=P1^1 ;
sbit LED2=P1^2 ;
sbit LED3=P1^3 ;
sbit LED4=P1^4 ;
sbit LED5=P1^5 ;
sbit LED6=P1^6 ;
sbit LED7=P1^7 ;
sbit BEEP=P3^3;
void delayms(unsigned int delay) //延时程序
{
unsigned int i,x;
for (x=0;x<delay;x++)
{
for (i=0;i<100;i++);
}
}
uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159, 212,212,106,126,159,169,190,119,119,126,159,142,159,0};
//生日快乐歌的音符频率表,不同频率由不同的延时来决定uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,
9,3,12,12,12,12,12,9,3,12,12,12,24,0};
//生日快乐歌节拍表,节拍决定每个音符的演奏长短
void PlayMusic1() //播放音乐一函数
{
uint i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
{
if(K1==1)
{
for(j=0;j<SONG_LONG[i]*20;j++)
{
BEEP=~BEEP;
for(k=0;k<SONG_TONE[i]/5;k++);
}
}
delayms(10);
i++;
}
}
void PlayMusic2() //播放音乐二函数
{
uint i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
{
if(K2==1)
{
for(j=0;j<SONG_LONG[i]*30;j++)
{
BEEP=~BEEP;
for(k=0;k<SONG_TONE[i]/5;k++);
}
}
delayms(10);
i++;
}
}
void PlayMusic3() //播放音乐三函数
{
uint i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
{
if(K3==1)
{
for(j=0;j<SONG_LONG[i]*30;j++)
{
BEEP=~BEEP;
for(k=0;k<SONG_TONE[i]/10;k++);
}
}
delayms(10);
i++;
}
}
void liang1() //数码管显示1,利用table1数组显示LED灯{
int i;
for(i=0;i<8;i++) //8个LED灯从左向右依次点亮
{
if(K1==1)
{P1=table1[i];
delayms(80) ; }
P1=0xFF; //点亮模式完成后,让8个LED灯全部点亮
}
}
void liang2() //数码管显示2,利用table1数组显示LED灯
{
int i;
for(i=7;i>=0;i--) //8个LED灯从右向左依次点亮
{
if(K2==1)
{P1=table1[i];
delayms(80) ;}
P1=0xFF;
}
}
void liang3() //数码管显示3,利用table2数组显示LED灯{
int i;
for(i=0;i<4;i++) //8个LED灯从外侧向内侧每两个依次点亮
{
if(K3==1)
{
P1=table2[i];
delayms(80) ;}
P1=0xFF;
}
}
void main() //主函数
{
BEEP=0; //喇叭初始状态
while(1)
{
P1=0x00;
if(K1==1) //按键K1,数码管显示1,播放音乐一
{
XBYTE[0xFF21]=0x08 ; //选择数码管的位置
XBYTE[0xFF22]=table[1]; //数码管显示的数字
Liang1() ;
PlayMusic1();
if(K1==0){P1=0x00;XBYTE[0xFF21]=0x08 ; //松开按键后初始化XBYTE[0xFF22]=table[0];}
}
if(K2==1) //按键K2,数码管显示2,播放音乐二
{
XBYTE[0xFF21]=0x08 ;
XBYTE[0xFF22]=table[2];
Liang2();
PlayMusic2();
if(K2==0){P1=0x00;XBYTE[0xFF21]=0x08 ;
XBYTE[0xFF22]=table[0];}
}
if(K3==1) //按键K3,数码管显示3,播放音乐三
{
XBYTE[0xFF21]=0x08 ;
XBYTE[0xFF22]=table[3];
Liang3();
PlayMusic3();
if(K3==0){P1=0x00;XBYTE[0xFF21]=0x08;
XBYTE[0xFF22]=table[0];}
}
}
}
六、设计的优缺点:
1.优点:
实验设计的程序简单,易于理解。
经过调试后,程序能够按照预期的功能,通过开关K1~K3在三种模式之间正常切换,LED显示相应的数值,自动播放相应的音乐,并且跑马灯按照相应的模式闪亮。
2.缺点:
设计的LED灯点亮方式有缺陷,只能进行一次点亮循环,设计出的跑马灯是先亮灯后播放音乐,没有在响音乐的同时就闪灯。
程序较长,循环较少。
七、实验心得
通过这次单片机课程设计,我们选择了音乐跑马灯这个课题,刚开始是有些摸不着头脑,但通过老师的知道和自己的资料查询,逐渐对这个课题有了实际性的作用,通过自己对程序的编写和调试,加深了对单片机知识和模块知识的巩固理解和知识总结。
通过自己的实际操作得到的东西远远比理解书面意思要容易的多也有趣得多,最让我觉得有些遗憾的是,自己本身对于中断的理解就不是很明白,就用了简单的程序循环来完成了这个实验,没有用到中断,对中断还是没有实践性的理解。
10。