多功能电子时钟(带时区划分,闹钟,区分上午和下午)
来源:互联网 发布: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) //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;
}
}
- 多功能电子时钟(带时区划分,闹钟,区分上午和下午)
- 单片机编写多功能电子时钟
- android studio tabhost基础 多功能时钟app 实现闹钟功能(一)
- android studio tabhost基础 多功能时钟app 实现闹钟功能 TimePickerDialog(二)
- android studio tabhost基础 多功能时钟app 使用sharedpreference存储闹钟数据(三)
- android studio tabhost基础 多功能时钟app 删除闹钟(四)
- android studio tabhost基础 多功能时钟app 设置闹钟 alarmmanager(五)
- android studio tabhost基础 多功能时钟app 闹钟执行后清除 alarmmanager(六)
- android studio tabhost基础 多功能时钟app 闹钟铃声(七)
- Linux时钟和时区
- 关于iis 时间格式 带星期、上午、下午的问题
- 电子闹钟
- 如何去除时间显示里的上午和下午
- 2007年上半年程序员考试标准答案(上午和下午)
- 2007年下半年软件设计师考试标准答案(上午和下午)
- 2007年下半年程序员考试标准答案(上午和下午)
- 单片机做成的带闹钟的时钟程序
- java 实现的带闹钟的数字时钟
- 代码调试技巧
- 查看gcc的版本
- Javascript的history对象的back的使用
- 1004let the balloon rise
- 第九周任务之编程
- 多功能电子时钟(带时区划分,闹钟,区分上午和下午)
- Vs2010 vs2008 vs2005 链接libcurl静态库
- Javascript全选、反选、取消选择
- 基于MapWinGis的开发探索(三)--改善缩放、渲染、显示文本
- Javascript表格的显示和隐藏
- 刘云浩:群智感知——从主动击发,到无意识配合(众包思想的延展)
- JAVA程序配置开机启动
- Javascript实现鼠标经过改变按钮
- Build a Desktop GIS Application Using MapWinGIS and C#