| 
UID274637阅读权限60推广 幽默 注册时间2012-3-21最后登录1970-1-1 
 | 
 
 
 楼主|
发表于 2019-4-28 22:43:52
|
显示全部楼层 
| #include<STC89C5xRC.H> #include<intrins.h>                //包含_nop_函数
 #define uchar unsigned char
 #define uint unsigned int
 sbit RS = P2^2;
 sbit RW = P2^1;
 sbit EN = P2^0;
 sbit she=P1^0;                //设置键
 sbit jia=P1^1;                //加键
 sbit jian=P1^2;                //减键
 sbit qx=P1^3;                //取消键
 bit bi,key,tt;
 char n,y,r,h,m,s,q,v,tian,k,jj,ja,w1,w2,w3,w4,w5,w6;
 uchar e,f,g;
 uint ys;
 uchar code ma[]={0X30,0X31,0X32,0X33,0X34,0X35,0X36,0X37,0X38,0X39};           //0~9对应ASCII码
 void delay(uint a);          //毫秒延时函数
 void mingling(uchar com);         //1602写指令函数
 void zifu(uchar f);                         //1602写字符函数
 void run (char nian,char yue);           //闰年计算函数
 void  date(uchar p,uchar d,uchar w);        //显示数字函数
 void display(char n1,char y1,char r1,char h1,char m1,char s1);  //整体显示年月日时分秒函数
 bit mang( )           //查忙函数
 {
 P0=0xff;
 RS=0;
 RW=1;
 EN=0;
 _nop_();
 EN=1;
 return (bit)(P0 & 0x80);
 }
 
 void main(void)
 {
 n=0;
 y=1;
 r=1;
 h=12;
 m=0;
 s=0;                                 //默认年月日时分秒初始值
 mingling(0X38);         //16*2显示,5*7点阵,8位数据口
 mingling(0X0C);         //开显示,不显示光标,不闪烁
 mingling(0X06);    //读或者写一个字符后,指针地址自动+1,且光标+1
 mingling(0X01);    //清屏
 display(n,y,r,h,m,s);          //显示年月日时分秒
 EA=1;
 ET0=1;
 ET1=1;
 TMOD=0X11;
 TH0=0X3C;
 TL0=0XB0;
 TH1=0X3C;
 TL1=0XB0;
 TR0=1;                                //开中断,配置定时器0和定时器1,并启动定时器0
 while(1)                                //主程序只负责扫描4个按键,并执行按键指令
 {
 if(she==0&&key==1)
 {
 delay(5);
 if(she==0)                  //设置键
 {
 ys=0;                  //归零延时数值
 key=0;          //标记有按键按下(主函数在最后进行所有按键的松手检测,确保按下一次只执行一次,且没有松手前不执行新的按键指令)
 v=1;                  //标记设置键有效,定时器0不刷新显示(不在设置状态,加减和取消都无效)
 mingling(0xc9);        //设置指针地址在秒数的前一位(:的位置)
 zifu(':');                //把闪烁的“:”显示出来,(按下设置键的时候“:”有可能在不显示状态)
 g++;                                //记录设置键按下次数
 if(g==1)                        //第一次按下设置键
 {
 w1=n;
 w2=y;
 w3=r;
 w4=h;
 w5=m;
 w6=s;                          //复制当前时间年月日时分秒数值
 q=2;                          //设置参数的指针地址0x83+2=0x85(tt=0控制0x83,tt=1控制0xc3)
 k=w1;                          //把年份数字赋给k(定时器1调用k并配合指针地址进行闪烁显示,加减键调用k进行加减运算,使加减操作和显示同步)
 tt=0;
 TR1=1;                  //启动定时器1,开始闪烁显示
 }
 if(g==2)                          //第二次按下设置键
 {
 TR1=0;                  //关闭定时器1(避免定时器1中断切入刷新屏幕)
 w1=k;                  //把第一次调整的年份数值保存
 date(1,2,w1);  //把年份显示出来(调试由年份改为月份时,年份可能被定时器1刷新在不显示状态)
 q=5;                          //月份指针地址(0x83+5=0x88)
 k=w2;                  //月份数值
 TR1=1;                  //调试月份准备工作完成,启动定时器1
 }
 if(g==3)                          //第三次按下设置键
 {
 TR1=0;
 w2=k;
 date(1,5,w2);
 q=8;
 k=w3;                   //天数
 run(w1,w2);           //调用闰年函数,把当前年份和月份给闰年函数,得出当月最大天数
 if(k>tian)           //如果当前数值大于闰年函数计算出来的最大天数
 k=tian;           //把当前数值修改为最大天数(-------1-------)
 TR1=1;
 }
 if(g==4)
 {
 TR1=0;
 w3=k;
 date(1,8,w3);
 q=1;
 k=w4;
 tt=1;
 TR1=1;
 }
 if(g==5)
 {
 TR1=0;
 w4=k;
 date(2,1,w4);
 q=4;
 k=w5;
 TR1=1;
 }
 if(g==6)
 {
 TR1=0;
 w5=k;
 date(2,4,w5);
 q=7;
 k=w6;
 TR1=1;
 }
 if(g==7)                 //第七次按下设置键
 {
 TR1=0;         //关闭定时器1,不需要再闪烁了
 w6=k;
 date(2,7,w6);
 n=w1;
 y=w2;
 r=w3;
 h=w4;
 m=w5;
 s=w6;           //把调试好的时间数值分别赋给年月日时分秒(设置生效)
 TR0=0;
 TH0=0X3C;
 TL0=0XB0;
 TR0=1;           //重新初始化定时器0,并启动
 TH1=0X3C;
 TL1=0XB0;   //初始化定时器1
 g=0;                   //清除设置键次数
 v=0;                   //允许定时器0刷新屏幕并禁止加减键和取消键
 }
 }
 }
 if(jia==0&&v==1&&key==1)
 {
 delay(5);
 if(jia==0)                   //加键按下
 {
 ys=0;                        //清零延时
 key=0;                        //标记有按键按下
 ja=k;                        //把当前需要设置的数值k转移给ja
 ja++;                        //+1
 if(g==1)                //年份调整
 {
 if(ja>99) //最大2099年,调整的后两位
 ja=0;                //大于99清零
 }
 if(g==2)                //月份调整
 {
 if(ja>12)  //月份超过12
 ja=1;   //月份清1,月份和天数最小是1,没有0月0日这一天
 }
 if(g==3)                 //天数调整
 {
 run(w1,w2);
 if(ja>tian)        //大于该月最大天数
 ja=1;                //天数清1
 }
 if(g==4)                   //小时调整
 {
 if(ja>23)
 ja=0;
 }
 if(g==5||g==6)        //分钟和秒数最大都是60
 {
 if(ja>59)
 ja=0;
 }
 k=ja;                                //把调整加好的数值还给k(每加一次就更新一次)
 }
 }
 if(jian==0&&v==1&&key==1)
 {
 delay(5);
 if(jian==0)                                //减键按下
 {
 ys=0;                                //清除延时
 key=0;
 jj=k;
 jj--;
 if(g==1)                   //年份
 {
 if(jj<0)                //由于2000年,这个0是需要显示的,所以需要减到0以下,所有年月日时分秒变量及相关变量全部用char型有符号
 jj=99;
 }
 if(g==2)                   //月份
 {
 if(jj==0)
 jj=12;
 }
 if(g==3)                   //天数
 {
 run(w1,w2);
 if(jj==0)
 jj=tian;
 }
 if(g==4)                        //小时
 {
 if(jj<0)
 jj=23;
 }
 if(g==5||g==6)         //分钟和秒数
 {
 if(jj<0)
 jj=59;
 }
 k=jj;
 }
 }
 if(qx==0&&v==1&&key==1)                 //取消键,取消当前设置(设置未最后生效前)并恢复时钟,设置过程时钟一直在走时,只是禁止刷新屏幕而已
 {
 delay(5);
 if(qx==0)
 {
 ys=0;                                 //清零延时
 key=0;
 g=0;                                         //清零设置
 TR1=0;                                 //停止定时器1
 display(n,y,r,h,m,s);   //把屏幕刷新为当前时钟
 v=0;                                           //允许定时器0刷新屏幕,禁止加减和取消键
 }
 }
 if(she==1&&jia==1&&jian==1&&qx==1);        //松手检测,检测全部按键
 {
 delay(5);
 if(she==1&&jia==1&&jian==1&&qx==1)
 key=1;
 }
 if(ys>=400)                                           //超过20秒无操作,取消设置,并恢复时钟
 {
 TR1=0;
 ys=0;
 g=0;
 display(n,y,r,h,m,s);
 v=0;
 }
 }
 }
 void aa() interrupt 1                        //定时器0
 {
 TH0=0X3C;
 TL0=0XB0;
 f++;
 if(f==10&&v==0)
 {
 mingling(0XC9);
 zifu(' ');          //0.5秒的时候把秒的两点更新为空,即不显示两点
 }
 if(f==20)
 {
 f=0;
 s++;                          //秒+1
 if(s==60)
 {
 s=0;
 m++;          //满60秒,秒清零,分+1
 if(m==60)
 {
 m=0;
 h++;   //满60分,分清零,小时+1
 if(h==24)
 {
 h=0;
 r++;   //满24小时,小时清零,天数+1
 run (n,y);
 if(r>tian)
 {
 r=1;   //如果大于当月最大天数,天数清1
 y++;   //月份+1
 if(y==13)
 {
 y=1;
 n++;  //大于最大月数,月份清1,年份+1
 if(n==100)
 n=99;        //限制最大年份为2099年(20这两位是固定的,变化的后两位)
 if(v==0)        //允许刷新屏幕
 date(1,2,n);          //刷新年份
 }
 if(v==0)
 date(1,5,y);         //刷新月份
 }
 if(v==0)
 date(1,8,r);           //刷新天数
 }
 if(v==0)
 date(2,1,h);                  //刷新小时
 }
 if(v==0)
 date(2,4,m);                         //刷新分钟
 }
 if(v==0)
 {
 bi=1;           //显示“:”           (-------2------)
 date(2,7,s);          //刷新秒钟(年月日时分秒全部是有变化的才刷新,没有变化的则不刷新)
 }
 }
 }
 void bb() interrupt 3                 //定时器1负责对要调试的项目闪烁显示,且对无操作定时
 {
 TH1=0X3C;
 TL1=0XB0;
 e++;
 ys++;                         //无操作延时
 if(e==8)
 {
 if(tt==0)
 mingling(0X83+q);        //第一排年月日
 if(tt==1)
 mingling(0XC3+q);         //第二排时分秒
 zifu(' ');
 zifu(' ');                        //不论调试哪一项,都是两位数字,这里把要调试的两个数字改为空不显示
 }
 if(e==12)
 {
 e=0;
 if(tt==0)
 date(1,q,k);                  //显示要调试的数值
 if(tt==1)
 date(2,q,k);
 }
 }
 void delay(uint a)                          //毫秒延时函数
 {
 uint b,c;
 for(b=a;b>0;b--)
 for(c=114;c>0;c--);
 }
 void mingling(uchar com)                   //1602写命令
 {
 while(mang());                          //忙则等待
 RS=0;
 RW=0;
 EN=1;
 P0=com;
 _nop_();
 EN=0;
 }
 void zifu(uchar f)                         //写单个字符包括数字和符号
 {
 while(mang());
 RS=1;
 RW=0;
 EN=1;
 P0=f;
 _nop_();
 EN=0;
 }
 void  date(uchar p,uchar d,uchar w)         //刷新两位数字
 {
 uchar ge,shi;
 shi=w/10;
 ge=w%10;        //分离十位个位(w是要显示的两位数)
 
 if(bi==1)
 {
 bi=0;
 mingling(0XC0+9);
 zifu(':');        //秒钟显示“:”
 }
 if(p==1)
 mingling(0X83+d);
 if(p==2)                                  //p控制第一排还是第二排
 mingling(0XC3+d);
 zifu(ma[shi]);                   //取出十位和个位对应的ASC码写入1602
 zifu(ma[ge]);                   //指针自动+1,不用重新写指针命令
 }
 void run (char nian,char yue)          //闰年
 {
 if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)
 tian=31;   //最大31天
 if(yue==4||yue==6||yue==9||yue==11)
 tian=30;   //最大30天
 if(yue==2)   //2月份
 {
 if(nian%4==0)         //年被4整除
 {
 tian=29;
 }
 else                 //不能被4整除
 {
 tian=28;
 }
 }
 }
 void display(char n1,char y1,char r1,char h1,char m1,char s1)
 {
 date(1,0,20);
 date(1,2,n1);          //年
 zifu('-');
 date(1,5,y1);           //月
 zifu('-');
 date(1,8,r1);           //日
 date(2,1,h1);           //时
 zifu(':');
 date(2,4,m1);           //分
 zifu(':');
 date(2,7,s1);           //秒
 }
 /*----1----
 在设置天数的时候需要对当月天数的上限进行一次判断,比如
 之前是1月31日 ,而修改月份的时候修改为2月或者4月6月等最
 大天数没有31日的, 到调整天数的时候尚未进行加减操作时,
 屏幕(天数)依旧显示31日,这样就会是2月31日,这是错误BUG,
 自动修改为当月最大天数
 -------2------
 定时器0在刷新显示秒数的时候会和“:”一同显示,标记bi=1,让“:”在
 date函数里去显示,之所以不在定时器0里显示“:”是因为显示完“:”后
 再用date函数显示秒数会有时间差,视觉上就是先显示“:”过一会儿秒数
 再变化,直接去data函数里面显示尽量缩短时间差,让视觉感觉“:”和秒
 数是同时变化的
 */
 | 
 评分
查看全部评分
 |