|
仅使用内部定时器,走时精度已经可观。
难度在于使用键盘调节万年历。
下载:
1602 定时器 点扫描做时钟.rar
(2.62 KB, 下载次数: 20)
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- uchar shi,fen,miao,ri,yue,nian,rimax,keyn,xq,flag;
- uint tt;
- uchar code table[]="2011-11-11 FRI";
- uchar code table1[]="23:59:51";
- uchar code tablex[]="MON TUE WED THU FRI SAT SUN ";
- sbit dula=P2^6;
- sbit wela=P2^7;
- sbit lcden=P3^4;
- sbit rs=P3^5;
- sbit key=P3^0;
- sbit keyg=P3^1;
- sbit keyd=P3^2; //原计划写调减,不想写了。
- sbit gnd=P3^7;
- void init();
- void write_com(uchar com);
- void write_date(uchar date);
- void write_sfm(uchar wei,uchar date);
- void write_nyr(uchar wei,uchar date);
- void write_xq();
- void delay(uchar z);
- void yueday();
- void shunbianday();
- void keyscan();
- void clockrun();
- void main()
- {
- init();
- while(1)
- {
- keyscan();
- clockrun();
- }
- }
- void init()
- {
- uchar a,b;
- dula=0;
- wela=0;
- lcden=0;
- shi=23;
- fen=59;
- miao=58;
- nian=16;
- yue=2;
- ri=29;
- keyn=0;
- write_com(0x38);
- write_com(0x0c);
- write_com(0x06);
- write_com(0x01);
- write_com(0x80+1);
- for(a=0;a<14;a++)
- {
- write_date(table[a]);
- }
- write_com(0x80+0x40+4);
- for(b=0;b<8;b++)
- {
- write_date(table1[b]);
- }
- write_nyr(2,nian);
- write_nyr(5,yue);
- write_nyr(8,ri);
- write_sfm(0,shi);
- write_sfm(3,fen);
- write_sfm(6,miao);
- write_xq();
- yueday();
- TMOD=0x02; //设定定时/计数器工作方式2,自动重装初值
- TH0=0; //高八位+1计数器,工作方式1中,(65536-46080)/256=高八位,高八位总共可以装256,减76后可装180,即:当低八位为零时,高八位加一计数器+1次数180次时刚好50ms
- TL0=0; //低八位+1计数器,工作方式2中,第八位用于+1计数完成计时,高八位用于保留初值给第八位重写初值
- EA=1; //现在因不需占用机器周期重装初值,若还有误差,则只能是晶振的误差
- ET0=1;
- TR0=1;
- }
- void timer0() interrupt 1
- {
- tt++; //由于第八位加计数器只能计256,
- }
- void write_sfm(uchar wei,uchar date)
- {
- uchar ge,shi;
- shi=date/10;
- ge=date%10;
- write_com(0x80+0x40+4+wei);
- write_date(0x30+shi);
- write_date(0x30+ge);
- }
- void write_nyr(uchar wei,uchar date)
- {
- uchar ge,shi;
- shi=date/10;
- ge=date%10;
- write_com(0x80+1+wei);
- write_date(0x30+shi);
- write_date(0x30+ge);
- }
- void write_xq() //写星期数
- {
- uchar q;
- write_com(0x80+12);
- for(q=0;q<4;q++)
- {
- write_date(tablex[xq]);
- xq++;
- if(xq==28)
- xq=0;
- }
- }
- void yueday() //程序写长了,改子函数名有困难,以后注意。
- { //该子函数表示月+1后计算引用的天数
- if(yue==1)
- rimax=32;
- if(yue==2)
- {
- if(nian%4==0)
- rimax=30;
- else
- rimax=29;
- }
- if(yue==3)
- rimax=32;
- if(yue==4)
- rimax=31;
- if(yue==5)
- rimax=32;
- if(yue==6)
- rimax=31;
- if(yue==7)
- rimax=32;
- if(yue==8)
- rimax=32;
- if(yue==9)
- rimax=31;
- if(yue==10)
- rimax=32;
- if(yue==11)
- rimax=31;
- if(yue==12)
- rimax=32;
- }
- void shunbianday() //该子函数表示月+0后计算引用的天数
- {
- if(yue==2) //实际调用1月份天数最大31
- rimax=31;
- if(yue==3) //实际调用2月份天数最大28/29
- {
- if(nian%4==0)
- rimax=29;
- else
- rimax=28;
- }
- if(yue==4)
- rimax=31; //实际调用3月份天数最大31
- if(yue==5)
- rimax=30; //实际调用4月份天数最大30
- if(yue==6)
- rimax=31; //实际调用5月份天数最大31
- if(yue==7)
- rimax=30; //实际调用6月份天数最大30
- if(yue==8)
- rimax=31; //实际调用7月份天数最大31
- if(yue==9)
- rimax=31; //实际调用8月份天数最大31
- if(yue==10)
- rimax=30; //实际调用9月份天数最大30
- if(yue==11)
- rimax=31; //实际调用10月份天数最大31
- if(yue==12)
- rimax=30; //实际调用11月份天数最大30
- }
- void delay(uchar z)
- {
- uchar i,j;
- for(i=z;i>0;i--)
- for(j=115;j>0;j--);
- }
- void write_com(uchar com)
- {
- rs=0;
- P0=com;
- delay(4);
- lcden=1;
- delay(4);
- lcden=0;
- }
- void write_date(uchar date)
- {
- rs=1;
- P0=date;
- delay(4);
- lcden=1;
- delay(4);
- lcden=0;
- }
- void keyscan()
- {
- uchar temp,p;
- gnd=0;
- if(key==0)
- {
- delay(5);
- if(key==0)
- {
- TR0=0;
- keyn++;
- if(keyn==7)
- keyn=0;
- write_com(0x0f);
- if(keyn==0)
- {
- TR0=1;
- write_com(0x0c);
- }
- if(keyn==1)
- write_com(0x80+0x40+11);
- if(keyn==2)
- write_com(0x80+0x40+8);
- if(keyn==3)
- write_com(0x80+0x40+5);
- if(keyn==4)
- write_com(0x80+10);
- if(keyn==5)
- write_com(0x80+7);
- if(keyn==6)
- write_com(0x80+4);
- while(!key);
- }
- }
- if(keyn==1)
- {
- if(keyg==0)
- {
- delay(5);
- if(keyg==0)
- {
- miao++;
- if(miao==60)
- miao=0;
- write_sfm(6,miao);
- write_com(0x80+0x40+11);
- while(!keyg);
- }
- }
- }
- if(keyn==2)
- {
- if(keyg==0)
- {
- delay(5);
- if(keyg==0)
- {
- fen++;
- if(fen==60)
- fen=0;
- write_sfm(3,fen);
- write_com(0x80+0x40+8);
- while(!keyg);
- }
- }
- }
- if(keyn==3)
- {
- if(keyg==0)
- {
- delay(5);
- if(keyg==0)
- {
- shi++;
- if(shi==24)
- shi=0;
- write_sfm(0,shi);
- write_com(0x80+0x40+5);
- while(!keyg);
- }
- }
- }
- if(keyn==4)
- {
- if(keyg==0)
- {
- delay(5);
- if(keyg==0)
- {
- yueday();
- ri++;
- if(ri>=rimax)
- {
- ri=1;
- temp=(rimax-2)%7;
- for(p=6-temp;p>0;p--)
- {
- write_xq(); //因为跳出循环后,下面还会再重复一次,所以这里只循环5次
- }
- }
- write_xq();
- write_nyr(8,ri);
- write_com(0x80+10);
- while(!keyg);
- }
- }
- }
- if(keyn==5)
- {
- if(keyg==0)
- {
- delay(5);
- if(keyg==0)
- {
- yue++;
- if(yue==13)
- {
- yue=1; //情况二,跨月数调月(12变1)后,间隔天数
- if(nian%4==0) //情况二分支1,闰年
- { //因为12月、1月均为月大,日编号不会变
- for(p=(366-33)%7;p>0;p--)
- write_xq();
- }
- else //情况二分支2,平年
- {
- for(p=(365-31)%7;p>0;p--)
- write_xq();
- }
- }
- write_nyr(5,yue);
- //标记点
- yueday(); //情况一,顺序调月后(1→12),间隔天数。本句判断本月有多少天供后续利用
- if(ri>rimax-1) //情况一分支1。当当前显示的天数小于本月最大天数时,显示本月最大天数
- {
- write_nyr(8,rimax-1); //上个注释的执行部分,将示数改到最大值范围
- temp=ri-rimax; //情况一分支1,判断当月数加一后,天数增加数量
- ri=rimax-1; //上个注释的执行部分,不能光改示数,而不改实际运行值。
- shunbianday(); //更换rimax值
- for(p=(rimax+temp-1)%7;p>0;p--)
- write_xq();
- }
- else //情况一分支2,判断当月数加一后,天数增加数量
- { //当初值大于29时,1月变2月,是顺变,同时显示值大于最大允许值
- shunbianday();
- for(p=rimax%7;p>0;p--)
- write_xq();
- }
- write_com(0x80+7);
- while(!keyg);
- }
- }
- }
- if(keyn==6)
- {
- if(keyg==0)
- {
- delay(5);
- if(keyg==0)
- {
- if(nian%4==0&&yue==2&&ri==29) //分支3,当年+0为闰年2月29日时,年+1后2月只有28号。
- {
- ri=28; //改日的值
- write_nyr(8,ri); //改日显示
- for(p=7;p>0;p--) //改星期显示
- write_xq(); //循环七次,相当于没改
- flag=1; //分支4,当闰年2月29调过年数,调年再经过闰年未能识别闰年
- }
- nian++;
- if(nian>99) //分支1,嘿嘿,百年虫
- {
- nian=0;
- write_xq();
- }
- if(nian%4==0) //分支2.1,年+1为闰年
- {
- if(flag==1)
- {
- for(p=(365-28)%7;p>0;p--)
- write_xq();
- flag=2;
- }
- else
- {
- for(p=(366-35)%7;p>0;p--)
- write_xq();
- }
- }
- else //分支2.2,年+1为平年
- {
- if(flag==2)
- {
- for(p=2;p>0;p--)
- write_xq();
- flag=1;
- }
- else
- {
- for(p=(365-28)%7;p>0;p--)
- write_xq();
- }
- }
- write_nyr(2,nian);
- write_com(0x80+4);
- while(!keyg);
- }
- }
- }
- }
- void clockrun()
- {
- if(tt==3600)
- {
- tt=0;
- miao++;
- if(miao>=60)
- {
- miao=0;
- fen++;
- if(fen>=60)
- {
- fen=0;
- shi++;
- if(shi>=24)
- {
- shi=0;
- ri++;
- write_xq();
- yueday();
- if(ri>=rimax)
- {
- ri=1;
- yue++;
- if(yue>=13)
- {
- yue=1;
- nian++;
- if(nian>=100)
- nian=0;
- write_nyr(2,nian);
- }
- write_nyr(5,yue);
- }
- write_nyr(8,ri);
- }
- write_sfm(0,shi);
- }
- write_sfm(3,fen);
- }
- write_sfm(6,miao);
- }
- }
复制代码
|
|