#include <reg52.h>
#include <string.h>
#include <intrins.h>
#define uchar unsigned char define uint unsigned int sbit SDA=P1^0; // DS1302数据线
sbit CLK=P1^1; //DS1302时钟线
sbit RST=P1^2; //DS1302复位线
sbit RS=P2^0;
sbit RW=P2^1;
sbit EN=P2^2;
sbit K1=P3^4; // 选择
sbit K2=P3^5; // 加
sbit K3=P3^6; // 减
sbit K4=P3^7; // 确定
void Display_LCD_String();
uchar tCount=0;//一年中每个月的天数,2月的天数由年份决定 uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};
uchar *WEEK[]={"SUN","MON","TUS","WEN","THU","FRI","SAT"};//周日,周一到周六
uchar LCD_DSY_BUFFER1[]={"Date 00-00-00 "}; //LCD显示缓冲 uchar LCD_DSY_BUFFER2[]={"Time 00-00-00 "};
uchar DateTime[7]; //所读取的日期时间
char Adjust_Index=-1; //当前调节的时间:秒,分,时,日, uchar Change_Flag[]="-MHDM-Y";
uchar Read_LCD_State();
void LCD_Busy_Wait();
void Write_LCD_Data(uchar dat);
void Write_LCD_Command(uchar cmd);
void Init_LCD();
void Set_LCD_POS(uchar p);
void DelayMS(uint x)
{
uchar i;
while(x--) for(i=0;i<120;i++);
}
uchar Read_LCD_State()
{
uchar state;
RS=0;
RW=1;
EN=1;
DelayMS(1);
state=P0;
EN=0;
DelayMS(1);
return state;
}
void LCD_Busy_Wait()
{
while((Read_LCD_State()&0x08)==0x80);
DelayMS(5);
}
void Write_LCD_Data(uchar dat) //写数据
{
LCD_Busy_Wait();
RS=1;
RW=0;
EN=0;
P0=dat;
EN=1;
DelayMS(1);
EN=0;
}
void Write_LCD_Command(uchar cmd)//写命令
{
LCD_Busy_Wait();
RS=0;
RW=0;
EN=0;
P0=cmd;
EN=1;
DelayMS(1);
EN=0;
}
void Init_LCD() //LCD初始化
{
Write_LCD_Command(0x38); DelayMS(1);
Write_LCD_Command(0x01); DelayMS(1);
Write_LCD_Command(0x06); DelayMS(1);
Write_LCD_Command(0x0C); DelayMS(1);
Display_LCD_String(0x00,"zhongzhoudaxue");
//DelayMS(1000);
Display_LCD_String(0x40,"dian zi ri li");
DelayMS(2000);
}
void Set_LCD_POS(uchar p)
{
Write_LCD_Command(p|0x80);
}
void Display_LCD_String(uchar p,uchar *s)
{
uchar i;
Set_LCD_POS(p);
for(i=0;i<16;i++)
{
Write_LCD_Data(s[i]);
DelayMS(1);
}
}
/*--------------------------
向DS1302写入一字节
---------------------------*/
void DS1302_Write_Byte(uchar x)
{
uchar i;
for(i=0;i<8;i++)
{
SDA=x&1;
CLK=1;
CLK=0;
x>>=1;
}
}
/*-------------------------------
从DS1302读取一字节
--------------------------------*/
uchar DS1302_Read_Byte()
{
uchar i,b,t;
for(i=0;i<8;i++)
{
b>>=1;
t=SDA;
b|=t<<7;
CLK=1;
CLK=0;
}
return b/16*10+b%16;
}
/*-------------------------------
从DS1302指定位置数据
--------------------------------*/
uchar Read_Data(uchar addr)
{
uchar dat;
RST=0;
CLK=0;
RST=1;
DS1302_Write_Byte(addr);
dat=DS1302_Read_Byte();
CLK=1;
RST=0;
return dat;
}
/*-------------------------------
向DS1302某地址写入数据
--------------------------------*/
void Write_DS1302(uchar addr,uchar dat)
{
CLK=0;
RST=1;
DS1302_Write_Byte(addr);
DS1302_Write_Byte(dat);
CLK=0;
RST=0;
}
/*------------------------------------
设置时间
------------------------------------*/
void SET_DS1302()
{
uchar i;
Write_DS1302(0x8e,0x00);
for(i=0;i<7;i++)
{
Write_DS1302(0x80+2*i,(DateTime[i]/10<<4|(DateTime[i]%10)));
}
Write_DS1302(0x8e,0x80);
}
/*------------------------------------
读取当前时期时间
------------------------------------*/
void GetTime()
{
uchar i;
for(i=0;i<7;i++)
{
DateTime[i]=Read_Data(0x81+2*i);
}
}
/*------------------------------------
时间和日期转换成数字字符
------------------------------------*/
void Format_DateTime(uchar d,uchar *a)
{
a[0]=d/10+'0';a[1]=d%10+'0';
}
/*------------------------------------
判断是否为闰年
------------------------------------*/
uchar isLeapYear(uint y)
{
return (y%4==0&&y%100!=0)||(y%400==0);
}
/*------------------------------------
星期转换
------------------------------------*/
void RefreshWeekDay()
{
uint i,d,w=5;
for(i=2000;i<2000+DateTime[6];i++)
{
d=isLeapYear(i) ? 366 : 365;
w=(w+d)%7;
}
d=0;
for(i=1;i<DateTime[4];i++) d+=MonthsDays[i];
d+=DateTime[3];
DateTime[5]=(w+d)%7+1;
}
/*------------------------------------
年月日时分秒++/--
------------------------------------*/
void DateTime_Adjust(char x)
{
switch (Adjust_Index)
{
case 6: //年
if(x== 1&&DateTime[6]<99) DateTime[6]++;
if(x==-1&&DateTime[6]>0) DateTime[6]--;
MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29:28;
if(DateTime[3]>MonthsDays[DateTime[4]])
DateTime[3]=MonthsDays[DateTime[4]];
RefreshWeekDay();
break;
case 4: //月
if(x== 1&&DateTime[4]<12) DateTime[4]++;
if(x==-1&&DateTime[4]>1) DateTime[4]--;
MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29:28;
if(DateTime[3]>MonthsDays[DateTime[4]])
DateTime[3]=MonthsDays[DateTime[4]];
RefreshWeekDay();
break;
case 3: //日
MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29:28;
if(x== 1&&DateTime[3]<MonthsDays[DateTime[4]]) DateTime[3]++;
if(x==-1&&DateTime[3]>0) DateTime[3]--;
RefreshWeekDay();
break;
case 2: //时
if(x== 1&&DateTime[2]<23) DateTime[2]++;
if(x==-1&&DateTime[2]>0) DateTime[2]--;
break;
case 1: //秒
if(x== 1&&DateTime[1]<59) DateTime[1]++;
if(x==-1&&DateTime[1]>0) DateTime[1]--;
break;
}
}
/*------------------------------------
定时器每秒刷新LCD显示
------------------------------------*/
void T0_INT() interrupt 1
{
TH0=-50000/256;
TL0=-50000%256;
if(++tCount!=2) return;
tCount=0;
Format_DateTime(DateTime[6],LCD_DSY_BUFFER1+5);
Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+8);
Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+11);
strcpy(LCD_DSY_BUFFER1+13,WEEK[DateTime[5]-1]);
Format_DateTime(DateTime[2],LCD_DSY_BUFFER2+5);
Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+8);
Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+11);
Display_LCD_String(0x00,LCD_DSY_BUFFER1);
Display_LCD_String(0x40,LCD_DSY_BUFFER2);
}
/*------------------------------------
键盘中断
------------------------------------*/
void EX_INT0() interrupt 0
{
if(K1==0) //选择调整对象:年,月,日,时,分,秒
{
while(K1==0);
if(Adjust_Index==-1||Adjust_Index==1) Adjust_Index=7;
Adjust_Index--;
if(Adjust_Index==5) Adjust_Index=4;
LCD_DSY_BUFFER2[13]='[';
LCD_DSY_BUFFER2[14]=Change_Flag[Adjust_Index];
LCD_DSY_BUFFER2[15]=']';
}
else
if(K2==0) // 加
{
while (K2==0); DateTime_Adjust(1);
}
else
if(K3==0) // 减
{
while (K3==0); DateTime_Adjust(-1);
}
else
if(K4==0) // 确定
{
while(K4==0);
SET_DS1302(); //调整后的时间写入DS1302
LCD_DSY_BUFFER2[13]=' ';
LCD_DSY_BUFFER2[14]=' ';
LCD_DSY_BUFFER2[15]=' ';
Adjust_Index=-1;
}
}
/*------------------------------------
主程序
------------------------------------*/
void main()
{
Init_LCD(); //LCD初始化
IE=0x83; // 允许INT0,T0中断
IP=0x01;
IT0=0x01;
TMOD=0x01;
TH0=-50000/256;
TL0=-50000%256;
TR0=1;
while(1)
{
if(Adjust_Index==-1) GetTime();
}
}
|