#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_dat P0
sbit LED=P2^0;
sbit led_1=P1^0;
sbit led_2=P1^1;
sbit led_3=P1^2;
sbit LCD1602_rs=P2^5; //I/O 定义
sbit LCD1602_rw=P2^6; //I/O 定义
sbit LCD1602_e=P2^7;
sbit SCLK=P3^7; //DS1302时钟
sbit SDA=P3^6; //DS1302数据
sbit RST=P3^5; //DS1302片选
sbit key_1=P1^3;
sbit key_2=P1^4;
sbit key_3=P1^5;
sbit key_4=P1^6;
sbit Red=P2^1;
sbit Sen=P3^4;
uchar Time[11];
uchar state,mode,ms;
bit s1,ok,ss;
unsigned int IR_Time = 0 ;
void delay(uint T) //延时程序
{
while(T--);
}
/************************************************
* * * * 名称: : : : DS1302WriteByte
* * * * 说明: : : : 无
* * * * 功能: : : : 写入 t 8bit 数据
* * * * 调用: : : : delayus()
* * * * 输入: : : : dat: 要写入的数据
* * * * 输出: : : : 无
*************************************************/
void DS1302WriteByte(uchar dat)
{
uchar i;
SCLK=0; // 初始时钟线置为 0 0 0 0
delay(20);
for(i=0;i<8;i++) // 开始传输 8 8 8 8 个字节的数据
{
SDA=dat&0x01; // 取最低位,注意 2 DS1302 的数据和地址都是从最低位开始传输的
delay(20);
SCLK=1; // 时钟线拉高,制造上升沿, SDA 的数据被传输
delay(20);
SCLK=0; // 时钟线拉低,为下一个上升沿做准备
dat>>=1; // 数据右移一位,准备传输下一位数据
}
}
/************************************************
* * * * 名称: : : : DS1302ReadByte) ()
* * * * 说明: : : : 无
* * * * 功能: : : : 读取 t 8bit 的数据
* * * * 调用: : : : delayus()
* * * * 输入: : : : 无
* * * * 输出: : : : dat: 读取的数据
*************************************************/
uchar DS1302ReadByte()
{
uchar i,dat;
delay(20);
for(i=0;i<8;i++)
{
dat>>=1; // 要返回的数据左移一位
if(SDA==1) // 当数据线为高时,证明该位数据为 1 1 1 1
dat|=0x80; // 要传输数据的当前值置为 , 1, 若不是, , , , 则为 0 0 0 0
SCLK=1; //拉高时钟线
delay(20);
SCLK=0; // 制造下降沿
delay(20);
}
return dat; // 返回读取出的数据
}
/************************************************
* * * * 名称: : : : r uchar DS1302Read()
* * * * 说明: : : : 先写地址,后读数据
* * * * 功能: : : : 从 d cmd 相应地址中读取一个字节的数据
* * * * 调用: : : : DS1302WriteByte(),DS1302ReadByte()
* * * * 输入: : : : cmd: 要写入的控制字节
* * * * 输出: : : : dat: 读取的数据
*************************************************/
uchar DS1302Read(uchar cmd)
{
uchar dat;
RST=0; // 初始 CE 线置为 0 0 0 0
SCLK=0; // 初始时钟线置为 0 0 0 0
RST=1; // 初始 CE 置为 1 1 1 1 ,传输开始
DS1302WriteByte(cmd); // 传输命令字,要读取的时间/ / / / 日历地址
dat=DS1302ReadByte(); // 读取要得到的时间/ / / / 日期
SCLK=1; // 时钟线拉高
RST=0; // 读取结束, CE 置为 0 0 0 0 ,结束数据的传输
return dat; // 返回得到的时间/ / / / 日期
}
/************************************************
* * * * 名称: : : : DS1302Write
* * * * 说明: : : : 先写地址,后写数据
* * * * 功能: : : : 向 d cmd 相应地址中写一个字节的数据
* * * * 调用: : : : DS1302WriteByte()
* * * * 输入: : : : cmd: 要写入的控制字 ,dat: 要写入的数据
* * * * 输出: : : : 无
*************************************************/
void DS1302Write(uchar cmd, uchar dat)
{
RST=0; // 初始 CE 线置为 0 0 0 0
SCLK=0; // 初始时钟线置为 0 0 0 0
RST=1; // 初始 CE 置为 1 1 1 1 ,传输开始
DS1302WriteByte(cmd);
dat=(dat/10)*16+dat%10;
DS1302WriteByte(dat); // 写入要修改的时间/ / / / 日期
SCLK=1; // 时钟线拉高
RST=0; // 读取结束, CE 置为 0 0 0 0 ,结束数据的传输
}
/************************************************
* * * * 名称: : : : d void Init_DS1302(void)
* * * * 说明: : : : 给 2 1302 写入一个初始的值
* * * * 功能: : : : 写入日期,和时钟的值
* * * * 调用: : : : DS1302Write ()
* * * * 输入: : : : 无
* * * * 输出: : : : 无
*************************************************/
void Init_DS1302(void)
{
uchar dat;
if (DS1302Read(0xc1)!=3)
{
DS1302Write(0x8e,0x00); // 写保护关
DS1302Write(0xc0,3);
DS1302Write(0x80,0); //秒 // 初始秒值为 0
DS1302Write(0x82,18);//分 // 初始分钟值为 0
DS1302Write(0x84,6);//时 // 初始为 24 式 小时模式 初始时间为 0点
DS1302Write(0x86,12); //2011 年 1 月 1 日 日 星期 6
DS1302Write(0x88,3);
DS1302Write(0x8c,15);
DS1302Write(0x8a,3);
DS1302Write(0x90,0x01); // 充电
DS1302Write(0x8e,0x80);
}else
{
DS1302Write(0x8e,0x00); // 写保护关
DS1302Write(0x90,0x01); // 充电
DS1302Write(0x8e,0x80);
}
dat=DS1302Read(0xc3); //想换数据读取
dat=(dat/16)*10+dat%16;
Time[7]=dat;
dat=DS1302Read(0xc5);
dat=(dat/16)*10+dat%16;
Time[8]=dat;
dat=DS1302Read(0xc7);
dat=(dat/16)*10+dat%16;
Time[9]=dat;
dat=DS1302Read(0xc9);
dat=(dat/16)*10+dat%16;
Time[10]=dat;
}
void read_time() //实时读取DS1302中的时间数据
{
uchar i,j;
for (j=0;j<7;j++)
{
i=DS1302Read(0x81+j*2);
i=(i/16)*10+i%16;
Time[j]=i;
}
}
void write_DS1302(void) // 将设置好的时间、日期 发送到DS1302 内
{
DS1302Write(0x8e,0x00);
DS1302Write(0x80,Time[0]);
DS1302Write(0x82,Time[1]);
DS1302Write(0x84,Time[2]);
DS1302Write(0x86,Time[3]);
DS1302Write(0x88,Time[4]);
DS1302Write(0x8c,Time[6]);
DS1302Write(0x8a,Time[5]);
DS1302Write(0xc2,Time[7]);
DS1302Write(0xc4,Time[8]);
DS1302Write(0xc6,Time[9]);
DS1302Write(0xc8,Time[10]);
DS1302Write(0x90,0x01);
DS1302Write(0x8e,0x80);
}
void LCD1602_write(uchar order,dat) //1602 一个字节 处理
{
LCD1602_e=0;
LCD1602_rs=order;
LCD1602_dat=dat;
LCD1602_rw=0;
LCD1602_e=1;
delay(1);
LCD1602_e=0;
}
void LCD1602_writebyte(uchar *prointer) //1602 字符串 处理
{
while(*prointer!='\0')
{
LCD1602_write(1,*prointer);
prointer++;
}
}
void LCD1602_cls() //1602 初始化
{
LCD1602_write(0,0x01); //1602 清屏 指令
delay(1500);
LCD1602_write(0,0x38); // 功能设置 8位、5*7点阵
delay(1500);
LCD1602_write(0,0x0c); //设置 光标 不显示开关、不显示光标、字符不闪烁
LCD1602_write(0,0x06);
LCD1602_write(0,0xd0);
delay(1500);
}
void show()
{
if(state<6)
{
LCD1602_write(0,0x80);
if(state==1&&s1==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_writebyte("20");
LCD1602_write(1,0x30+Time[6]/10%10);
LCD1602_write(1,0x30+Time[6]%10);
}
LCD1602_writebyte("-");
if(state==2&&s1==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_write(1,0x30+Time[4]/10%10);
LCD1602_write(1,0x30+Time[4]%10);
}
LCD1602_writebyte("-");
if(state==3&&s1==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_write(1,0x30+Time[3]/10%10);
LCD1602_write(1,0x30+Time[3]%10);
}
LCD1602_writebyte(" ");
if(state==4&&s1==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_write(1,0x30+Time[2]/10%10);
LCD1602_write(1,0x30+Time[2]%10);
}
if(ss==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_writebyte(":");
}
if(state==5&&s1==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_write(1,0x30+Time[1]/10%10);
LCD1602_write(1,0x30+Time[1]%10);
}
LCD1602_write(0,0xc0);
LCD1602_writebyte("M:");
switch(mode)
{
case 0:
LCD1602_writebyte("Auto ");
break;
case 1:
LCD1602_writebyte("Manual ");
break;
case 2:
LCD1602_writebyte("Timing ");
break;
}
LCD1602_writebyte("LED:");
if(ok==0)
{
LCD1602_writebyte("OFF");
}else
{
LCD1602_writebyte(" ON");
}
}else
{
LCD1602_write(0,0x80);
LCD1602_writebyte("Start:");
if(state==6&&s1==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_write(1,0x30+Time[7]/10%10);
LCD1602_write(1,0x30+Time[7]%10);
}
LCD1602_writebyte(":");
if(state==7&&s1==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_write(1,0x30+Time[8]/10%10);
LCD1602_write(1,0x30+Time[8]%10);
}
LCD1602_writebyte(" ");
LCD1602_write(0,0xC0);
LCD1602_writebyte("Over:");
if(state==8&&s1==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_write(1,0x30+Time[9]/10%10);
LCD1602_write(1,0x30+Time[9]%10);
}
LCD1602_writebyte(":");
if(state==9&&s1==1)
{
LCD1602_writebyte(" ");
}else
{
LCD1602_write(1,0x30+Time[10]/10%10);
LCD1602_write(1,0x30+Time[10]%10);
}
LCD1602_writebyte(" ");
}
}
void key()
{
if(!key_1)
{
delay(1000);
if(!key_1)
{
while(!key_1)show();
state=(state+1)%10;
if(state==0)
{
write_DS1302();
}
}
}
if(!key_2&&state==0)
{
delay(1000);
if(!key_2)
{
while(!key_2)show();
mode=(mode+1)%3;
ok=0;
LED=1;
}
}
if(!key_3)
{
delay(1000);
if(!key_3)
{
while(!key_3) show();
switch(state)
{
case 1:
Time[6]=(Time[6]+1)%100;
break;
case 2:
Time[4]=Time[4]%12+1;
break;
case 3:
if(Time[4]==1|Time[4]==3|Time[4]==5|Time[4]==7|Time[4]==8|Time[4]==10|Time[4]==12)
{
Time[3]=(Time[3]%31)+1;
}else if(Time[4]==4|Time[4]==6|Time[4]==9|Time[4]==11)
{
Time[3]=(Time[3]%30)+1;
}else
{
Time[3]=(Time[3]%28)+1;
}
break;
case 4:
Time[2]=(Time[2]+1)%24;
break;
case 5:
Time[1]=(Time[1]+1)%60;
break;
case 6:
Time[7]=(Time[7]+1)%24;
break;
case 7:
Time[8]=(Time[8]+1)%60;
break;
case 8:
Time[9]=(Time[9]+1)%24;
break;
case 9:
Time[10]=(Time[10]+1)%60;
break;
case 0:
if(mode==1)
{
ok=1;
LED=0;
}
break;
}
}
}
if(!key_4)
{
delay(1000);
if(!key_4)
{
while(!key_4)show();
switch(state)
{
case 1:
if(Time[6]==0)Time[6]=99;
else Time[6]--;
break;
case 2:
Time[4]--;
if(Time[4]==0) Time[3]=12;
break;
case 3:
if(Time[4]==1|Time[4]==3|Time[4]==5|Time[4]==7|Time[4]==8|Time[4]==10|Time[4]==12)
{
Time[3]--;
if(Time[3]==0) Time[3]=31;
}else if(Time[4]==4|Time[4]==6|Time[4]==9|Time[4]==11)
{
Time[3]--;
if(Time[3]==0) Time[3]=30;
}else
{
Time[3]--;
if(Time[3]==0) Time[3]=29;
}
break;
case 4:
if(Time[2]==0) Time[2]=23;
else Time[2]--;
break;
case 5:
if(Time[1]==0) Time[1]=59;
else Time[1]--;
break;
case 6:
if(Time[7]==0) Time[7]=23;
else Time[7]--;
break;
case 7:
if(Time[8]==0) Time[8]=59;
else Time[8]--;
break;
case 8:
if(Time[9]==0) Time[9]=23;
else Time[9]--;
break;
case 9:
if(Time[10]==0) Time[10]=59;
else Time[10]--;
break;
case 0:
if(mode==1)
{
ok=0;
LED=1;
}
break;
}
}
}
}
void proc()
{
uint ks,js,dq;
switch(mode)
{
case 0:
led_1=0;
led_2=led_3=1;
if(Red==1&&Sen==1) IR_Time = 600;
if(IR_Time!=0)
{
LED=0;
ok=1;
}else
{
LED=1;
ok=0;
}
break;
case 1:
led_2=0;
led_1=led_3=1;
IR_Time = 0;
break;
case 2:
led_3=0;
led_2=led_1=1;
ks=Time[7]*60+Time[8]; //开始时间 |当天的分钟数
js=Time[9]*60+Time[10];
dq=Time[2]*60+Time[1];
IR_Time = 0;
if(ks<js)
{
if(dq>= ks && dq<js)
{
LED=0;
ok=1;
}else
{
LED=1;
ok=0;
}
}else if(ks>js)
{
if(dq>=ks|dq<js)
{
LED=0;
ok=1;
}else
{
LED=1;
ok=0;
}
}else
{
LED=1;
ok=0;
}
break;
}
}
void main()
{
TMOD=0x01;
TH0=0x3c;
TL0=0xb0;
EA=1;
ET0=1;
TR0=1;
Init_DS1302();
read_time();
LCD1602_cls();
if(Time[7]>23||Time[8]>59||Time[9]>23||Time[10]>59)
{
Time[7]=6;
Time[8]=30;
Time[9]=18;
Time[10]=30;
}
while(1)
{
key();
show();
if(state==0) read_time();
proc();
}
}
void init_1() interrupt 1
{
TH0=0x3c;
TL0=0xb0;
ms++;
if(IR_Time!=0) IR_Time--;
if(ms%5==0)
{
s1=!s1;
}
if(ms%10==0)
{
ss=!ss;
}
if(ms>19)
{
ms=0;
}
}
|