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

多功能电子时钟

单片机: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)          //AM、PM指示灯的打开电平

#define LEDOFF                        (0)          //AM、PM指示灯的关闭电平

#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——指定闪烁的部分,可取值FLASHHOUR、FLASHMINUTE、FLASHSECOND、FLASHNONE

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——时间模式,可取值为TIMEMODE12、TIMEMODE24

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——开关状态,可取值为ALARMON、ALARMOFF

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;

}

}

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

  1. php 区分上午下午,中午(怎样区分上午中午下午)

    早上:7~9点,中午:11~13点 下午:13~15点 晚上:19~21点.更明确的划分可分为:早晨7-9点.上午9-11点.中午11-13点.下午13-15点.傍晚15-17点.黄昏17-19点.晚 ...

  2. 51单片机+ds1302+lcd1602简易电子时钟(带闹钟功能)

    51单片机+ds1302+lcd1602简易电子时钟(带闹钟功能) AT89C52.LCD1602.DS1302.speaker. Proteus仿真 实例代码 #include<reg52.H ...

  3. 基于51单片机的1602LCD时钟、可以设置闹钟(带仿真)

    基于51单片机的1602LCD时钟.可以设置闹钟 最近做了个51单片机的时钟.具有设置时间.闹钟等功能 程序分为3个模块.程序比较简单.由于用于学习交流用没有做掉电运行功能. 供大家学习. isis仿 ...

  4. 基于51单片机、DS1302时钟模块的电子闹钟设计

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.设计原理 1.DS1302介绍 2.闹钟音乐播放原理 二.程序设计 1.DS1302.h 2.ds1302.c 3.mu ...

  5. 【数据分享】世界国家时区划分(含世界国家时区)

    Part1数据背景 由于世界各国家与地区经纬度不同,正式的时区划分24个时区,每隔经度15°划分一个时区. Part2数据详情 小火今天分享的是全球时区划分.全球国家时区划分.全球15°经线数据等,专 ...

  6. js 格式化带时区的日期

    /*** 格式化带时区的日期*/ function formatDate(date) {var arr = date.split("T");var d = arr[0];var d ...

  7. 【java】带时区的时间格式化

    前言 jdk1.8 当前时区 带时区格式化时间 为SimpleDateFormat对象指定时区后,再执行格式化. Calendar cal = Calendar.getInstance(); Simp ...

  8. 带时区时间日期 ZonedDateTime

    带时区时间日期 ZonedDateTime 1. 简介 ZonedDateTime表示带时区的日期时间,如2007-12-03T10:15:30+01:00 Europe/Paris. 参考官方文档描 ...

  9. 用单片机用c语言做闹钟,基于单片机与ds1302时钟芯片的电子闹钟C程序

    原标题:基于单片机与ds1302时钟芯片的电子闹钟C程序 #include #define w_second 0x80 //秒写入地址 #define w_minute 0x82 //分写入地址 #d ...

最新文章

  1. Java高并发编程:线程池
  2. arcgis-shp文件属性表导出为dbf或txt
  3. CSS--选择符大全(常用css选择符)
  4. Xcode插件管理工具Alcatraz
  5. this关键字 和 private关键字
  6. 【练习手记】【多题合集】用树状数组做线段树练习1、2、3
  7. 罗永浩吐槽卖小米、苹果被骂,卖华为也被骂,李楠:警惕键盘侠
  8. 火影忍者服务器维护时间,火影手游12月12日更新:仙鸣增加破霸体,小自来也变蛙时间减半!...
  9. 凤凰系统运行linux,把凤凰系统装进U盘里,打造PC上的可移动android系统
  10. c语言小学生入门自学,啊哈C语言:小学生坐在马桶上都可以读懂的C语言编程入门书 PDF 扫描版[20M]...
  11. 0到1使用spring-security(Spring的安全认证框架)
  12. app逆向--91视频刷邀请
  13. 词汇导入词根词缀字典
  14. crontab——定时周期性执行任务
  15. 神奇宝贝五分类:数据预处理,可以推广到任意图片集
  16. 如何将照片从iPhone导入到Mac
  17. 《可转债投资魔法书》:魔法般教会你可转债
  18. 山寨版的《KingdomRush(皇城突袭)》
  19. unity 多个物体围绕一个点生成圆形状
  20. 线程经典实例——吃苹果问题

热门文章

  1. 虚拟机使用NAT模式连接网络设置
  2. 【Redis】孔夫子旧书网爬虫接入芝麻代理IP:代理IP利用效率最大化
  3. mot_challenge官方评估代码
  4. CodeForces Round #288 Div.2
  5. IP地址,MAC地址与域名地址
  6. 如何将视频数据录制成多媒体文件
  7. 在idea中,无法使用vue的标签,报红显示错误“Namespace ‘v-ind‘ is not bound“
  8. [原]红帽 Red Hat Linux相关产品iso镜像下载
  9. 使用ArcGIS制作专题图,并添加经纬网
  10. Qt QScrollArea