多功能电子时钟(带时区划分,闹钟,区分上午和下午)

来源:互联网 发布:ldc1000数据手册 编辑:程序博客网 时间:2024/04/30 12:03

/********************************************************************

多功能电子时钟

单片机:STC89C52系列或其兼容型号

        外部晶振:12MHZ

作者:xxx

日期:2012.7.17

*********************************************************************/

#include "reg52.h"

 

#define FOSC                             (12)        //系统晶振,以MHZ为单位

#define MSECOND                     (10)        //定时器的定时时间,以毫秒为单位

#define CLOCKCOUNT              (3)          //时钟个数

 

#define FLASHHOUR                 (1)          //小时闪烁判断值

#define FLASHMINUTE             (2)          //分钟闪烁判断值

#define FLASHSECOND             (3)          //秒闪烁判断值

#define FLASHNONE                 (4)          //不闪烁判断值

 

#define FLASHFREQ                  (10)        //小时、分、秒闪烁时的频率,值越大越慢

#define BEEPFREQ                    (10)        //蜂鸣器的发声频率,值越大越慢

 

#define TIMEMODE12               (1)          //12小时制

#define TIMEMODE24               (2)          //24小时制

 

#define ALARMON                     (1)

#define ALARMOFF                   (2)

 

#define AM                                (1)

#define PM                                 (2)

 

#define vTL0                              ((65536-MSECOND*FOSC/12*1000)%256)     //计算定时器初值

#define vTH0                              ((65536-MSECOND*FOSC/12*1000)/256)

 

#define SEGPORT                      (P0)        //显示器段码口

#define WEIPORT                      (P1)        //显示器位码口

 

#define BEEPON                        (1)          //打开蜂鸣器的电平

#define BEEPOFF                      (0)          //关闭蜂鸣器的电平

 

#define LEDON                          (1)          //AMPM指示灯的打开电平

#define LEDOFF                        (0)          //AMPM指示灯的关闭电平

 

#define KEY1                             (1)          //1号按键的键值

#define KEY2                             (2)          //2号按键的键值

#define KEY3                             (3)          //3号按键的键值

#define NOKEY                         (4)          //无按键时的值

 

#define KEYSPEED                   (5)          //按键的响应速度,值越大响应越慢

 

#define KEYWAITTIME             (1000)     //无按键时,自动退出前的等待时间,值越大时间越长

#define ALARMTIME                 (30000)   //自动撤销闹铃前的等待时间,值越大时间越长

 

sbit Key1                                    =P2^0;    //1号按键,以下程序设定为“功能键”

sbit Key2                                    =P2^1;    //2号按键,以下程序设定为“增键”

sbit Key3                                    =P2^2;    //3号按键,以下程序设定为“减键”

 

sbit AmLed                                 =P2^3;    //AM指示灯

sbit PmLed                                 =P2^4;    //PM指示灯

 

sbit Beep                                    =P2^7;    //闹铃驱动口线

 

typedef struct {//定义一个时钟结构体类型——TClock

                            unsigned char Hour;

                            unsigned char Minute;

                            unsigned char Second;

                            unsigned int MSecond;          //毫秒

                            unsigned char AlarmOpen;

                            unsigned char AlarmHour;

                            unsigned char AlarmMinute;

                            unsigned char AlarmFlag;

                            unsigned int AlarmTime;

} TClock;

 

unsigned char code SegCode[]={//共阴极管 dp g f e d c b a

                                                   0x3f,0x06,0x5b,0x4f,0x66,

                                         0x6d,0x7d,0x07,0x7f,0x6f,

                                                   0x00

};

 

TClock Clock[CLOCKCOUNT],*pClock;                 //时钟数组和时钟指针

unsigned char DispBuf[6];                                        //显示缓冲区

unsigned char KeyWaitFlag=0,AdjustTimeFlag=0;     //用于函数间协调的两个标志

unsigned char WhichClock=0;                                  //存放当前所选时钟的下标

unsigned char TimeMode=TIMEMODE24;                //时间模式

unsigned char AMorPM,AlarmOnOff;

unsigned int KeyWaitTime=0;                                   //为无按键时的自动退出服务

 

void xDelay(unsigned char x)

{

 unsigned char y;

 

 for(;x>0;x--)

  for(y=20;y>0;y--);

}

 

//将所选时钟的数据填充到显示缓冲区

//pClock——指向时钟的指针

void FillDispBuf(TClock *pClock)

{

 DispBuf[0]=SegCode[pClock->Hour/10];    //指针访问结构体中的元素用符号“->,叫成员运算符

 DispBuf[1]=SegCode[pClock->Hour%10];   //结构体中访问其中元素用符号“.

 

 DispBuf[2]=SegCode[pClock->Minute/10];

 DispBuf[3]=SegCode[pClock->Minute%10];

 

 DispBuf[4]=SegCode[pClock->Second/10];

 DispBuf[5]=SegCode[pClock->Second%10];

}

 

//将所选时钟的闹铃时间填充到显示缓冲区

//pClock——指向时钟的指针

void FillAlarmToDispBuf(TClock *pClock)

{

 DispBuf[0]=SegCode[10];

 DispBuf[1]=SegCode[10];

 

 DispBuf[2]=SegCode[pClock->AlarmHour/10];

 DispBuf[3]=SegCode[pClock->AlarmHour%10];

 

 DispBuf[4]=SegCode[pClock->Minute/10];

 DispBuf[5]=SegCode[pClock->Minute%10];

}

 

//显示函数,用于显示时间,可闪烁显示

//FlashWhich——指定闪烁的部分,可取值FLASHHOURFLASHMINUTEFLASHSECONDFLASHNONE

void Display(unsigned char FlashWhich)

{

 unsigned char WeiCode,i;

 static unsigned char FlashCount,nState=0;    //静态变量的值会一直保持不变,但是只会在所定义的函数中有效

 

 if (FlashWhich!=FLASHNONE) FlashCount=FLASHFREQ;

 else nState=0;

 

 WeiCode=0xfe;

 for(i=0;i<6;i++)

  {

   switch(FlashWhich){

       case FLASHHOUR:

                               if((i==0)||(i==1))

                                switch(nState){

                                    case 0:  //on

                                                 if (--FlashCount>0) SEGPORT=DispBuf[i];

                                                 else {FlashCount=FLASHFREQ; nState=1;}

                                                 break;

                                    case 1: //off

                                                 if (--FlashCount>0) SEGPORT=SegCode[10];

                                                 else {FlashCount=FLASHFREQ; nState=0;}

                                                 break;

                                    default: nState=0;

                                   }

                               else    SEGPORT=DispBuf[i];

                               break;

       case FLASHMINUTE:

                               if((i==2)||(i==3))

                                switch(nState){

                                    case 0:  //on

                                                 if (--FlashCount>0) SEGPORT=DispBuf[i];

                                                 else {FlashCount=FLASHFREQ; nState=1;}

                                                 break;

                                    case 1: //off

                                                 if (--FlashCount>0) SEGPORT=SegCode[10];

                                                 else {FlashCount=FLASHFREQ; nState=0;}

                                                 break;

                                    default: nState=0;

                                   }

                               else    SEGPORT=DispBuf[i];

                               break;

       case FLASHSECOND:

                               if((i==4)||(i==5))

                                switch(nState){

                                    case 0:  //on

                                                 if (--FlashCount>0) SEGPORT=DispBuf[i];

                                                 else {FlashCount=FLASHFREQ; nState=1;}

                                                 break;

                                    case 1: //off

                                                 if (--FlashCount>0) SEGPORT=SegCode[10];

                                                 else {FlashCount=FLASHFREQ; nState=0;}

                                                 break;

                                    default: nState=0;

                                   }

                               else    SEGPORT=DispBuf[i];

                               break;

    default: SEGPORT=DispBuf[i];

   };

 

   WEIPORT=WeiCode;

   WeiCode<<=1; WeiCode|=0x01;

   xDelay(10);

  }

}

 

//显示指定时钟的时钟下标(编号)

//aClock——时钟下标

void DisplayClock(signed char aClock)

{

 DispBuf[0]=0x39;       //C

 DispBuf[1]=0x38;       //L

 DispBuf[2]=0x3f; //O

 DispBuf[3]=0x39;       //C

 

 DispBuf[4]=0x00;       //熄灭

 

 DispBuf[5]=SegCode[aClock];    //时钟编号

 

 Display(FLASHNONE);

}

 

//用于显示时钟的时间模式(12小时制或24小时制)

//xTimeMode——时间模式,可取值为TIMEMODE12TIMEMODE24

void DisplayTimeMode(unsigned char xTimeMode)

{

 if (xTimeMode==TIMEMODE12)

  {

   DispBuf[0]=SegCode[1];  //1

   DispBuf[1]=SegCode[2];  //2

  }

 else

  {

   DispBuf[0]=SegCode[2];  //2

   DispBuf[1]=SegCode[4];  //4

  }

 DispBuf[2]=0x74;  //h

 DispBuf[3]=0x5c;  //o

 DispBuf[4]=0x1c;  //u

 DispBuf[5]=0x70;  //r

 

 Display(FLASHNONE);

}

 

//用于显示所选时钟闹铃的开关状态

//OnOff——开关状态,可取值为ALARMONALARMOFF

void DisplayAlarm(unsigned char OnOff)

{

 DispBuf[0]=0x77;       //A

 DispBuf[1]=0x38;       //L

 DispBuf[2]=0x77;       //A

 

 if (OnOff==ALARMON)

  {

   DispBuf[3]=0x00;    //熄灭

   DispBuf[4]=0x5c;    //o

   DispBuf[5]=0x54;    //n

  }

 else

  {

   DispBuf[3]=0x5c;    //o

   DispBuf[4]=0x71;    //F

   DispBuf[5]=0x71;    //F

  }

 

 Display(FLASHNONE);

}

 

//键盘函数,返回值为按键的键值

//返回值包括KEY1,KEY2,KEY3,NOKEY

unsigned char Key(void)

{

 static unsigned char xCount=0;

 

 if (++xCount<KEYSPEED) return(NOKEY);

 xCount=0;

 

 if (Key1==0)              return(KEY1);

 else if (Key2==0)       return(KEY2);

 else if (Key3==0)       return(KEY3);

 else                           return(NOKEY);

}

 

//系统初始化函数

void Init(void)

{

 TMOD=0x01;

 TL0=vTL0;

 TH0=vTH0;

 ET0=1;

 EA=1;

 TR0=1;

 pClock=Clock; //时钟指针初始指向第1个时钟

 if (pClock->Hour>=12) AMorPM=PM;

 else AMorPM=AM;

 AlarmOnOff=ALARMOFF;

}

 

void main(void)

{

 unsigned char aKey,nState=0,Temp=0;

 

 Init();

 

 while(1){

  aKey=Key();

  switch(nState){

   case 0:  //时钟正常运行

                      FillDispBuf(Clock+WhichClock);

                      Display(FLASHNONE);

                      AdjustTimeFlag=0;

 

                      if (Clock[WhichClock].AlarmFlag)  //驱动闹钟蜂鸣器

                       {

                        if (++Temp>=BEEPFREQ) {Beep^=1; Temp=0;}

                        if (aKey!=NOKEY)

                         {

                             Clock[WhichClock].AlarmFlag=0;

                             Temp=0;

                             Beep=BEEPOFF;

                            }

                       }

                      else if (aKey==KEY1)

                       {KeyWaitTime=0; Clock[WhichClock].MSecond=0; nState=1;}

                    break;

   case 1:      //选择时钟

                      KeyWaitFlag=1;   //等待按键时间内无按键,自动返回运行状态

                      if (KeyWaitTime>=KEYWAITTIME) {KeyWaitTime=0; KeyWaitFlag=0; nState=0;}

 

                      if (aKey==KEY1)

                       {KeyWaitTime=0; nState=2;}

                      else if (aKey==KEY2)

                       {if (WhichClock<CLOCKCOUNT-1) WhichClock++; KeyWaitTime=0;}

                      else if (aKey==KEY3)

                       {if (WhichClock>0) WhichClock--; KeyWaitTime=0;}

 

                      DisplayClock(WhichClock);

                    break;

   case 2:      //选择时间模式(12小时制或24小时制)

                      KeyWaitFlag=1;   //等待按键时间内无按键,自动返回运行状态

                      if (KeyWaitTime>=KEYWAITTIME) {KeyWaitTime=0; KeyWaitFlag=0; nState=0;}                

                      

                      if (aKey==KEY1) {KeyWaitTime=0; AdjustTimeFlag=1; nState=3;}

 

                      if ((aKey==KEY2)||(aKey==KEY3))

                       {

                        KeyWaitTime=0;

                        if (TimeMode==TIMEMODE12)

                         {

                          TimeMode=TIMEMODE24;

                          AmLed=LEDOFF;

                          PmLed=LEDOFF;

                          Clock[WhichClock].Hour+=12;

                         }

                        else

                         {

                             TimeMode=TIMEMODE12;

                             if (Clock[WhichClock].Hour>=12)

                              {PmLed=LEDON; AmLed=LEDOFF; Clock[WhichClock].Hour-=12; AMorPM=PM;}

                             else

                              {PmLed=LEDOFF; AmLed=LEDON; AMorPM=AM;}

                         }

                       }

 

                      DisplayTimeMode(TimeMode);

                   break;

   case 3:  //调整所选时钟的小时

                      KeyWaitFlag=1;   //等待按键时间内无按键,自动返回运行状态

                      if (KeyWaitTime>=KEYWAITTIME) {KeyWaitTime=0; KeyWaitFlag=0; nState=0;}

 

                      FillDispBuf(Clock+WhichClock);

                      Display(FLASHHOUR);

 

                      if (aKey==KEY1)

                       {KeyWaitTime=0; nState=4;}

                      else if (aKey==KEY2)

                       {

                        if (TimeMode==TIMEMODE12)

                         {

                             if (Clock[WhichClock].Hour<11) {Clock[WhichClock].Hour++; KeyWaitTime=0;}

                            }

                        else if (Clock[WhichClock].Hour<23) {Clock[WhichClock].Hour++; KeyWaitTime=0;}

                       }

                      else if (aKey==KEY3)

                       {if (Clock[WhichClock].Hour>0) Clock[WhichClock].Hour--; KeyWaitTime=0;}

                    break;

   case 4:      //调整所选时钟的分钟

                      KeyWaitFlag=1;   //等待按键时间内无按键,自动返回运行状态

                      if (KeyWaitTime>=KEYWAITTIME) {KeyWaitTime=0; KeyWaitFlag=0; nState=0;}

 

                      FillDispBuf(Clock+WhichClock);

                      Display(FLASHMINUTE);

 

                      if (aKey==KEY1)

                       {KeyWaitTime=0; nState=5;}

                      else if (aKey==KEY2)

                       {if (Clock[WhichClock].Minute<59) Clock[WhichClock].Minute++; KeyWaitTime=0;}

                      else if (aKey==KEY3)

                       {if (Clock[WhichClock].Minute>0) Clock[WhichClock].Minute--; KeyWaitTime=0;}

                    break;

   case 5:      //调整所选时钟的秒

                      KeyWaitFlag=1;   //等待按键时间内无按键,自动返回运行状态

                      if (KeyWaitTime>=KEYWAITTIME) {KeyWaitTime=0; KeyWaitFlag=0; nState=0;}

 

                      FillDispBuf(Clock+WhichClock);

                      Display(FLASHSECOND);

 

                      if (aKey==KEY1)

                       {KeyWaitTime=0; AdjustTimeFlag=0; nState=6;}

                      else if (aKey==KEY2)

                       {if (Clock[WhichClock].Second<59) Clock[WhichClock].Second++; KeyWaitTime=0;}

                      else if (aKey==KEY3)

                       {if (Clock[WhichClock].Second>0) Clock[WhichClock].Second--; KeyWaitTime=0;}

                    break;

   case 6: //开关闹铃功能

                      KeyWaitFlag=1;   //等待按键时间内无按键,自动返回运行状态

                      if (KeyWaitTime>=KEYWAITTIME) {KeyWaitTime=0; KeyWaitFlag=0; nState=0;}

 

                      if (aKey==KEY1) {KeyWaitTime=0; nState=7;}

 

                      if ((aKey==KEY2)||(aKey==KEY3))

                       {

                        KeyWaitTime=0;

                        if (Clock[WhichClock].AlarmOpen)

                         {Clock[WhichClock].AlarmOpen=0; AlarmOnOff=ALARMOFF;}

                        else

                         {Clock[WhichClock].AlarmOpen=1; AlarmOnOff=ALARMON;}

                       }

 

                      DisplayAlarm(AlarmOnOff);

                      break;

   case 7: //调整闹铃小时

                      KeyWaitFlag=1;   //等待按键时间内无按键,自动返回运行状态

                      if (KeyWaitTime>=KEYWAITTIME) {KeyWaitTime=0; KeyWaitFlag=0; nState=0;}

 

                      if (aKey==KEY1) {KeyWaitTime=0; nState=8;}

 

                      if (TimeMode==TIMEMODE12)

                       {

                        if (aKey==KEY2)

                         if (Clock[WhichClock].AlarmHour<11)

                             {Clock[WhichClock].AlarmHour++; KeyWaitTime=0;}

                        if (aKey==KEY3)

                         if (Clock[WhichClock].AlarmHour>0)

                             {Clock[WhichClock].AlarmHour--; KeyWaitTime=0;}                     

                       }

                      else

                       {

                        if (aKey==KEY2)

                         if (Clock[WhichClock].AlarmHour<23)

                             {Clock[WhichClock].AlarmHour++; KeyWaitTime=0;}

                        if (aKey==KEY3)

                         if (Clock[WhichClock].AlarmHour>0)

                             {Clock[WhichClock].AlarmHour--; KeyWaitTime=0;}

                       }

 

                      FillAlarmToDispBuf(Clock+WhichClock);

                      Display(FLASHMINUTE);

                      break;

   case 8: //调整闹铃分钟

                      KeyWaitFlag=1;   //等待按键时间内无按键,自动返回运行状态

                      if (KeyWaitTime>=KEYWAITTIME) {KeyWaitTime=0; KeyWaitFlag=0; nState=0;}

 

                      if (aKey==KEY1) {KeyWaitTime=0; nState=0;}

 

                      if (aKey==KEY2)

                       if (Clock[WhichClock].AlarmMinute<59)

                        {Clock[WhichClock].AlarmMinute++; KeyWaitTime=0;}

                      if (aKey==KEY3)

                       if (Clock[WhichClock].AlarmMinute>0)

                        {Clock[WhichClock].AlarmMinute--; KeyWaitTime=0;}

 

                      FillAlarmToDispBuf(Clock+WhichClock);

                      Display(FLASHSECOND);              

                      break;

   default: nState=0;

  }

 }

}

 

//T0定时器10ms中断服务函数

void T0Int(void) interrupt 1

{

 unsigned char i;

 

 TL0=vTL0; TH0=vTH0;

 

 if ((KeyWaitFlag)&&(KeyWaitTime<KEYWAITTIME)) KeyWaitTime++; //用于按键等待

 

 if (!AdjustTimeFlag)  //只有处于非调整时间状态,才刷新时钟的时间

  {

   for(i=0;i<CLOCKCOUNT;i++) //此循环用于刷新各时钟的时间

    {

     pClock->MSecond+=10;

     if (pClock->MSecond>=1000) {pClock->Second++; pClock->MSecond=0;}

     if (pClock->Second>=60)   {pClock->Minute++; pClock->Second=0;}

     if (pClock->Minute>=60)   {pClock->Hour++; pClock->Minute=0;}

     if (TimeMode==TIMEMODE12)

         {

          if (AMorPM==AM)

           {

            if (pClock->Hour>=12)

                {AMorPM=PM; pClock->Hour=0; PmLed=LEDON; AmLed=LEDOFF;}

              }

          else

           {

            if (pClock->Hour>=12)

                {AMorPM=AM; pClock->Hour=0; PmLed=LEDOFF; AmLed=LEDON;}

              }

         }

        else if (pClock->Hour>=24) {pClock->Hour=0;}

        

 

     if ((pClock->AlarmOpen)&&(!pClock->AlarmFlag))       //判断是否应打开闹铃

      if (pClock->Hour==pClock->AlarmHour)

           if (pClock->Minute==pClock->AlarmMinute) pClock->AlarmFlag=1;

 

        if (pClock->AlarmFlag) //闹铃时间到,自动关闭闹铃

         if (++pClock->AlarmTime>=ALARMTIME) {pClock->AlarmFlag=0; pClock->AlarmTime=0;}

 

     pClock++;

    }

   pClock=Clock;

  }

}

原创粉丝点击