課程設計:電子琴(世上只有媽媽好)
本文引用地址:http://butianyuan.cn/article/201609/296962.htm
//proteus仿真
//單片機發(fā)生,就是用蜂鳴器簡單的模擬歌曲的音調(用定時器來實現(xiàn)),并不是唱出歌曲(目前51我還沒有聽說過)
//主程序如下,實現(xiàn)功能是按下某個鍵后,數(shù)碼管顯示對應的按鍵號,如果是前三個鍵的話,發(fā)出(dao,ruai,mi)音符
//如果是第四個鍵的話,發(fā)出(世上只有媽媽好的歌曲音調)
//程序如下
#include
#define uchar unsigned char
sbit dula=P2^6; //如果是用實物的話,用到了
sbit wela=P2^7; //鎖存器如果是proteu的話,就不需要了
sbit sound=P2^3; //定義蜂鳴器引腳
unsigned char i,j,key,k,m,time;
uchar STH0,STL0;
//共陽極數(shù)碼管編碼值
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
//1,2,3,4對應的編碼值
unsigned char code music[]={0x25,0x57,0x84,0x98};
//位選編碼(這個也是如果是proteus的話,就不需要了,如果是實物的話,需要)
uchar code table1[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//世上只有媽媽好數(shù)據(jù)表
code unsigned char sszymmh[]={
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
};
// 音階頻率表 高八位
code unsigned char FREQH[]={
0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,
0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, //1,2,3,4,5,6,7,8,i
0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,
} ;
// 音階頻率表 低八位
code unsigned char FREQL[]={
0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, //1,2,3,4,5,6,7,8,i
0xEE,0x44, 0x6B,0xB4,0xF4,0x2D,
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,
};
//函數(shù)聲明
void display(uchar Duan_value,uchar Wei_value);
void delay(unsigned char t);
void delay1(uchar );
void display1(uchar value);
//播放歌曲音符函數(shù)
void song()
{
TH0=STH0;
TL0=STL0;
TR0=1;
delay1(time); //這個延時很重要,用來使某個音符放多長時間
}
//設置對應按鍵定時器初值函數(shù)
void key_on(unsigned char key)
{
m=0;
if(key!=3)
{
TMOD=0x01; //設置定時工作方式位t0方式1(16位定時器)
TH0=0xfe;
TL0=music[key]; //定時器附初值(根據(jù)音符對應的編碼)
EA=1; //一次打開各個中斷
ET0=1;
TR0=1;
display1(key+1);
while(P3!=0xff); //按鍵按起去抖動
TR0=0;
}
else //第四個鍵按下之后,來播放歌曲
{
TMOD=0x01; //設置定時工作方式位t0方式1(16位定時器)
TH0=0xfe;
TL0=music[key]; //定時器附初值(根據(jù)音符對應的編碼)
EA=1; //一次打開各個中斷
ET0=1;
TR0=0;
display1(key+1);
while(P3!=0xff); //按鍵按起去抖動
time=1;
while(time!=0) //歌曲播放完之后,time=0退出(終止符)
{
k=sszymmh[m]+7*sszymmh[m+1]-1;
STH0=FREQH[k];
STL0=FREQL[k];
time=sszymmh[m+2]; //這個模式是固定的,不用過多研究為啥+2
m=m+3;
song();
}
}
}
/*函數(shù)功能:播放音樂的節(jié)拍控制*/
void delay1(unsigned char t)
{
unsigned char t1;
unsigned long t2;
for(t1=0;t1
{
for(t2=0;t2<8000;t2++)
{
;
}
}
TR0=0;
}
//延時函數(shù)(單位ms)
void delay(unsigned char t)
{
unsigned char x,y;
for(x=t;t>0;t--)
for(y=111;y>0;y--);
}
//顯示對應位選的數(shù)碼管按鍵值(如果是實物的話所用到的)
/*void display(uchar Duan_value,uchar Wei_value)
{
dula=1;
P0=table[Duan_value];
dula=0;
wela=1;
P0=table1[Wei_value];
wela=0;
delay(3);
}*/
//顯示函數(shù)
void display1(uchar value)
{
P0=table[value];
}
void main()
{
display1(key);
while(1)
{
if(P3==0xef) //第一個鍵按下
{
delay(10); //按鍵按下消抖
if(P3==0xef)
{
key=0;
key_on(key); //檢測按鍵按下(并且在函數(shù)中來顯示數(shù)據(jù))
}
}
if(P3==0xdf) //第二個鍵按下
{
delay(10); //按鍵按下消抖
if(P3==0xdf)
{
key=1;
key_on(key);
}
}
if(P3==0xbf) //第三個鍵按下
{
delay(10);
if(P3==0xbf)
{
key=2;
key_on(key);
}
}
if(P3==0x7f) //第四個鍵按下
{
delay(10);
if(P3==0x7f)
{
key=3;
key_on(key);
}
}
}
}
//定時器1中斷函數(shù)
void t0() interrupt 1
{
if(key!=3)
{
TH0=0xfe;
TL0=music[key];
}
else
{
TH0=STH0;
TL0=STL0;
}
sound=~sound; //蜂鳴器取反(產生脈沖)
}
評論