版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
#include<reg52.h>#include"24c02.h"#defineucharunsignedchar#defineuintunsignedintsbitkey1=P3^7;sbitkey2=P3^6;sbitkey3=P3^5;sbitkey4=P3^4;sbitled=P1^7;//定义秒针的指示灯sbitbeep=P2^3; //定义蜂鸣器sbitled1=P1^0; //定义左边数字调整指示灯sbitled2=P1^1; //定义右边数字调整指示灯sbitled3=P1^2; //定义秒表状态指示灯sbitled4=P1^3; //定义日期调整状态指示灯sbitled5=P1^4; //定义闹铃调整状态指示灯ucharcodetable[10]={0xa0,0xbe,0x62,0x2a,0x3c,0x29,0x21,0xba,0x20,0x28};ucharcodetable_dot[10]={0x80,0x9e,0x42,0x0a,0x1c,0x09,0x01,0x9a,0x00,0x08};ucharmode,adjust,hour,min,sec,num0,num1,month,day,bell_hour,bell_min; /*mode为指示电子钟模式的变量,mode=0为正常状态,1为秒表状态,2为日期调整状态,3为闹铃调整状态。adjust为调整选择变量,adjust=0时不调整任何变量,=1时为小时/月份调整状态,=2时为分钟/日期调整状态。hour、min、sec分别为时钟的小时、分钟、秒钟。num0、num1为记录定时器溢出次数的变量。month、day、bell_hour、bell_min分别为月份、日期、闹铃小时、闹铃分钟。*/bitfrezze=0,date_display,bell_display,flag; /*frezze为表示秒表显示是否静止的变量(frezze=1时秒表显示静止)。date_display、bell_display为指示日期、闹铃显示状态的变量。*/uintmin1,sec1,a,b; //min1、sec1为秒表状态时的分、秒*10。a,b为秒表示数静止时保存秒表分和秒和临时变量*//**************************************************//********************延时函数********************//*************************************************/voiddelay(m){ uinti,j; for(i=m;i>0;i--) for(j=110;j>0;j--); }voiddi(){ beep=0; delay(12); beep=1;}/**************************************************//**********时间显示时的显示子函数**************//**************************************************/voiddisplay(ucharhour_1,ucharmin_1){ uchara,b,c,d; a=hour_1/10; //分离小时和分钟的个位和十位 b=hour_1%10; c=min_1/10; d=min_1%10; if(a==0) //如果小时的十位为零则只显示个位 { P2=0xdf; P0=0xff; P0=table_dot[b]; delay(1); } else { P2=0xbf; P0=0xff; P0=table[a]; delay(1); P2=0xdf; P0=0xff; P0=table_dot[b]; } delay(1); P2=0xef; P0=0xff; P0=table[c]; delay(1); P2=0x7f; P0=0xff; P0=table[d]; delay(1); P0=0xff;}/************************************************//*************秒表状态时的显示子函数*************/voiddisplay_stopwatch(ucharmin1,uintsec1) //该函数为0~10分钟内的显示子函数,其中第一位显示分钟,第二、三位显示秒钟、最后一位显示0.1秒{ uchara,b,c; a=(sec1%1000)/100; b=(sec1%100)/10; c=sec1%10; P2=0xbf; P0=0xff; P0=table_dot[min1]; delay(5); P2=0xdf; P0=0xff; P0=table[a]; delay(5); P2=0xef; P0=0xff; P0=table_dot[b]; delay(5); P2=0x7f; P0=0xff; P0=table[c]; delay(5); P0=0xff;}/**************************************************//*****************秒表显示子函数2******************/voiddisplay_stopwatch2(ucharmin1,uintsec1){ //该函数为10~99分钟内的显示子函数 uchara,b,c,d; //其中前两位为分钟,后两位为秒钟 a=min1/10; b=min1%10; c=sec1/100; d=(sec1/10)%10; P2=0xbf; P0=0xff; P0=table[a]; delay(1); P2=0xdf; P0=0xff; P0=table_dot[b]; delay(1); P2=0xef; P0=0xff; P0=table[c]; delay(1); P2=0x7f; P0=0xff; P0=table[d]; delay(1); P0=0xff;}/**************************************************//****************日期状态时的显示子函数************/voiddisplay_date(ucharmonth,ucharday){ uchara,b,c,d; a=month/10; b=month%10; c=day/10; d=day%10; if(a==0) //如果月份的十位为零则只显示个位 { P2=0xdf; P0=0xff; P0=table_dot[b]; delay(1); P0=0xff; } else { P2=0xbf; P0=0xff; P0=table[a]; delay(1); P2=0xdf; P0=0xff; P0=table_dot[b]; delay(1); P0=0xff; } if(c==0) { P2=0x7f; P0=0xff; P0=table[d]; delay(1); P0=0xff; P0=0xff; } else { P2=0xef; P0=0xff; P0=table[c]; delay(1); P2=0x7f; P0=0xff; P0=table[d]; delay(1); P0=0xff; P0=0xff; }}/******************************************//****************键盘检测函数**************//******************************************/voidkeyscan(){ if(key1==0) //按下第一个键时钟将在正常状态、秒表状态、日期调整状态和 { //闹铃调整状态之间循环切换 di(); //每按一下按键蜂鸣器“嘀”一下 delay(10); if(key1==0) { mode++; if(mode==4)mode=0; //mode取值范围为0~3,故mode加到4时应清零 if(flag==1)mode=0; //如果在秒表状态、日期调整状态或闹铃调整下进行了操作,则flag将会被置1,如果按下key1时检测到flag为1,则直接返回到正常模式 if(mode==2||mode==3)adjust=2; elseadjust=0; flag=0; //每次按下key1键时flag要置0 led=1;//切换模式时应使秒针指示灯熄灭 while(!key1); } } if(key2==0&&mode!=1) //按下第二个按键时在小时/月份调整状态、分钟/日期调整状态和非调整状态之间循环切换 { di(); delay(10); if(key2==0) { if(mode==0) //在正常状态下可以在小时/月份、分钟/日期和非调整状态之间切换 { if(adjust==0)adjust=3; } else //而在其他状态下只能小时/月份、分钟/日期之间切换 { if(adjust==1)adjust=3; } adjust--; while(!key2); } } if(key3==0) //在调整状态时按下该键时对应的变量加1 { if(mode==0&&adjust==0) //在正常状态且非调整状态时按住该键将显示日期,放开后恢复显示时间 { date_display=1; led=1; //按住时应保证秒针指示灯熄灭 } else { flag=1; //按下该键后flag被置1 di(); delay(10); if(key3==0) { switch(mode) { case0: //mode为0时,调整时间 if(adjust==1) { hour++; if(hour==24) //当小时加到24时应该清零,下面的同理 hour=0; write_add(3,hour); //每调整一次将改变写入AT24C02 } elseif(adjust==2) { min++; if(min==60) min=0; write_add(2,min); } break; case2: //mode为2时,调整日期 if(adjust==1) { month++; if(month==13)month=1; write_add(5,month); } elseif(adjust==2) { day++; switch(month) { case1:case3:case5:case7:case8:case10:case12: if(day>=32) day=1; break; case4:case6:case9:case11: if(day>=31) day=1; break; case2: if(day>=29) day=1; break; } write_add(4,day); } break; case3: //mode为3时,调整闹铃时间 if(adjust==1) { bell_hour++; if(bell_hour==24) bell_hour=0; write_add(7,bell_hour); } elseif(adjust==2) { bell_min++; if(bell_min==60) bell_min=0; write_add(6,bell_min); } break; case1: //mode为1时为秒表状态,按下该键时启动或停止计时 TR1=~TR1; //启动或停止定时器1 led=1; //确保计时停止时最后一个发光二极管熄灭 break; } while(!key3); } } } elsedate_display=0; if(key4==0) //在调整状态时按下该键时对应的变量减1 { //此按键的注释与上面的类似,这里不再重复 if(mode==0&&adjust==0) { bell_display=1; led=1; } else { flag=1; di(); delay(100); if(key4==0) { switch(mode) { case0: if(adjust==1) { if(hour==0) //当小时加到24时应该清零,下面的同理 hour=24; hour--; write_add(3,hour); } elseif(adjust==2) { if(min==0) min=60; min--; write_add(2,min); } break; case2: if(adjust==1) { if(month==1)month=13; month--; write_add(5,month); } elseif(adjust==2) { switch(month) { case1:case3:case5:case7:case8:case10:case12: if(day==1) day=32; break; case4:case6:case9:case11: if(day==1) day=31; break; case2: if(day==1) day=29; break; } day--; write_add(4,day); } break; case3: if(adjust==1) { if(bell_hour==0) bell_hour=24; bell_hour--; write_add(7,bell_hour); } elseif(adjust==2) { if(bell_min==0) bell_min=60; bell_min--; write_add(6,bell_min); } break; case1: if(TR1==0) //当秒表暂停时按下该按键则秒表清零 { if(frezze)frezze=0;//如果在显示静止时按下了key1键使得计数暂停,则如果按下key2键, //应退出显示静止状态,显示当前秒表时间,再次按下s2键时秒表才清零 elsemin1=0,sec1=0; } else //若秒表正在计时时按下该按键则秒表显示静止,但计时仍继续 { if(frezze==0) { a=min1,b=sec1; //在计时过程中将按下该键时秒表的分和秒存入临时变量a和b } frezze=~frezze; //进入或退出显示静止状态 } } while(!key4); } } } elsebell_display=0;}/**********************************************//*******************主函数*********************//**********************************************/voidmain(){ TMOD=0x11; //设置定时器0和1的工作方式 TH0=(65536-50000)/256; //装初值 TL0=(65536-50000)%256; TH1=(65536-50000)/256; TL1=(65536-50000)%256; EA=1; //开总中断 ET0=1; //开定时器0中断 ET1=1; //开定时器1中断 TR0=1; //启动定时器0 TR1=0; //定时器1未运行 init_24c02(); sec=read_add(1); //程序首次执行时从AT24C02里读取数据 if(sec>=60)sec=0; //防止读到错误的数据 min=read_add(2); if(min>=60)min=0; hour=read_add(3); if(hour>=24)hour=0; day=read_add(4); if(day>31||day==0)day=1; month=read_add(5); if(month>=12||month==0)month=1; bell_min=read_add(6); if(bell_min>=60)bell_min=0; bell_hour=read_add(7); if(bell_hour>=24)bell_hour=0; while(1) { keyscan(); if(adjust==1)led1=0; elseled1=1; //当处于小时、月份、闹铃的小时状态时,第一个发光二极管亮 if(adjust==2)led2=0; elseled2=1; //当处于分钟、日期、闹铃的分钟状态时,第二个发光二极管亮 if(min==0&&sec==0)beep=0; //整点报时功能:当时间为0分0秒时蜂鸣器响,保持1秒钟 if(bell_hour==hour&&bell_min==min&&mode==0&adjust==0) { //当闹铃时间等于当前时间且不处于闹铃调整状态时时, if(num0==0)beep=0; //蜂鸣器以1秒为周期鸣响 if(num0==6)beep=1; if(num0==7)beep=0; if(num0==13)beep=1; } if(mode==1) { led3=0; //秒表状态时秒表状态指示灯亮,其他灯熄灭 led4=led5=1; if(min1<10) //当分钟小于10时则调用display_stopwatch来显示 { if(frezze==0) display_stopwatch(min1,sec1); elsedisplay_stopwatch(a,b); //在frezze为0时显示按下key3键时的时间,即显示静止 } else //当分钟大于或等于10时则调用display_stopwatch2来显示 { if(frezze==0) display_stopwatch2(min1,sec1); elsedisplay_stopwatch2(a,b); } } elseif(mode==2||date_display==1) //在日期调整状态或日期显示状态时显示当前日期 { led4=0; //日期状态指示灯亮,其他灯熄灭 led3=led5=1; display_date(month,day); } elseif(mode==3||bell_display==1) //在闹铃调整状态或闹铃显示状态时显示当前闹铃时间 { led5=0; led3=led4=1; display(bell_hour,bell_min); } else //正常状态时显示当前时间 { display(hour,min); led3=led4=led5=1; } }}/*******************************************************//**********定时器0中断(用于电子钟时间的计时)**********//*******************************************************/voidt0_time()interrupt1{ TH0=(65536-50000)/256; TL0=(65536-50000)%256; //重装初值 num0++; if(num0==20) //当num0加到20时,则1秒的时间到,num0清零 { num0=0; sec++; write_add(1,sec); if(sec==60) { min++; sec=0; write_add(2,min); } if(min==60) { hour++; min=0; write_add(3,hour); } if(hour==24) { hour=0; day++; switch(month) { case1:case3:case5:case7:case8:case10:case12: if(day>=32) { day=1; month++; } break; case4:case6:case9:case11: if(day>=31) { day=1; month++; } break; case2: if(day>=29) { day=1; month++; } break; } write_add(4,day); if(month==13)month=1; write_add(5,month); } } if(num0%10==0&&mode==0&&date_display==0&&bell_display==0) //只有在正常状态且不在日期或闹铃显示状态时, led=~led; //秒钟指示灯每0.5秒闪烁一次}/****************************************************//***********定时器1中断(用于秒表的计时)************//****************************************************/voidt1_time()interrupt3{ TH1=(65536-50000)/256; TL1=(65536-50000)%256; //重装初值 num1++; if(num1==2) //当num1加到2时则0.1秒的时间到,num1清零 { num1=0; sec1++; if(sec1==600) { min1++; sec1=0; } if(min1==100) min1=0; if((sec1%5==0)&&mode==1&&date_di
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 智能水表电磁干扰抗性测试技师(中级)考试试卷及答案
- 眼镜制造工程师考试试卷及答案
- 厦门大学2026年强基计划复试《面试+体育测试》模拟试题及答案解析
- 2025年山东省蓬莱市高二生物下册期末考试模拟卷附答案【B卷】
- 2026年广东省连州市高二生物下册期末考试模拟卷附完整答案(易错题)
- 2026年福建省龙海市高二生物下册期末考试试卷【研优卷】附答案
- 2026年湖北省枣阳市高二生物下册期末考试模拟卷A4版附答案
- 2025年黑龙江省富锦市高二生物下册期末考试测试卷含答案(预热题)
- 2026年江苏省启东市高二生物下册期末考试试卷及参考答案(A卷)
- 2026年山东省诸城市高二生物下册期末考试模拟卷【满分必刷】附答案
- 2025年城投债券新增及地方债务结构演变观察(成都篇)
- 2025年鞍山辅助警务人员考试练习题及答案
- 2026年广东省实验中学中考英语二模试卷
- 2026年辽宁锦州海通实业有限公司计划招录28人备考题库及一套参考答案详解
- 2026春北师大版三年级下册数学期末易错题专项训练试卷附答案
- 2026-2030中国氯丙烯市场运行现状及竞争策略研究报告
- 2026年安徽省八年级地生会考真题试卷+答案
- 珠海市2025广东横琴粤澳深度合作区执行委员会招26人笔试历年参考题库典型考点附带答案详解
- 2026年安全生产月主题培训
- 北京金隅物业服务有限公司招聘笔试题库2026
- 2026中国教师生成式人工智能应用报告
评论
0/150
提交评论