/*******************************/
/****基于stc89c51的时钟设计 ****/
/**1、走时 ****/
/**2、显示 ****/
/**3、校时 ****/
/**4、定时报警 ****/
/**5、节电模式 ****/
/*******************************/
/*****************************/
/**** 寄存器头文件 ****/
/*****************************/
#include <reg51.h>
/*****************************/
/**** 宏定义 ****/
/*****************************/
#define N 2 //计时阈值
#define OV 60 //过零修正
/*** 计算时间差值宏定义 ***/
#define TIMER(MIN,OLD_MIN)\
( ( char )( ( MIN ) - ( OLD_MIN ) ) ) >= 0 ?\
( ( ( MIN ) - ( OLD_MIN ) ) >= N ) : \
( ( (OLD_MIN) >= (OV) - (N) ) ?\
( ( ( ( MIN ) + OV ) - ( OLD_MIN ) ) >= N ):\
( 0 ) )
/*****************************/
/**** 全局变量定义 ****/
/*****************************/
unsigned char LedOut[6]; //存放显示数据
bit change = 0; // 小时更新标志
bit alarm_able = 0;
bit shine = 0; //闪烁标志
bit light = 1; //是否显示
sbit mdi = P3^5; //接蜂鸣器
unsigned ms = 0;
unsigned char loc = 0; //显示当前位置
unsigned char state = 0; //0:显示时间 1:显示日期 2:调整时间
//3:调整日期 4:设置闹铃
unsigned char old_min = 0; //计算时间差用
unsigned char code Disp_Tab[] =
// 0 1 2 3
{0x03,0x9f,0x25,0x0d
// 4 5 6 7
,0x99,0x49,0x41,0x1f
// 8 9 -
,0x01,0x09,0xff,0xfd}; //笔形码
unsigned char code key[] =
// 0 1 2 3
{0xee,0xde,0xbe,0x7e
// 4 5 6 7
,0xed,0xdd,0xbd,0x7d
// 8 9 - -
,0xeb,0xdb,0xbb,0x7b
//定位闹铃 状态确认
,0xe7,0xd7,0xb7,0x77}; //键码
int key_value = -1; //键值 -1 表示无键按下
enum weekday {mon,tue,wed,thu,fri,sat,sun}
week = 0;
// 2011-12-12 是星期一
struct Date
{
unsigned char year;
unsigned char month;
unsigned char day;
} date = {11,12,12}; //日期初始化为 2011-12-12
struct Time
{
unsigned char hour;
unsigned char min;
unsigned char sec;
} time = {12,0,0}; //时间初始化为 12:00:00
struct Alarm
{
unsigned char hour;
unsigned char min;
} alarm = {8,0}; //闹钟初始化为 08:00
/*****************************/
/**** 函数前置声明 ****/
/*****************************/
void init();
void delay(unsigned int);
void correct();
void update();
void display();
int key_loc();
void key_charge();
void music();
/*****************************/
/**** 主函数定义 ****/
/*****************************/
void main()
{
init();
while( 1 )
{
if( change ) //更新日期
{
change = 0;
update();
display(); //更新显示
}
if ( !(ms % 20) ) //约20ms查键、更新显示一次
{
display();
P1 = 0xf0;
if(P1 != 0xf0)
{
delay(25);
if(P1 != 0xf0)
{
key_value = key_loc();
}
}
}
if( key_value != -1) //若有键,则处理按键
{
key_charge();
key_value = -1;
}
if (alarm_able && time.hour == alarm.hour
&& time.min == alarm.min)
//闹铃开启且时间到达
{
music();
}
if ( TIMER(time.min,old_min) )
light = 0;
else light = 1;
}
}
/*****************************/
/**** 初始化函数定义 ****/
/*****************************/
void init()
{
SCON = 0; //串行口方式0
TMOD|= 0x01; //定时器方式1
TH0= 0xFC; //12.000M 1ms
TL0= 0x18;
IE = 0x82; // 设置EA ET0 开定时器0中断
TR0 = 1; // 开启定时器0
}
/*****************************/
/**** 延时函数定义 ****/
/*****************************/
void delay(unsigned int i) //12M晶振,延时约200 * i us
{
char j;
for(i; i > 0; i--)
for(j = 200; j > 0; j--);
}
/*****************************/
/**** 闹铃函数定义 ****/
/*****************************/
void music()
{
mdi = 0; //响铃
delay(5);
/* **注意** */
/* mdi = 1 必须在各改变 mdi 值的语句之后,以确保闹铃正确关闭 */
mdi = 1; //灭铃
}
/*****************************/
/**** 日期更新函数定义 ****/
/*****************************/
void update()
{
if( ++date.day > 28)
{
switch(date.day)
{
//非闰年2月
case 29: if(date.month==2 &&
!((date.year%4==0&&date.year%100!=0)||(date.year%400==0)))
{ date.day=1; date.month=3; }
break;
//闰年2月
case 30: if(date.month==2) { date.day=1; date.month=3; }
break;
//其他月份
case 31: if(date.month==4 || date.month==6 || date.month==9 || date.month==11)
{ date.day=1; date.month++; }
break;
case 32: date.day=1; date.month++;
if(date.month >= 13) { date.month=1; date.year++;}
break;
default : date.day = 1; //处理过调或错误
}
}
}
/*****************************/
/**** 过调修正函数定义 ****/
/*****************************/
void correct()
{
if( time.sec >= 60 ) time.sec = 0;
if( time.min >= 60 ) time.min = 0;
if( time.hour >= 24) time.hour = 0;
if( alarm.hour >= 24 ) alarm.hour = 0;
if( alarm.min >= 60 ) alarm.min = 0;
if( date.day >= 28 ) date.day--; update();
if( date.month >= 13) date.month = 0;
}
/*****************************/
/**** 求键值函数定义 ****/
/*****************************/
int key_loc() // key_value = key_loc();
{
int temp = 0 ,temp1 = 0, i ;
P1=0xF0; //高四位输入 行为高电平 列为低电平
delay(25);
temp=P1; //读P1口
temp&=0xF0; //屏蔽低四位
P1 = 0x0F;
delay(25);
temp |= (temp1 = P1) & 0x0F;
P1 = 0xF0;
delay(25);
while(P1 != 0xF0) //松手检测
{
delay(25);
display();
P1 = 0xF0;
delay(25);
}
for( i = 0; i < 16; i++) //搜索键值
{
delay(25);
if ( temp == key[i])
return i;
}
return -1;
}
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。