可设置八个闹钟的智能时钟原理图+程序.docx

上传人:b****4 文档编号:5459579 上传时间:2022-12-16 格式:DOCX 页数:14 大小:35.39KB
下载 相关 举报
可设置八个闹钟的智能时钟原理图+程序.docx_第1页
第1页 / 共14页
可设置八个闹钟的智能时钟原理图+程序.docx_第2页
第2页 / 共14页
可设置八个闹钟的智能时钟原理图+程序.docx_第3页
第3页 / 共14页
可设置八个闹钟的智能时钟原理图+程序.docx_第4页
第4页 / 共14页
可设置八个闹钟的智能时钟原理图+程序.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

可设置八个闹钟的智能时钟原理图+程序.docx

《可设置八个闹钟的智能时钟原理图+程序.docx》由会员分享,可在线阅读,更多相关《可设置八个闹钟的智能时钟原理图+程序.docx(14页珍藏版)》请在冰豆网上搜索。

可设置八个闹钟的智能时钟原理图+程序.docx

可设置八个闹钟的智能时钟原理图+程序

可设置8个闹钟时间的智能时钟

广东珠海曾向文

普通的家用时钟一般只能设置一个闹钟时间,但很多人均需为工作日、周末、早晨、午休等不同时段设置不同的闹钟时间。

如果是使用普通的闹钟,只好每次休息前重新设置,很不方便,有时甚至会出现忘记更改闹钟设置而睡过头的情况。

针对这种情况,本人利用89C51单片机设计了一款有8种闹钟设置的时钟,通过一段时间的使用,情况良好。

1、元件清单

共阴极数码管8个4511七段译码芯片1片

ATMEL89C51单片机1片24C08EEPROM1片

24M晶振1个9V变压器(3VA)1个

LM317输出可调稳压IC1个整流桥堆1个

470uF电容1个100uF电容1个

10uF电容1个0.1uF电容1个

33pF电容2个蜂鸣器1个

9014(或其它NPN管)8个ksp92(或其它PNP管)1个

二极管2个1K欧电阻16个

470欧电阻1个10K欧可调电阻1个

10K欧电阻4个按钮开关4个

可装四节电池的电池盒1个万能板(约12CM*17CM)1块

所有元件按以下的电路图焊接在一块万能板上。

注意LM317的输出应由低调高,以免烧IC。

电路图

2、功能简介

该时钟以24小时制显示时间,并可显示2000年至2049年之间的任何日期及星期,日期与时间经按键可相互切换,可输入8个闹钟时间设置,每个闹钟设置包括响铃的时间(小时与分钟)、对工作日有效还是对周末有效的标志,以及本项设置是否启用的标志等三部分。

这8个闹钟设置均保存在EEPROM中,即使掉电也不用重新输入。

当然使用者可通过按钮对任何一个设置作修改。

数码管可经按钮关闭显示,避免夜间刺眼、影响睡眠。

调节LM317输出电压,可改变数码管亮度,但电压不能低于后备电池的电压,否则后备电池供电。

用四节1.25V电池串联作后备电源,保证市电停电时时钟继续走时。

时钟的精度取决于晶振频率的精度。

3、程序清单

本程序用C语言编写,经KeilC51编译成二进制码后写入89C51内的EPROM内即可。

#include"atmel\at89x51.h"

#include"intrins.h"

unsignedcharhour,min,sec,year,month,day,weekday;//当前时间、日期、星期

unsignedintcount_down;//1秒钟计时用

bitled_on;//数码管是否点亮的标志

unsignedchardisplay[8];//8位数码管要显示的数据

unsignedcharattr;//八个数码管的闪烁控制字节,当为0时,对应数码管闪

bitflash;//LED闪烁开关,与attr共同决定数码管是否闪烁

unsignedcharshow_status;//LED显示状态标志

//0:

设置闹钟数据

//1:

显示当前日期及星期

//2:

显示当前时间

//3:

设置当前日期

//4:

设置当前时间

bitkm;//按键已去抖动标志

bitkp;//按键已处理标志

bitsound;//蜂鸣器响标志

bitalarm_stop;//蜂鸣器响后用户手工按停标志

struct{unsignedcharh;//小时

unsignedcharm;//分钟

}alarm[8];//8个闹钟项

unsignedcharalarm_en;//闹钟项启用标志

unsignedcharalarm_wk;//闹钟项周末启用标志

unsignedcharcur_alarm_set;//当前设置的闹钟项

unsignedcharcur_alarm_active;//当前到点的闹钟项

bitnew_alarm_info;//闹钟项内容已修改标志

sbitsound_output=P1^5;//蜂鸣器驱动端口,输出0时蜂鸣器响

sbitSDA_PIN=P1^6;//EEPROM数据线端口

sbitSCL_PIN=P1^7;//EEPROM时钟线端口

voidI2cDelay()//EEPROM操作时需要的延时函数

{_nop_();_nop_();_nop_();

_nop_();_nop_();_nop_();

}

voidDelayX1ms(unsignedcharcount)//延迟函数,参数为毫秒数

{unsignedchari,j;

for(i=0;i

for(j=0;j<240;j++);

}

voidStart()//I2C启动,24C08使用I2C方式

{SDA_PIN=1;I2cDelay();

SCL_PIN=1;I2cDelay();

SDA_PIN=0;I2cDelay();

SCL_PIN=0;

}

voidStop()//I2C停止

{I2cDelay();SDA_PIN=0;

I2cDelay();SCL_PIN=1;

I2cDelay();SDA_PIN=1;

I2cDelay();

}

bitSendByte(unsignedcharvalue)//发送1字节数据给EEPROM

{unsignedchari;

bitno_ack=0;

for(i=0;i<8;i++)//发送8位数据

{I2cDelay();

if(value&0x80)SDA_PIN=1;

elseSDA_PIN=0;

value=value<<1;

I2cDelay();SCL_PIN=1;

I2cDelay();

I2cDelay();SCL_PIN=0;

}

I2cDelay();SDA_PIN=1;//确认脉冲周期,等待EEPROM的确认

I2cDelay();SCL_PIN=1;

I2cDelay();

if(SDA_PIN==1)no_ack=1;

I2cDelay();SCL_PIN=0;

returnno_ack;

}

voidmywrite(unsignedcharaddress,unsignedcharvalue)//向EEPROM写1字节

{Start();SendByte(0xa0);SendByte(address);

SendByte(value);Stop();DelayX1ms(10);

}

unsignedcharReadByte()//从EEPROM接收1字节

{unsignedchari,bval;

bval=0;

for(i=0;i<8;i++)//接收8位数据

{I2cDelay();

SDA_PIN=1;//从P1输入数据时,先往P1输入“1”

I2cDelay();SCL_PIN=1;

I2cDelay();bval=bval<<1;if(SDA_PIN)bval=bval|0x01;

I2cDelay();SCL_PIN=0;

}

I2cDelay();SDA_PIN=1;//确认脉冲周期,不送出确认

I2cDelay();SCL_PIN=1;

I2cDelay();

I2cDelay();

return(bval);

}

unsignedcharmyread(unsignedcharaddress)//从EEPROM读入1字节数据

{unsignedchartmp;

Start();SendByte(0xa0);SendByte(address);

Start();SendByte(0xa1);tmp=ReadByte();

Stop();DelayX1ms

(2);

return(tmp);

}

voidTimer0ISR(void)interrupt1using3//定时器0中断程序,用于走时,1/8000秒一次

{unsignedchartmp,tmp_days;

count_down--;

if(count_down==1||count_down==2001||count_down==4001||count_down==6001)

{flash=~flash;//数码管闪烁的开关量

if(sound&&flash)sound_output=0;//驱动蜂鸣器

elsesound_output=1;//关闭蜂鸣器

return;

}

/***计算当前日期为星期几***/

if(count_down==3000)

{if(year==0)weekday=5;//2000年1月1日为星期六

else{tmp=(year-1)/4+1;tmp=(year-tmp)+tmp*2;

weekday=(tmp+5)%7;//计算出当前年的1月1日为星期几

}

tmp_days=0;

for(tmp=1;tmp

if(tmp==1||tmp==3||tmp==5||tmp==7||tmp==8||tmp==10)

tmp_days=tmp_days+31;

elseif(tmp==4||tmp==6||tmp==9||tmp==11)

tmp_days=tmp_days+30;

elseif(tmp==2)

{if(year%4==0)tmp_days=tmp_days+29;

elsetmp_days=tmp_days+28;

}

tmp_days=tmp_days+day-1;weekday=(weekday+tmp_days%7)%7+1;

return;

}

/***查询是否有闹钟时间项符合触发条件***/

if(count_down==5000)

{if((alarm_stop||sound)&&alarm[cur_alarm_active].m!

=min)//触发后1分钟

{alarm_stop=0;sound=0;}//自动关蜂鸣器

if(sound==0&&alarm_stop==0)//没有已触发的闹钟项

for(tmp=0;tmp<8;tmp++)//则查询8个闹钟项内是否有符合条件的

{if(((alarm_en>>tmp)&1)==0)continue;//该闹钟项不启用

if(((alarm_wk>>tmp)&1)==1)//该闹钟项周末有效

{if(weekday!

=6&&weekday!

=7)continue;}//当前不是星期六或星期天

else

{if(weekday==6||weekday==7)continue;}

if(alarm[tmp].h==hour&&alarm[tmp].m==min)//比较当前时间与该

{sound=1;cur_alarm_active=tmp;break;}//闹钟项的时间

}

return;

}

if(count_down==0)//过了一秒钟

{count_down=8000;

sec++;

if(sec==60)

{sec=0;

min++;

if(min==60)

{min=0;

hour++;

if(hour==24)

{hour=0;day++;

switch(day)

{case29:

if(month==2&&year%4){day=1;month=3;}

break;

case30:

if(month==2&&year%4==0){day=1;month=3;}

break;

case31:

if(month==4||month==6||month==9||month==11)

{day=1;month++;}

break;

case32:

day=1;month++;

if(month==13){month=1;year++;}

}

}

}

}

}

}

voidTimer1ISR(void)interrupt3using2//定时器2中断,用于按键扫描

{unsignedcharkeytmp;

chartmp;

TH1=0x15;TL1=0xa0;//每30ms中断一次

/***当前显示的内容***/

if(show_status==0)//当前正在设置闹钟项

{display[0]=cur_alarm_set;display[1]=0xf;

display[2]=alarm[cur_alarm_set].h/10;display[3]=alarm[cur_alarm_set].h%10;

display[4]=alarm[cur_alarm_set].m/10;display[5]=alarm[cur_alarm_set].m%10;

display[6]=(alarm_wk>>cur_alarm_set)&1;display[7]=(alarm_en>>cur_alarm_set)&1;

}

if(show_status==1||show_status==3)//当前显示或设置日期

{display[0]=year/10;display[1]=year%10;display[2]=month/10;

display[3]=month%10;display[4]=day/10;display[5]=day%10;

display[6]=0xf;display[7]=weekday;

}

if(show_status==2||show_status==4)//当前显示或设置时间

{display[0]=hour/10;display[1]=hour%10;display[2]=min/10;

display[3]=min%10;display[4]=sec/10;display[5]=sec%10;

display[6]=0xf;display[7]=0xf;//最后两后无显示

}

/***按键扫描及处理***/

keytmp=~(P1)&0x0f;

if(keytmp==0){km=0;kp=0;}

else

{if(km==0)km=1;

else

{if(kp==0)

{kp=1;

if(keytmp==1)//第一个按钮

{if(sound){alarm_stop=1;sound=0;}//如果闹钟正响,按此键停止

elseif((show_status==1||show_status==2)&&led_on)//正显示日期或时间

{show_status=0;cur_alarm_set=0;attr=0x3f;}//进入闹钟设置

elseif(show_status==0)//如正在设置闹钟时间项

{show_status=2;new_alarm_info=1;attr=0xff;}//返回当前时间显示

return;

}

if(keytmp==2&&led_on)//第二个按钮,仅当数码管打开时有效

{switch(attr)

{case0xff:

if(show_status==1)show_status=2;//在显示时间与日期间切换

elseif(show_status==2)show_status=1;

break;

case0x3f:

if(show_status==0)cur_alarm_set=(cur_alarm_set+1)%8;

elseif(show_status==3)

year=(year+1)%50;//当前日期的“年”加1

elseif(show_status==4)

hour=(hour+1)%24;//当前时间的“时”加1

break;

case0xcf:

if(show_status==0)//闹钟设置的“时”加1

alarm[cur_alarm_set].h=(alarm[cur_alarm_set].h+1)%24;

elseif(show_status==3)

{month++;//当前日期的“月”加1

if(month==13)month=1;}

elseif(show_status==4)

min=(min+1)%60;//当前时间的“分”加1

break;

case0xf3:

if(show_status==0)

alarm[cur_alarm_set].m=(alarm[cur_alarm_set].m+1)%60;

elseif(show_status==3)

{day++;//当前日期的“日”加1

if(day==32)day=1;}

elseif(show_status==4)

{count_down=8000;

sec=(sec+1)%60;}//当前时间的“秒”加1

break;

case0xfd:

if(show_status==0)

alarm_wk^=0x1<

break;

case0xfe:

if(show_status==0)

alarm_en^=0x1<

}//endofswitch(attr)

return;

}//endofif(keytmp==1)

if(keytmp==4)//第三个按钮

{switch(attr)

{case0xff:

if(show_status==1||show_status==2)

led_on=~led_on;//打开或关闭数码管显示

break;

case0x3f:

if(show_status==0)//如果正在设置闹钟

{if(cur_alarm_set==0)cur_alarm_set=7;

elsecur_alarm_set--;}

elseif(show_status==3)//当前日期的“年”减1

{if(year==0)year=49;elseyear--;}

elseif(show_status==4)//当前时间的“时”减1

{tmp=hour-1;if(tmp<0)hour=23;elsehour=tmp;}

break;

case0xcf:

if(show_status==0)//闹钟设置的“时”减1

{tmp=alarm[cur_alarm_set].h-1;

if(tmp<0)alarm[cur_alarm_set].h=23;

elsealarm[cur_alarm_set].h=tmp;

}

elseif(show_status==3)

{month--;//当前日期的“月”减1

if(month==0)month=12;}

elseif(show_status==4)

{tmp=min-1;//当前时间的“分”减1

if(tmp<0)min=59;elsemin=tmp;}

break;

case0xf3:

if(show_status==0)//闹钟设置的“分钟”减1

{tmp=alarm[cur_alarm_set].m-1;

if(tmp<0)alarm[cur_alarm_set].m=59;

elsealarm[cur_alarm_set].m=tmp;

}

elseif(show_status==3)

{day--;//当前日期的“日”减1

if(day==0)day=31;}

elseif(show_status==4)

{tmp=sec-1;//当前时间的“秒”减1

count_down=8000;

if(tmp<0)sec=59;elsesec=tmp;}

break;

case0xfd:

if(show_status==0)//切换周末标志

alarm_wk^=0x1<

break;

case0xfe:

if(show_status==0)//切换启用标志

alarm_en^=0x1<

}//endofswitch(attr)

return;

}//endofif(keytmp==2)

if(keytmp==8&led_on)//第四个按钮,仅当数码管打开时有效

{switch(attr)

{case0xff:

if(show_status==1)//如果当前显示日期

show_status=3;//切换到调准日期状态

elseif(show_status==2)//如果当前显示时间

show_status=4;//切换到调准时间状态

attr=0x3f;break;//第一、二个数码管闪烁

case0x3f:

attr=0xcf;break;//第三、四个数码管闪烁

case0xcf:

attr=0xf3;break;//第五、六个数码管闪烁

case0xf3:

if(show_status==0)attr=0xfd;//第七个数码管闪烁

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1