#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
typedef unsigned int u16;
typedef unsigned char u8;
sbit LCDEN=P2^7;
sbit LCDRS=P2^6;
sbit LCDRW=P2^5;
sbit DSIO=P3^4;
sbit RST=P3^5; //CE
sbit SCLK=P3^6;
sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;
uchar code WRITE_RTC_ADDR[3] = {0x80, 0x82, 0x84};//写入秒分时的地址命令
uchar code READ_RTC_ADDR[3] = {0x81, 0x83, 0x85};//读秒分时日月周年的地址命令
uchar TIME[7] = {0x54, 0x57, 0x23};//秒分时日月周年的各个数据
uchar SetState,SetPlace;
void delay(uint c) //误差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
void Write_Cmd(unsigned char C) //写命令
{
LCDEN=0;
LCDRS=0;
LCDRW=0;
P0=C;
delay(1);
LCDEN=1;
delay(5);
LCDEN=0;
}
void Write_Data(unsigned char D)//写数据
{
LCDEN=0;
LCDRS=1;
LCDRW=0;
P0=D;
delay(1);
LCDEN=1;
delay(5);
LCDEN=0;
}
void LCD_Init() //LCD初始化
{
LCDRS=0;
Write_Cmd(0x38); //开显示
Write_Cmd(0x0c); //开显示不显示光标
Write_Cmd(0x06); //写一个指针加1
//Write_Cmd(0x01); //清屏
Write_Cmd(0x80); //设置数据指针起点
}
void Ds1302Write(uchar addr,uchar dat) //向DS1302写地址,数据
{
uchar n;
RST=0;
_nop_();
SCLK=0;
_nop_();
RST=1;
_nop_();
for(n=0;n<8;n++) //开始传送八位地址命令
{
DSIO=addr&0x01; //数据从低位开始传送
addr>>=1;
SCLK=1; //数据在上升沿(SCLK)时,向DS1302写数据
_nop_();
SCLK=0;
_nop_();
}
for(n=0;n<8;n++) //写入8位数据
{
DSIO=dat&0x01; //数据从低位开始传送
dat>>=1;
SCLK=1; //数据在上升沿(SCLK)时,向DS1302写数据
_nop_();
SCLK=0;
_nop_();
}
}
uchar Ds1302Read(uchar addr) //DS1302读数据
{
uchar n,dat,dat1;
RST=0;
_nop_();
SCLK=0;
_nop_();
RST=1;
_nop_();
for(n=0;n<8;n++) //读一个字节(八位)的地址
{
DSIO=addr&0x01;
addr>>=1;
SCLK=1;
_nop_();
SCLK=0;
_nop_();
}
_nop_();
for(n=0;n<8;n++)
{
dat1=DSIO;
dat=(dat>>1)|(dat1<<7);
SCLK=1;
_nop_();
SCLK=0;
_nop_();
}
RST=0;
_nop_();
SCLK=1;
_nop_();
SCLK=0;
_nop_();
DSIO=0;
_nop_();
DSIO=1;
_nop_();
return dat;
}
void Ds1302Init() //DS1302初始化
{
uchar n;
Ds1302Write(0x8E,0x00);//禁止写保护,关闭写保护功能
for(n=0;n<3;n++) //写入3个字节的时钟信号:分秒时
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80);//打开写保护功能
}
void Ds1302Read()//读取时钟信息
{
uchar n;
for(n=0;n<3;n++)
{
TIME[n]=Ds1302Read(READ_RTC_ADDR[n]);
}
}
void shuzu()
{
Write_Cmd(0x80);
Write_Data('0'+TIME[2]/16); //时
Write_Data('0'+(TIME[2]&0x0f));
Write_Data('-');
Write_Data('0'+TIME[1]/16); //分
Write_Data('0'+(TIME[1]&0x0f));
Write_Data('-');
Write_Data('0'+TIME[0]/16); //秒
Write_Data('0'+(TIME[0]&0x0f));
}
void INT1Timer1() //外部中断T1的配置
{
IT1=1;
EX1=1;
EA=1;
}
void main()
{
u8 i=0;
Ds1302Init();
LCD_Init();
INT1Timer1();
while(1)
{
if(SetState==0)
{
Ds1302Read();
}
else
if(k1==0)
{
delay(100);
if(k1==0)
{
SetPlace++;
if(SetPlace>3)
{
SetPlace=0;
}
}
}
if(k2==0)
{
delay(200);
if(k2==0)
{
TIME[SetPlace]++;
if(TIME[SetPlace]>=0x60&&(SetPlace<2)) //秒和分不能加到超过60,超过60变为0
{
TIME[SetPlace]=0;
}
if(TIME[SetPlace]>=0x24&&(SetPlace=2)) //小时不能超过23,超过23变为0
{
TIME[SetPlace]=0;
}
}
if(k3==0)
{
delay(200);
if(k3==0)
{
TIME[SetPlace]--;
if(TIME[SetPlace]<0&&(SetPlace<2)) //秒和分不能减至负数,小于0则变为59
{
TIME[SetPlace]=0x59;
}
if(TIME[SetPlace]<0&&(SetPlace=2)) //小时不能减至负数,小于0则变为23
{
TIME[SetPlace]=0x23;
}
}
}
}
shuzu();
}
}
void Int1() interrupt 2 //中断服务程序
{
delay(10);
if(k4==0)
{
SetState=~SetState;
SetPlace=0;
Ds1302Init();
}
}
|