下面是主程序:
/**************************************
名稱: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;
}
}
|