
头衔:未定义
等级:小学生
帖数:15
金钱:185
S币:3
|
|
收藏 举报 1F 资料 | 留言 | 编辑 | 引用 | 评帖 | 主页
发一个用蜂鸣器唱歌的程序
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit BUZZ = P1^1;
uchar Time_H = 0;
uchar Time_L = 0;
#define YF_YF 160
#define SFYF_JG 4/5// 原始频率表,低音。
uint code FreTab[12]=
{
262,
277,
293,
311,
329,
349,
370,
392,
415,
440,
466,
494
};
// 1-7.
uchar code XY_Tab[7]=
{0,2,4,5,7,9,11};
uint New_FreTab[12];
uchar YC_Tab[]=
{1,2,4,8,16,32,64};
//同一首歌
uchar code MusicSame[]={ 0x0F,0x01, 0x15,0x02, 0x16,0x02, 0x17,0x66, 0x18,0x03,
0x17,0x02, 0x15,0x02, 0x16,0x01, 0x15,0x02, 0x10,0x02,
0x15,0x00, 0x0F,0x01, 0x15,0x02, 0x16,0x02, 0x17,0x02,
0x17,0x03, 0x18,0x03, 0x19,0x02, 0x15,0x02, 0x18,0x66,
0x17,0x03, 0x19,0x02, 0x16,0x03, 0x17,0x03, 0x16,0x00,
0x17,0x01, 0x19,0x02, 0x1B,0x02, 0x1B,0x70, 0x1A,0x03,
0x1A,0x01, 0x19,0x02, 0x19,0x03, 0x1A,0x03, 0x1B,0x02,
0x1A,0x0D, 0x19,0x03, 0x17,0x00, 0x18,0x66, 0x18,0x03,
0x19,0x02, 0x1A,0x02, 0x19,0x0C, 0x18,0x0D, 0x17,0x03,
0x16,0x01, 0x11,0x02, 0x11,0x03, 0x10,0x03, 0x0F,0x0C,
0x10,0x02, 0x15,0x00, 0x1F,0x01, 0x1A,0x01, 0x18,0x66,
0x19,0x03, 0x1A,0x01, 0x1B,0x02, 0x1B,0x03, 0x1B,0x03,
0x1B,0x0C, 0x1A,0x0D, 0x19,0x03, 0x17,0x00, 0x1F,0x01,
0x1A,0x01, 0x18,0x66, 0x19,0x03, 0x1A,0x01, 0x10,0x02,
0x10,0x03, 0x10,0x03, 0x1A,0x0C, 0x18,0x0D, 0x17,0x03,
0x16,0x00, 0x0F,0x01, 0x15,0x02, 0x16,0x02, 0x17,0x70,
0x18,0x03, 0x17,0x02, 0x15,0x03, 0x15,0x03, 0x16,0x66,
0x16,0x03, 0x16,0x02, 0x16,0x03, 0x15,0x03, 0x10,0x02,
0x10,0x01, 0x11,0x01, 0x11,0x66, 0x10,0x03, 0x0F,0x0C,
0x1A,0x02, 0x19,0x02, 0x16,0x03, 0x16,0x03, 0x18,0x66,
0x18,0x03, 0x18,0x02, 0x17,0x03, 0x16,0x03, 0x19,0x00,
0x00,0x00 };
//两只蝴蝶
uchar code MusicHappyBirthday[]={ 0x0F,0x03, 0x0F,0x03, 0x10,0x02, 0x0F,0x02, 0x15,0x02,
0x11,0x01, 0x0F,0x03, 0x0F,0x03, 0x10,0x02, 0x0F,0x02,
0x16,0x02, 0x15,0x01, 0x0F,0x03, 0x0F,0x03, 0x19,0x02,
0x17,0x02, 0x15,0x02, 0x11,0x0C, 0x10,0x02, 0x18,0x03,
0x18,0x03, 0x17,0x02, 0x15,0x02, 0x16,0x02, 0x17,0x01,
0x0F,0x03, 0x0F,0x03, 0x10,0x02, 0x0F,0x02, 0x15,0x02,
0x11,0x01, 0x0F,0x03, 0x0F,0x03, 0x10,0x02, 0x0F,0x02,
0x16,0x02, 0x15,0x01, 0x0F,0x03, 0x0F,0x03, 0x19,0x02,
0x17,0x02, 0x15,0x02, 0x11,0x0C, 0x10,0x02, 0x18,0x03,
0x18,0x03, 0x17,0x02, 0x15,0x02, 0x16,0x02, 0x10,0x01,
0x00,0x00 };
void Delay_10MS(void);
void JX_New_Few_FerTab(uchar QSD,uchar SYD);
void Play_Music(uchar *Sound,uchar QSD,uchar SYD);
void Delay(uchar i);
void main(void)
{
TMOD = 0x01;
TH0 = 0xFF;
TL0 = 0xFF;
ET0 =1;
TR0 = 0;
EA = 1;
while(1)
{
Play_Music(MusicGirl,0,0);
Delay(200);
Play_Music(MusicSame,0,0);
Delay(200);
}
}
void Delay(uchar i)
{
while(i--)
{
Delay_10MS();
}
}
void Time_INT() interrupt 1
{
BUZZ = ~BUZZ;
TH0 = Time_H;
TL0 = Time_L;
}
// QSD 0-11 // SYD 1-3 1降8度 2不变,3升8度
void JX_New_Few_FerTab(uchar QSD,uchar SYD)
{
uchar i = 0;
uchar j = 0;
for(i = 0 ;i <12;i++) // 12次循环
{
j = i +QSD; //根据起始调判断起始音符位置
if(j >11) //如果起始调不是最低
{
j = j - 12; // 0-11
New_FreTab[i] = FreTab[j]*2;// 频率*2
}
else //频率不变
{
New_FreTab[i] = FreTab[j];
}
if(SYD == 1) //判断升降调。1降调,2不变,3升调。
{
New_FreTab[i] >>= 1;//频率减一半
}
else
{
if(SYD == 3)
{
New_FreTab[i] <<= 1;
}
}
}
}
void Play_Music(uchar *Sound,uchar QSD,uchar SYD)
{
uint GQ_CD = 0; //歌曲长度
uint GQ_WZ = 0;
uchar GQ_YG = 0;
uchar GQ_YC = 0;
uint YP_PL = 0;
uchar YG_Bai = 0;
uchar YG_Shi = 0;
uchar YG_Ge = 0;
uchar YC_Bai = 0;
uchar YC_Shi = 0;
uchar YC_Ge = 0;
uint DSD_PL = 0;
uint YF0 = 0; // 1分音符变量
uint YF1 = 0; // 发音长度时间
uint YF2 = 0; //不发音长度时间
uint YF4 = 0; // 4分音符时间
uint FY_JG = 0;
uint YZ_TC = 0;
uint JF_YF = 0;
uchar i =0;
JX_New_Few_FerTab( QSD, SYD);
while(Sound[GQ_CD] != 0) //判断歌曲长度
{
GQ_CD += 2; //指向下一位音符数据
}
while(GQ_WZ < GQ_CD)
{
GQ_YG = Sound[GQ_WZ];
YG_Bai = GQ_YG/100; // 1升半音,0不升
YG_Shi = GQ_YG/10%10; // 1低音,2为中音,3为高音
YG_Ge = GQ_YG%10; // 1-7 音符位;
YP_PL = New_FreTab[XY_Tab[YG_Ge -1] + YG_Bai];// yg_ge -1 1-7 0-6
if(YG_Ge != 0)
{
switch(YG_Shi)
{
case 2: YP_PL <<=1;break;
case 3: YP_PL <<=2;break;
}
DSD_PL = 65536-(50000/YP_PL)*10;
Time_H = DSD_PL >>8;
Time_L = DSD_PL & 0x00FF;
TH0 = Time_H;
TL0 = Time_L;
}
GQ_YC = Sound[GQ_WZ +1];
YC_Bai = GQ_YC/100; // 1有符点,0无符点
YC_Shi = GQ_YC/10%10; // 演奏效果0普通,1连音,2顿音
YC_Ge = GQ_YC%10; // 几分音符。
YF0 = YF_YF;
YF4 = YF0 /4;
FY_JG =YF4- YF4 *SFYF_JG;
JF_YF = YC_Tab[YC_Ge];// 几分音符;
YZ_TC = YF0 /JF_YF; // 算出对应延时长度多少个10MS
if(YC_Bai == 1) //判断是否有符点
{
YZ_TC = YZ_TC+YZ_TC/2;//有符点
}
if(YC_Shi != 1) //不是连音
{
if(YC_Shi == 0) //是否为普通音
{
if(JF_YF <= 4) // 是否小于16分音
{
YF1 = YZ_TC -FY_JG; // 发音有间隔
}
else // 不小于16分音
{
YF1 = YZ_TC * SFYF_JG;//发音无音隔
}
}
else //是顿音,演奏时间为原来的一半
{
YF1 = YZ_TC /2;
}
}
else //是连音,发音无音隔
{
YF1 = YZ_TC;
}
if(YG_Ge == 0) //没有音符数据
{
YF1 = 0; //演奏时间 = 0
}
else //有音符数据
{
YF2 = YZ_TC - YF1;
TR0 =1;
for(i = YF1; i >0;i --)
{
Delay_10MS();
}
BUZZ = 1;
TR0 = 0;
for(i = YF2; i >0;i --)
{
Delay_10MS();
}
}
GQ_WZ += 2; //指向下一个音符
}
}
//延时函数 10MS。
void Delay_10MS(void)
{
uchar a = 0;
uchar b = 0;
for(a = 50; a>0;a--)
{
for(b = 300;b>0;b--);
}
}
本帖评分记录 奖!感谢无私贡献 金钱:10 aj8714523 2011-05-17 15:30:33
|
----签名档 --------------------------------------------------------
好好学习,天天向上!
Posted:2011-05-17 15:25:59
| |
|