新闻  |   论坛  |   博客  |   在线研讨会
基于STC89C51的时钟软件设计(一)
max116 | 2012-04-27 16:33:24    阅读:999   发布文章

 

 
/*******************************/
/****基于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;
}
 

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客