#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define KEY_IO P3
#define LCD_IO P0
//以下是C调低音的音频宏定义
#define L1 262 //将"L1"宏定义为低音"1"的频率262Hz 时间是1/262=3826/2 us 取半周期
#define L2 286 //将"L2"宏定义为低音"2"的频率286Hz
#define L3 311 //将"L3"宏定义为低音"3"的频率311Hz
#define L4 349 //将"L4"宏定义为低音"4"的频率349Hz
#define L5 392 //将"L5"宏定义为低音"5"的频率392Hz
#define L6 440 //将"l_a"宏定义为低音"6"的频率440Hz
#define L7 494 //将"L7"宏定义为低音"7"的频率494Hz
//以下是C调中音的音频宏定义
#define Z1 523 //将"Z1"宏定义为中音"1"的频率523Hz
#define Z2 587 //将"Z2"宏定义为中音"2"的频率587Hz
#define Z3 659 //将"Z3"宏定义为中音"3"的频率659Hz
#define Z4 698 //将"Z4"宏定义为中音"4"的频率698Hz
#define Z5 784 //将"Z5"宏定义为中音"5"的频率784Hz
#define Z6 880 //将"Z6"宏定义为中音"6"的频率880Hz
#define Z7 987 //将"Z7"宏定义为中音"7"的频率523H
//以下是C调高音的音频宏定义
#define H1 1046 //将"H1"宏定义为高音"1"的频率1046Hz
#define H2 1174 //将"H2"宏定义为高音"2"的频率1174Hz
#define H3 1318 //将"H3"宏定义为高音"3"的频率1318Hz
#define H4 1396 //将"H4"宏定义为高音"4"的频率1396Hz
#define H5 1567 //将"H5"宏定义为高音"5"的频率1567Hz
#define H6 1760 //将"H6"宏定义为高音"6"的频率1760Hz
#define H7 1975 //将"H7"宏定义为高音"7"的频率1975Hz
sbit k4=P3^3;
sbit sound=P1^6; //蜂鸣器
unsigned int C; //储存定时器的定时常数
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit LED = P2^4;
void music(void);
unsigned char u,t;
bit new_s, modify = 0;
char t0, sec = 40, min = 29, hour = 6;
char code LCD_line1[] = "HAPPY EVEDAY";
char code LCD_line2[] = "Timer: 00:00:00 ";
char Timer_buf[] = "23:59:50";
//---------------------------------------------------
void delay(uint z)
{
uint x, y;
for(x = z; x > 0; x--) for(y = 100; y > 0; y--);
}
void delay1()
{
unsigned char i,j;
for(i=0;i<100;i++)
for(j=0;j<250;j++)
;
}
//---------------------------------------------------
void W_LCD_Com(uchar com) //写指令
{
LCD_RS = 0; LCD_IO = com; // LCD_RS和R/W都为低电平时,写入指令
LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲
}
//---------------------------------------------------
void W_LCD_Dat(uchar dat) //写数据
{
LCD_RS = 1; LCD_IO = dat; // LCD_RS为高、R/W为低时,写入数据
LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲
}
//---------------------------------------------------
void W_LCD_STR(uchar *s) //写字符串
{
while(*s) W_LCD_Dat(*s++);
}
//---------------------------------------------------
void W_BUFF(void) //填写显示缓冲区
{
Timer_buf[7] = sec % 10 + 48;/*秒除以10,并取余数*/ Timer_buf[6] = sec / 10 + 48; /*秒除以10,并取整数*/
Timer_buf[4] = min % 10 + 48; Timer_buf[3] = min / 10 + 48;
Timer_buf[1] = hour % 10 + 48; Timer_buf[0] = hour / 10 + 48;
W_LCD_Com(0xc0 + 7); W_LCD_STR(Timer_buf);
}
//---------------------------------------------------
uchar read_key(void) //按键 判断
{
uchar x1, x2;
KEY_IO = 255;
x1 = KEY_IO; // if (new_s) {
if (x1 != 255) { // new_s = 0; sec++; sec %= 60;
delay(100); // if(!sec) { min++; min %= 60;
x2 = KEY_IO; // if(!min) { hour++; hour %= 24;}
if (x1 != x2) return 255; // }
while(x2 != 255) x2 = KEY_IO; // W_BUFF();
if (x1 == 0x7f) return 0;
else if (x1 == 0xbf) return 1;
else if (x1 == 0xdf) return 2;
else if (x1 == 0xef) return 3;
}
return 255;
}
//---------------------------------------------------
void Init()
{
LCD_RW = 0;
W_LCD_Com(0x38); delay(50);
W_LCD_Com(0x0c);
W_LCD_Com(0x06);
W_LCD_Com(0x01);
W_LCD_Com(0x80); W_LCD_STR(LCD_line1);
W_LCD_Com(0xC0); W_LCD_STR(LCD_line2);
TMOD = 0x01; //T0定时方式1 16位
TH0 = 0x4c;
TR0 = 1; //启动T0
ET0 = 1;
ET1=1;
EA = 1;
}
//-----------------------------------------------------------
void music(void)
{
//以下是《天空之城》简谱 //每行对应一小节音符
unsigned int code f[]={ Z6,Z7,/**/H1,Z7,H1,H3,/**/Z7,Z3,Z3, /**/Z6,Z5,Z6,H1,/**/Z5,Z3,Z3, /**/Z4,Z3,Z4,H1,
Z3,H1,H1,H1,/**/Z7,Z4,Z4,Z7,/**/Z7,Z6,Z7, /**/H1,Z7,H1,H3,/**/Z7,Z3,Z3, /**/Z6,Z5,Z6,H1,
Z5, Z3,/**/Z4,H1,Z7,H1,/**/H2,H2,H2,H1,/**/H1,Z6,Z7,Z5,/**/Z6,H1,H2, /**/H3,H2,H3,H5,
H2,Z5,Z5, /**/H1,Z7,H1,H3,/**/H3, /**/Z6,H1,Z7,H2,/**/H1,Z5,Z5, /**/H4,H3,H2,H1,
H3, /**/Z3,H3, /**/H6,H5,H5, /**/H3,H2,H1,H1,/**/H2,H1,H2,H5,/**/H3,H3,
H6,H5, /**/H3,H2,H1,H1,/**/H2,H1,H2,Z7,/**/Z6,Z6,Z7, /**/Z6,
0xff }; //以0xff作为音符的结束标志
//以下是简谱中每个音符的节拍
//"4"对应4个延时单位,"2"对应2个延时单位,"1"对应1个延时单位
unsigned char code JP[ ]={ 4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,4,12,
20,4,4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,8,8,
32, 4, /**/8,4,6,8, /**/4,4,4,16, /**/8,4,6,8, /**/24,4,4, /**/12,4,8,8,
24,4,4, /**/4,4,8,8, /**/32, /**/4,8,8,6, /**/12,4,16, /**/8,8,8,8,
30, /**/20,8, /**/16,8,8, /**/4,4,16,8, /**/8,4,4,8, /**/20,8,
16,16, /**/4,20,8, /**/8,4,4,8, /**/20,4,4, /**/32,
};
EA=1; //开总中断
ET1=1; //定时器T1中断允许
TMOD &= 0x0f;
TMOD |= 0x00; // 使用定时器T1的模式1(13位计数器)
TR1=1;
while(1) //无限循环
{
u=0; //从第1个音符f[0]开始播放
while(f[u]!=0xff) //只要没有读到结束标志就继续播放
{
C=460830/f[u]; //
TH1=(8192-C)/32; //可证明这是13位计数器TH0高8位的赋初值方法 5
TL1=(8192-C)%32; //可证明这是13位计数器TL0低5位的赋初值方法
TR1=1; //启动定时器T0
for(t=0;t<JP[u];t++) //控制节拍数
delay1(); //延时1个节拍单位
TR1=0; //关闭定时器T1
u++; //播放下一个音符
if(k4==0) //暂停按键
{ delay(2);
if(k4==0)
{
ET1=0; // 关 允许T1,相当于关音乐
}
break;
}
ET1=1; //为了不影响第二次播放音乐,再 开 允许T1
}
sound=0;
break;
}
}
//---------------------------------------------------
void main()
{
uchar Key;
Init();
while(1)
{
//-------------------------------
//-------------------------------
if (!sec && min==30 && hour==6)
{ //整点报时 // 可以自己定闹钟
music();
}
//-------------------------------
Key = read_key(); //读出按键
switch(Key)
{ //分别处理四个按键
case 0: modify = 1; break;
case 1: if(modify) {min++; min %= 60; W_BUFF(); break;}
case 2: if(modify) {hour++; hour %= 24; W_BUFF(); break;}
case 3: modify = 0; break;
}
}
}
//---------------------------------------------------
void timer0(void) interrupt 1 //T0中断函数, 50ms执行一次 T0中断等级是1 注意
{
TH0 = 0x4c;
t0++; t0 %= 20; //20, 一秒钟
if(t0 == 0) {new_s = 1; LED = ~LED;}
if (new_s)
{ //如果出现了新的一秒, 修改时间
new_s = 0; sec++; sec %= 60;
if(!sec) // 如果SEC为零,说明满了60秒, 进入下一步
{ min++; min %= 60;
if(!min) // 如果MIN为零,说明满了60分钟,进入下一步
{ hour++; hour %= 24;
}
}
W_BUFF(); //写显示
if(modify) LED = 0;
}
}
void Time1(void ) interrupt 3 //T1定时器的中断等级要注意 是3
{
sound=!sound; //将P3.7引脚输出电平取反,形成方波
TH1=(8192-C)/32; //可证明这是13位计数器TH0高8位的赋初值方法
TL1=(8192-C)%32; //可证明这是13位计数器TL0低5位的赋初值方法
}
|