- UID
- 274637
- 阅读权限
- 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函数里面显示尽量缩短时间差,让视觉感觉“:”和秒
数是同时变化的
*/ |
评分
-
查看全部评分
|