下面是主程序:
/**************************************
名称:89c52+at24c02+键盘时钟程序
工具:protues仿真软件
作者:kwx618
时间:2011-09-10
**************************************/
#include <reg52.h>
#include <intrins.h>
#include"at24c02.h"
#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS=P0^0;
sbit LCD_RW=P0^1;
sbit LCD_EN=P0^2;
sbit S1=P1^2;
sbit S2=P1^3;
sbit S3=P1^4;
sbit S4=P1^5;
char year,mounth,day,hour,minute,second;
uchar num,count;
bit write=0; //写2402标志
uchar code nyr_table[]=" 20 - - ";
uchar code sfm_table[]=" : : ";
/************延时1ms函数***************/
void delay1ms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=112;y>0;y--);
}
/**************LCD1602程序***********/
void LCD_BUSY()
{
P2=0x00;
LCD_RS=0;
LCD_RW=1;
LCD_EN=1;
while(P2&0x80);
LCD_EN=0;
}
void writeLCD_command(uchar cmd)
{
LCD_BUSY();
LCD_RS=0;
LCD_RW=0;
P2=cmd;
_nop_();
LCD_EN=1;
_nop_();
LCD_EN=0;
}
void writeLCD_data(uchar date)
{
LCD_BUSY();
LCD_RS=1;
LCD_RW=0;
P2=date;
_nop_();
LCD_EN=1;
_nop_();
LCD_EN=0;
}
void write_nyrsfm(char add,char date)
{
char shiwei,gewei;
shiwei=date/10;
gewei=date%10;
writeLCD_command(0x80|add);
delay1ms(1);
writeLCD_data(0x30+shiwei);
delay1ms(1);
writeLCD_data(0x30+gewei);
delay1ms(1);
}
void LCD_init()
{
uchar num1,num2;
year=0;mounth=1;day=1;
hour=23;minute=59;second=59;
LCD_BUSY();
writeLCD_command(0x38);//设置16*2显示,5*7点阵,8位数据接口
delay1ms(5); //此处必须加延时,否则LCD不显示
writeLCD_command(0x0c);//开显示,光标不显示
delay1ms(5); //此处必须加延时,否则光标不会移动
writeLCD_command(0x06);//读或写字符后,光标自动加1,整屏不移动
delay1ms(5);
writeLCD_command(0x02);//数据指针清0
delay1ms(5);
writeLCD_command(0x80|0x02);
for(num1=0;num1<11;num1++)
{
writeLCD_data(nyr_table[num1]);
}
writeLCD_command(0x80|0x43);
for(num2=0;num2<9;num2++)
{
writeLCD_data(sfm_table[num2]);
}
write_nyrsfm(0x80|0x05,year);
_nop_();
write_nyrsfm(0x80|0x08,mounth);
_nop_();
write_nyrsfm(0x80|0x0b,day);
_nop_();
write_nyrsfm(0x80|0x44,hour);
_nop_();
write_nyrsfm(0x80|0x47,minute);
_nop_();
write_nyrsfm(0x80|0x4a,second);
_nop_();
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
/**************************************************
名称:按键程序
S1: 设置键
S2:时间加
S3:时间减
**************************************************/
void keyscan()
{
if(S1==0)
{
delay1ms(10);
if(S1==0)
num++;
while(!S1);
switch(num)
{
case 1: TR0=0;
writeLCD_command(0x80|0x4b);
delay1ms(1);
writeLCD_command(0x0f);
delay1ms(1);
break;
case 2: TR0=0;
writeLCD_command(0x80|0x48);
writeLCD_command(0x0f);
break;
case 3: TR0=0;
writeLCD_command(0x80|0x45);
writeLCD_command(0x0f);
break;
case 4: TR0=0;
writeLCD_command(0x80|0x0c);
writeLCD_command(0x0f);
break;
case 5: TR0=0;
writeLCD_command(0x80|0x09);
writeLCD_command(0x0f);
break;
case 6: TR0=0;
writeLCD_command(0x80|0x06);
writeLCD_command(0x0f);
break;
case 7: num=0;
writeLCD_command(0x0c);
TR0=1;
break;
default:break;
}
}
}
void up_downsetkey()
{
//keyscan();
if(num!=0)
{
if(S2==0)
{
delay1ms(10);
if(S2==0)
while(!S2);
switch(num)
{
case 1: second++;
if(second==60)
second=0;
write_nyrsfm(0x80|0x4a,second);
delay1ms(5);
write2402_data(1,second);
delay1ms(5);
break;
case 2: minute++;
if(minute==60)
minute=0;
write_nyrsfm(0x80|0x47,minute);
delay1ms(5);
write2402_data(2,minute);
delay1ms(5);
break;
case 3: hour++;
if(hour==24)
hour=0;
write_nyrsfm(0x80|0x44,hour);
delay1ms(5);
write2402_data(3,hour);
delay1ms(5);
break;
case 4: day++;
if(day==30)
day=0;
write_nyrsfm(0x80|0x0b,day);
delay1ms(5);
write2402_data(4,day);
delay1ms(5);
break;
case 5: mounth++;
if(mounth==12)
mounth=0;
write_nyrsfm(0x80|0x08,mounth);
delay1ms(5);
write2402_data(5,mounth);
delay1ms(5);
break;
case 6: year++;
if(year==99)
year=0;
write_nyrsfm(0x80|0x05,year);
delay1ms(5);
write2402_data(6,year);
delay1ms(5);
break;
default:break;
}
}
if(S3==0)
{
delay1ms(10);
if(S3==0)
while(!S3);
switch(num)
{
case 1: second--;
if(second==-1)
second=59;
write_nyrsfm(0x80|0x4a,second);
delay1ms(1);
write2402_data(1,second);
break;
case 2: minute--;
if(minute==-1)
minute=59;
write_nyrsfm(0x80|0x47,minute);
write2402_data(2,minute);
break;
case 3: hour--;
if(hour==-1)
hour=23;
write_nyrsfm(0x80|0x44,hour);
write2402_data(3,hour);
break;
case 4: day--;
if(day==-1)
day=30;
write_nyrsfm(0x80|0x0b,day);
write2402_data(4,day);
break;
case 5: mounth--;
if(mounth==-1)
mounth=12;
write_nyrsfm(0x80|0x08,mounth);
write2402_data(5,mounth);
break;
case 6: year--;
if(year==-1)
year=99;
write_nyrsfm(0x80|0x05,year);
write2402_data(6,year);
break;
default:break;
}
}
}
}
/*void display() //开始的时候采用这种边显示边写2402的方式,但是程序写不到2402,
{ //很郁闷。不过调整时间时光标很正常,一直想找个方法让光标正常而且能写进
if(count==20) // 2402的方法,但是没有想出来
{
second++;
count=0;
if(second==60)
{
second=0;
minute++;
if(minute==60)
{
minute=0;
hour++;
if(hour==24)
{
hour=0;
day++;
if(day==31)
{
day=0;
mounth++;
if(mounth==13)
{
mounth=0;
year++;
write_nyrsfm(0x80|0x05,year);
delay1ms(1);
write2402_data(6,year);
delay1ms(1);
}
write_nyrsfm(0x80|0x08,mounth);
delay1ms(1);
write2402_data(5,mounth);
delay1ms(1);
}
write_nyrsfm(0x80|0x0b,day);
delay1ms(1);
write2402_data(4,day);
delay1ms(1);
}
write_nyrsfm(0x80|0x44,hour);
delay1ms(1);
write2402_data(3,hour);
delay1ms(1);
}
write_nyrsfm(0x80|0x47,minute);
delay1ms(1);
write2402_data(2,minute);
delay1ms(1);
}
write_nyrsfm(0x80|0x4a,second);
delay1ms(1);
write2402_data(1,second);
delay1ms(1);
}
} */
/************显示程序****************/
void display()
{
//year=0;mounth=1;day=0; // 开始的时候不写这两句,显示的结果就是2000-0/-0/ 23-0/-0/ ,
//hour=23;minute=59;second=59; // 解决办法是先在加上这两句,然后把初始化里的那两句屏蔽掉,然后编译显示,
write_nyrsfm(0x80|0x05,year); // 在回过头来去掉初始化里的屏蔽,把这两句删掉编译就显示正常了,具体为什么会
delay1ms(1); //这样,我也不清楚,有待解决。
write_nyrsfm(0x80|0x08,mounth);
delay1ms(1);
write_nyrsfm(0x80|0x0b,day);
delay1ms(1);
write_nyrsfm(0x80|0x44,hour);
delay1ms(1);
write_nyrsfm(0x80|0x47,minute);
delay1ms(1);
write_nyrsfm(0x80|0x4a,second);
delay1ms(1);
}
void main()
{
init_2402();
delay1ms(5);
LCD_init();
delay1ms(5); //此处也必须加延时,否则不会在指定的位置显示
second =read_data(0); //读出24c02保存的值赋于sec
if(second>60) //防止首次读出错误数据
second=0;
delay1ms(5);
minute=read_data(1); //读出24c02保存的值赋于sec
if(minute>60) //防止首次读出错误数据
minute=0;
delay1ms(5);
hour=read_data(2); //读出24c02保存的值赋于sec
if(hour>24) //防止首次读出错误数据
hour=0;
delay1ms(5);
day=read_data(3); //读出24c02保存的值赋于sec
if(day>30) //防止首次读出错误数据
day=0;
delay1ms(5);
mounth=read_data(4); //读出24c02保存的值赋于sec
if(mounth>12) //防止首次读出错误数据
mounth=0;
delay1ms(5);
year=read_data(5); //读出24c02保存的值赋于sec
if(year>12) //防止首次读出错误数据
year=0;
delay1ms(5);
while(1)
{
display();
delay1ms(1);
keyscan();
delay1ms(1);
up_downsetkey();
delay1ms(1);
if(write==1)
{
write2402_data(0,second);
delay1ms(1);
write2402_data(1,minute);
delay1ms(1);
write2402_data(2,hour);
delay1ms(1);
write2402_data(3,day);
delay1ms(1);
write2402_data(4,mounth);
delay1ms(1);
write2402_data(5,year);
delay1ms(1);
write=0; //清0
}
}
}
void intputtime0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==16)//此处应该是20,但是用protues仿真时会发现误差很大,所以我调到了16,时间刚好。
{
second++;
count=0;
if(second==60)
{
second=0;
minute++;
if(minute==60)
{
minute=0;
hour++;
if(hour==24)
{
hour=0;
day++;
if(day==31)
{
day=0;
mounth++;
if(mounth==13)
{
mounth=0;
year++;
}
}
}
}
}
write=1;
}
}
|