#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;
}
}
|