本帖最后由 月影狼迹 于 2013-6-9 14:15 编辑
初学者。用16F877A写的,能显示2001~2099年任意时间、日期和星期。用Protues
仿真时,时间走的比电脑时钟慢。求大神分析一下!
#include <pic.h>
__CONFIG(0x3F39);
#define RS RC0
#define RW RC1
#define E RC2
#define T1_50MS 15536
#define key1 RB0
#define key2 RB1
#define key3 RB2
#define key4 RB3
const char table0[]={'0','1','2','3','4','5','6','7','8','9',' '}; //显示查表表格
const char table1[]={'/',':',' '};
const char table2[]={'S','U','N','M','O','N','T','U','E','W','E','D','T','H','U','F','R','I','S','A','T'};
char num=0,num0=0,num1=0; //定时器计数变量
int sec=0,min=0,hour=0,Years=2000; //时分秒计数变量
char day=1,weekday=0,mon=1,year=1; //年月日计数变量
char num5=0,num6=0,num7=0; //按键延时计数变量
char count1,count2=0,count3=0,count4=0; //按键状态变量
char count5=0,count6=0,count7=0;
char hh=0,hl=0,mh=0,ml=0,sh=0,sl=0,dd; //时分秒年月日高低位分解寄存
char nh=0,nl=1,yh=0,yl=1,rh=0,rl=1;
char tmp,tmp_days; //星期几计算中间变量
/******************************************************************/
/* 函数声明 */
/******************************************************************/
void delayms(unsigned int ms) //ms延时子程序
{
unsigned int x,y;
for (x=ms;x>0;x--)
for (y=110;y>0;y--);
}
/******************************************************************/
void delayus(char us) //us延时子程序
{
char x;
x=us;
while(x>0)
{
x--;
NOP();NOP();NOP();NOP();
}
}
/****************************************************************/
void write_com(char com) //LCD写命令子程序
{
RS=0;NOP();
RW=0;NOP();
PORTD=com;
delayms(1);
E=1;
delayms(1);
E=0;
}
/****************************************************************/
void write_data(char d) //LCD写数据子程序
{
RS=1;NOP();
RW=0;NOP();
PORTD=d;
delayms(1);
E=1;
delayms(1);
E=0;NOP();
RS=0;
}
/*********************************************************************/
void init() //初始化子程序
{
TRISB=0b11111111;
TRISC=0b00000000;
TRISD=0b00000000;
TMR0=(65536-50000)/256;
OP
tiON=0b10000111;
INTCON=0b10100000;
RS=1;NOP();
RW=0;NOP();
E=0;
delayms(20);
write_com(0b00110000);
delayms(1);
write_com(0b00110000);
delayus(10);
write_com(0b00110000);
delayus(10);
write_com(0b00110000);
write_com(0b00111000);
write_com(0b00001100);
write_com(0b00000001);
delayms(2);
write_com(0b00000110);
}
/*********************************************************************/
void display() //扫描显示子程序
{
write_com(0x80+0x00);
delayus(10);
write_data(table0[2]);
delayus(10);
write_data(table0[0]);
delayus(10);
write_data(table0[nh]);
delayus(10);
write_data(table0[nl]);
delayus(10);
write_data(table1[0]);
delayus(10);
write_data(table0[yh]);
delayus(10);
write_data(table0[yl]);
delayus(10);
write_data(table1[0]);
delayus(10);
write_data(table0[rh]);
delayus(10);
write_data(table0[rl]);
delayus(10);
write_com(0x80+0x0c);
delayus(10);
for(num=(3*weekday);num<(3*weekday+3);num++)
write_data(table2[num]);
write_com(0x80+0x40);
delayus(10);
write_data(table0[hh]);
delayus(10);
write_data(table0[hl]);
delayus(10);
write_data(table1[1]);
delayus(10);
write_data(table0[mh]);
delayus(10);
write_data(table0[ml]);
delayus(10);
write_data(table1[dd]);
delayus(10);
write_data(table0[sh]);
delayus(10);
write_data(table0[sl]);
delayus(10);
}
/*********************************************************************/
void keyscan()
{
if(key1==0) //key1为选择按键
{
num0++;
if(num0>5) //50ms延时确认
num0=6;
if(num0==2)
{
count1++; //count1==1,选择调整时针 ount1==4,选择调整当前年
if(count1==7) //count1==2,选择调整分针 ount1==5,选择调整当前月
count1=0; //count1==3,选择调整秒针 ount1==6,选择调整当前日
}
}
else
num0=0;
if(key2==0) //key2为时分秒年月日加1按键
{
num5++;
if(num5>5)
num5=6;
if(num5==2)
{
if(count1==1)
{
hour++;
if(hour==24)
hour=0;
}
if(count1==2)
{
min++;
if(min==60)
min=0;
}
if(count1==3)
{
sec++;
if(sec==60)
sec=0;
}
if(count1==4)
{
year++;
if(year==100)
year=1;
}
if(count1==5)
{
mon++;
if(mon==13)
mon=1;
}
if(count1==6)
{
Years=year+2000;
switch (mon)
{
case 2:
{
day++;
if(Years%4==0)
{
if(day==30)
day=1;
}
else
{
if(day==29)
day=1;
}
}
break;
case 1: case 3: case 5: case 7:
case 8: case 10: case 12:
{
day++;
if(day==32)
day=1;
}
break;
case 4: case 6: case 9: case 11:
{
day++;
if(day==31)
day=1;
}
break;
}
}
}
}
else
num5=0;
if(key3==0) //key3为时分秒年月日减1按键
{
num6++;
if(num6>5)
num6=6;
if(num6==2)
{
if(count1==1)
{
hour--;
if(hour== -1)
hour=23;
}
if(count1==2)
{
min--;
if(min== -1)
min=59;
}
if(count1==3)
{
sec--;
if(sec== -1)
sec=59;
}
if(count1==4)
{
year--;
if(year==0)
year=99;
}
if(count1==5)
{
mon--;
if(mon==0)
mon=12;
}
if(count1==6)
{
Years=year+2000;
switch (mon)
{
case 2:
{
day--;
if(Years%4==0)
{
if(day==0)
day=29;
}
else
{
if(day==0)
day=28;
}
}
break;
case 1: case 3: case 5: case 7:
case 8: case 10: case 12:
{
day--;
if(day==0)
day=31;
}
break;
case 4: case 6: case 9: case 11:
{
day--;
if(day==0)
day=30;
}
break;
}
}
}
}
else
num6=0;
if(key4==0) //key4为确认按键
{
num7++;
if(num7>5)
num7=6;
if(num7==2)
count1=0;
}
else
num7=0;
}
/*********************************************************************/
void timer()
{
if(num1<10)
dd=1;
else
dd=2;
if(num1>=20) //中断20次,时间计满1s
{
num1=0;
sec++; //秒针加1
if(sec>=60) //计满60秒,秒针归零
{
sec=0;
min++;
} //分针加1
sh=sec/10; //秒针高低位分解
sl=sec%10;
if(min>=60) //计满60分,分针归零
{
min=0;
hour++;
} //时针加1
mh=min/10; //分针高低位分解
ml=min%10;
if(hour>=24) //计满24小时,时针归零
{
hour=0;
day++;
} //日期加1
hh=hour/10; //时针高低位分解
hl=hour%10;
switch(mon)
{
case 1: case 3: case 5: case 7:
case 8: case 10: case 12:
{
if(day>31)
{ //月大日期计满31天,日期归1
day=1;
mon++;
} //月份加1
rh=day/10; //日期高低位分解
rl=day%10;
}
break;
case 4: case 6: case 9: case 11: //月小日期计满30天,日期归1
{
if(day>30)
{
day=1;
mon++;
} //月份加1
rh=day/10; //日期高低位分解
rl=day%10;
}
break;
case 2:
{
Years=year+2000;
if(Years%4==0)
{
if(day>29) //润年二月日期计满29天,日期归1
{
day=1;
mon++;
} //月份加1
rh=day/10; //日期高低位分解
rl=day%10;
}
else
{
if(day>28) //平年二月日期计满29天,日期归1
{
day=1;
mon++;
} //月份加1
rh=day/10; //日期高低位分解
rl=day%10;
}
}
break;
}
if(mon>12)
{ //月份计满12,月份归1
mon=1;
year++;
} //年份加1
yh=mon/10; //月份高低位分解
yl=mon%10;
if(year>99) //年份计满99,年份归1
year=1;
nh=year/10; //年份高低位分解
nl=year%10;
}
}
/*********************************************************************/
void time_change()
{
if(count1==1) //等于1表示有调整时针请求
{
dd=1;
if(count2>=20) //时针500ms闪烁
count2=0;
if(count2<10)
{
hh=10;
hl=10;
}
else
{
hh=hour/10;
hl=hour%10;
}
}
if(count1==2) //等于2表示有调整分针请求
{
hh=hour/10; //时秒针年月日正常显示
hl=hour%10;
dd=1;
if(count3>=20)
count3=0;
if(count3<10) //分针500ms闪烁
{
mh=10;
ml=10;
}
else
{
mh=min/10;
ml=min%10;
}
}
if(count1==3) //等于3表示有调整秒针请求
{
mh=min/10;
ml=min%10;
dd=1;
if(count4>=20)
count4=0;
if(count4<10) //秒针500ms闪烁
{
sh=10;
sl=10;
}
else
{
sh=sec/10;
sl=sec%10;
}
}
if(count1==4) //等于4表示有调整年份请求
{
sh=sec/10;
sl=sec%10;
dd=1;
if(count5>=20)
count5=0;
if(count5<10) //年份500ms闪烁
{
nh=10;
nl=10;
}
else
{
nh=year/10;
nl=year%10;
}
}
if(count1==5) //等于5表示有调整月份请求
{
nh=year/10;
nl=year%10;
dd=1;
if(count6>=20)
count6=0;
if(count6<10) //月份500ms闪烁
{
yh=10;
yl=10;
}
else
{
yh=mon/10;
yl=mon%10;
}
}
if(count1==6) //等于6表示有调整日期请求
{
yh=mon/10;
yl=mon%10;
dd=1;
if(count7>=20)
count7=0;
if(count7<10) //日期500ms闪烁
{
rh=10;
rl=10;
}
else
{
rh=day/10;
rl=day%10;
}
}
}
/*********************************************************************/
void weekdays(char day,char mon,char year)
{
Years=year+2000;
tmp=(Years-1)/4+1; //计算当前年1月1日为星期几?
tmp=(Years-tmp)+tmp*2;
weekday=(tmp+5)%7;
tmp_days=0;
for(tmp=1;tmp<mon;tmp++)
{
if(tmp==1 || tmp==3 || tmp==5 || tmp==7 || tmp==8 || tmp==10)
tmp_days=tmp_days+31;
else if(tmp==4 || tmp==6 || tmp==9 || tmp==11)
tmp_days=tmp_days+30;
else if(tmp==2)
{ if(Years%4==0)
tmp_days=tmp_days+29;
else
tmp_days=tmp_days+28;
}
}
tmp_days=tmp_days+day-1;
weekday=(weekday+tmp_days%7)%7+1; //计算当前日期为星期几?
if(weekday==7)
weekday=0;
}
/*********************************************************************/
void main(void) //主程序
{
init();
while(1)
{
display();
timer();
time_change();
keyscan();
weekdays(day,mon,year);
}
}
/*********************************************************************/
/*********************************************************************/
void interrupt T0(void)
{
if(T0IF==1)
{
T0IF=0;
TMR0=(65536-50000)/256;
if(count1==0) //等于0表示没有时间调整按键请求,正常走时
num1++;
if(count1==1) //等于1表示有调整时针请求
count2++;
if(count1==2) //等于2表示有调整分针请求
count3++;
if(count1==3) //等于3表示有调整秒针请求
count4++;
if(count1==4) //等于4表示有调整年份请求
count5++;
if(count1==5) //等于5表示有调整月份请求
count6++;
if(count1==6) //等于6表示有调整日期请求
count7++;
}
}
-
-
EXAMPLE1.rar
下载积分: 积分 -1 分
106.88 KB, 下载次数: 2, 下载积分: 积分 -1 分
我有经过计算的,预分频比1:256,TMR0=(256*256-50000)/256。50ms计一次,计20次为1s。
请指出哪里计算错误,谢谢!
一周热门 更多>