找到不同音符对应的频率,定义音符,根据《孤勇者》简谱编写乐谱,运用按键k1来设置闹钟倒计时时间,设置完成后按下按键k2,倒计时开始,倒计时结束后,播放《孤勇者》铃声
设计开发环境:
keli4(51系列兼容单片机C语言软件开发系统)
#include <reg52.h>
typedef unsigned int uint;
typedef unsigned char uchar;
uint a,FreqSelect,MusicSelect,count,count2,count_ms=100;
uchar code table[]={0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x00 //熄灭
};
sbit P2_0 = P2^3;
sbit P2_1 = P2^2;
sbit P2_2 = P2^1;
sbit P2_3 = P2^0;
sbit P2_4 = P2^7;
sbit P2_5 = P2^6;
sbit P2_6 = P2^5;
sbit P2_7 = P2^4;
sbit k1=P1^6;
sbit k2=P1^7;
sbit Buzzer=P1^4;
//播放速度,将一个四分音符的时长设置为600(ms),并以四分音符的时长为基准
#define SPEED 600
//音符与索引对应表,P:休止符,L:低音,M:中音,H:高音,下划线:升半音符号#
#define P 0
#define L1 1
#define L1_ 2
#define L2 3
#define L2_ 4
#define L3 5
#define L4 6
#define L4_ 7
#define L5 8
#define L5_ 9
#define L6 10
#define L6_ 11
#define L7 12
#define M1 13
#define M1_ 14
#define M2 15
#define M2_ 16
#define M3 17
#define M4 18
#define M4_ 19
#define M5 20
#define M5_ 21
#define M6 22
#define M6_ 23
#define M7 24
#define H1 25
#define H1_ 26
#define H2 27
#define H2_ 28
#define H3 29
#define H4 30
#define H4_ 31
#define H5 32
#define H5_ 33
#define H6 34
#define H6_ 35
#define H7 36
//索引与频率对照表
unsigned int FreqTable[]={
0,
63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,
64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,
65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283,
};
//乐谱
unsigned int code Music[]={//乐谱较长加上关键字code将其储存在ROM(flash)
//音符,时值,
//1
L6,4+4,
P,4,
P,2,
M6,1,
M7,1,
//2
H1,1,
H2,1,
M7,1,
H1,1,
H1,2,
H1,1,
M7,1,
H1,1,
H1,2,
H1,1,
H2,1,
//3
H3,1,
H2,1,
H3,1,
H2,1,
H3,2,
H3,1,
H2,1,
H3,2,
H5,2,
H3,2,
M6,1,
M7,1,
//4
H1,1,
H2,1,
M7,1,
H1,1,
H1,2,
H1,1,
M7,1,
H1,1,
H2,1,
M7,1,
H1,1,
H1,2,
H1,1,
H2,1,
//5
H3,1,
H2,1,
H3,1,
H2,1,
H3,2,
H3,1,
H2,1,
H3,2,
H5,2,
H3,2,
H5,2,
//6
H3,2+1,
H5,1,
H3,2+1,
H5,1,
H3,1,
H5,1,
H6,1,
H3,1,
H5,2,
H5,2,
//7
H3,2+1,
H5,1,
H3,2+1,
H5,1,
H3,1,
H5,1,
H6,1,
H3,1,
H5,1,
H5,1,
H5,1,
//8
H3,1,
H2,1,
H2,2,
H2,2,
H1,1,
H3,1,
H3,1,
H2,1,
H2,2,
H2,2,
H1,1,
H1,1,
//9
M6,4+4,
P,4,
P,2,
H5,1,
H5,1,
//10
H3,1,
H2,1,
H2,2,
H2,2,
H1,1,
H3,1,
H3,1,
H2,1,
H2,2,
H2,2,
H1,1,
H1,1,
//11
M6,4+4,
P,4,
P,4,
0xFF //终止标志
};
/*
* 延时函数 毫秒级
*/
void delay1(uint z)
{
uint x,y;
for(x=z;z>0;z--)
for(y=110;y>0;y--)
;
}
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
/********************************************************************
* 名称 : Timer1Init()
* 功能 : 定时器1初始化
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Timer1Init(void) //10毫秒@11.0592MHz
{
// AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x00; //设置定时初值
TH1 = 0xDC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //enable timer1 interrupt
EA = 1; //open global interrupt switch
}
void Timer0Init(void)
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
PT0=0;
}
/********************************************************************
* 名称 : display()
* 功能 : 数码管显示函数
* 输入 : Dis_data1,Dis_data2,Dis_data3,Dis_data4
* 输出 : 无
***********************************************************************/
void display1(uint Dis_data1,uint Dis_data2,uint Dis_data3,uint Dis_data4)
{
P0=table[Dis_data1];
P2_0 = 0;
delay1(2);
P2_0 = 1;
P0=table[Dis_data2];
P2_1 = 0;
delay1(2);
P2_1 = 1;
P0=table[Dis_data3];
P2_2 = 0;
delay1(2);
P2_2 = 1;
P0=table[Dis_data4];
P2_3 = 0;
delay1(2);
P2_3 = 1;
}
void display2(uint Dis_data1,uint Dis_data2,uint Dis_data3,uint Dis_data4)
{
P0=table[Dis_data1];
P2_4 = 0;
delay1(2);
P2_4 = 1;
P0=table[Dis_data2];
P2_5 = 0;
delay1(2);
P2_5 = 1;
P0=table[Dis_data3];
P2_6 = 0;
delay1(2);
P2_6 = 1;
P0=table[Dis_data4];
P2_7 = 0;
delay1(2);
P2_7 = 1;
}
/********************************************************************
* 名称 : main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void main()
{
while(1)
{
if(k1==0){
while(!k1);
a++;
}
if(k2==0){
break;
}
count=a;
display2(count%10000/1000,count%1000/100,count%100/10,count%10);
}
Timer1Init();
//count=100;
//count=10000;
count_ms=1000;
while(1)
{
display1(count%10000/1000,count%1000/100,count%100/10,count%10);
if(count==0){
Timer0Init();
while(1)
{
if(Music[MusicSelect]!=0xFF) //如果不是停止标志位
{
FreqSelect=Music[MusicSelect]; //选择音符对应的频率
MusicSelect++;
Delay(SPEED/2*Music[MusicSelect]); //选择音符对应的时长
MusicSelect++;
TR0=0;//不同音符间短暂停顿,利用延时开关定时器实现
Delay(5);
TR0=1;
}
else //如果是停止标志位
{
TR0=0; //关闭定时器
while(1);
}
}
}
}
}
/********************************************************************
* 名称 : void tm1_isr() interrupt 3 using 1
* 功能 : 定时器1中断服务函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void tm1_isr() interrupt 3 using 1
{
TL1 = 0x00; //设置定时初值
TH1 = 0xDC; //设置定时初值
if (count_ms-- == 0) //1ms * 1000 -> 1s
{
count_ms=1000;
if(count==0)
{
count=a;
}
count --; //reset counter
}
}
void Timer0_Routine() interrupt 1
{
if(FreqTable[FreqSelect]) //如果是休止符(0),那么不播放声音,只进行延时
{
//取对应频率值的重装载值到定时器(确认音高)FreqSelect=Music[MusicSelect]
TL0 = FreqTable[FreqSelect]%256; //设置低位定时初值
TH0 = FreqTable[FreqSelect]/256; //设置高位定时初值
Buzzer=!Buzzer; //翻转蜂鸣器IO口(注意这里的重装值是周期的一半,故仅进行一次蜂鸣器的翻转)
}
}