/*時鐘顯示1602獨立鍵盤(P1口)設置時鐘(K1設置時分秒星期年月日,K2加一,K3減一) */
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
//DS1302控制端口定義
sbit CE=P3^5;
sbit SDA=P3^4;
sbit SCLK=P3^6;
//LCD1602控制端口定義
sbit LCD_RS = P2^6;
sbit LCD_RW = P2^5;
sbit LCD_EN = P2^7;
//獨立按鍵定義
sbit K1=P1^0; //功能鍵
sbit K2=P1^1; //增大鍵
sbit K3=P1^2; //減小鍵
sbit K4=P1^3;
bit k=0;
//屏幕初始化圖標
uchar code table1[]={" 20 - - "};
uchar code table2[]={" : : "};
//星期LOGO
uchar code table3[]={"MON TUE WED THU FRI SAT SUN"};
//初始化 年 月 日 星期 時 分 秒
char year_h,year_l,month_h,month_l,day_h,day_l,hour_h,hour_l,min_h,min_l,sec_h,sec_l,date=1;
uchar year,month,day,hour,min,sec;
uchar K1num=0;
//聲明延時函數(shù)毫秒級
void delay1ms(uint ms);
/*******************************************************************************************
* 以下為DS1302驅動程序 *
*******************************************************************************************/
uchar DS1302_Read(uchar address)
{
uchar i,temp=0x00;
CE=0;
SDA=1;
SCLK=0;
CE=1;
for (i=0;i<8;i++) //循環(huán)8次 寫入地址數(shù)據(jù)
{
SCLK=0;
SDA=address&0x01; //每次傳輸?shù)妥止?jié)
address>>=1; //右移一位
SCLK=1;
}
delay1ms(1);
if(SDA)
temp|=0x80; //每次傳輸?shù)妥止?jié)
SCLK=0;
temp>>=1;
for (i=0;i<7;i++) //循環(huán)8次 讀取數(shù)據(jù)
{
SCLK=0;
if(SDA)
temp|=0x80; //每次傳輸?shù)妥止?jié)
SCLK=1;
temp>>=1; //右移一位
}
SCLK=1;
CE=0;
SDA=0;
return temp; //返回
}
void DS1302_Write(uchar address,uchar dat)
{
uchar i;
CE=0;
SCLK=0;
CE=1;
for (i=0;i<8;i++) //循環(huán)8次 寫入地址數(shù)據(jù)
{
SCLK=0;
_nop_();
SDA=address&0x01; //每次傳輸?shù)妥止?jié)
address>>=1; //右移一位
SCLK=1;
_nop_();
}
for (i=0;i<8;i++) //循環(huán)8次 寫入數(shù)據(jù)
{
SCLK=0;
_nop_();
SDA=dat&0x01; //每次傳輸?shù)妥止?jié)
dat>>=1; //右移一位 DSCLK=1
SCLK=1;
_nop_();
}
CE=0;
_nop_();
}
void DS1302_initW() //初始化時間設置(寫)
{
DS1302_Write(0x8e,0x00); //寫保護關
DS1302_Write(0x80,sec); //秒
DS1302_Write(0x82,min); //分
DS1302_Write(0x84,hour); //時
DS1302_Write(0x86,day); //日
DS1302_Write(0x88,month); //月
DS1302_Write(0x8a,date); //周
DS1302_Write(0x8c,year); //年
DS1302_Write(0x8e,0x80); //寫保護開
}
void DS1302_initR()
{
sec=DS1302_Read(0x81); //讀秒數(shù)據(jù)
min=DS1302_Read(0x83); //讀分鐘數(shù)據(jù)
hour=DS1302_Read(0x85); //讀小時數(shù)據(jù)
date=DS1302_Read(0x8b); //讀星期數(shù)據(jù)
day=DS1302_Read(0x87); //讀日數(shù)據(jù)
month=DS1302_Read(0x89);//讀月數(shù)據(jù)
year=DS1302_Read(0x8d); //讀年數(shù)據(jù)
}
/*******************************************************************************************
* 以上為DS1302驅動程序 *
*******************************************************************************************/
/*******************************************************************************************
* 以下為LCD1602驅動顯示程序 *
*******************************************************************************************/
void delay1ms(uint ms) //延時程序1ms
{
uint i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
void LCD_writecom(uchar com) //寫命令
{
LCD_RS=0;
LCD_RW=0;
LCD_EN=1;
delay1ms(2);
P0=com;
LCD_EN=0;
delay1ms(2);
}
void LCD_writedat(uchar dat) //寫數(shù)據(jù)
{
LCD_RS=1;
LCD_RW=0;
LCD_EN=1;
delay1ms(2);
P0=dat;
LCD_EN=0;
delay1ms(2);
}
void init()
{
LCD_EN=0;
delay1ms(15);
LCD_writecom(0x38); //工作方式設置(8位數(shù)據(jù)接口;兩行顯示;5*7點陣字符)
LCD_writecom(0x38);
delay1ms(5);
LCD_writecom(0x38);
LCD_writecom(0x06); //輸入方式設置(數(shù)據(jù)讀寫操作后AC自動加1;數(shù)據(jù)讀寫操作后畫面不移動)
LCD_writecom(0x0C); //顯示開關控制(開顯示,關光標,關閃爍)
LCD_writecom(0x01); //清屏
}
void display1() //初始化屏幕 格式: 20 - - // : :
{
uchar num;
init();
LCD_writecom(0x80);
for(num=0;num<12;num++)
{
LCD_writedat(table1[num]);
delay1ms(2);
}
LCD_writecom(0x80+0x40);
for(num=0;num<15;num++)
{
LCD_writedat(table2[num]);
delay1ms(2);
}
}
void display2(uchar date)
{
uchar num;
LCD_writecom(0x80+12);
if(date==1) //星期一
{
for(num=0;num<3;num++)
{
LCD_writedat(table3[num]);
delay1ms(2);
}
}
if(date==2) //星期二
{
for(num=4;num<7;num++)
{
LCD_writedat(table3[num]);
delay1ms(2);
}
}
if(date==3) //星期三
{
for(num=8;num<11;num++)
{
LCD_writedat(table3[num]);
delay1ms(2);
}
}
if(date==4) //星期四
{
for(num=12;num<15;num++)
{
LCD_writedat(table3[num]);
delay1ms(2);
}
} //星期五
if(date==5)
{
for(num=16;num<19;num++)
{
LCD_writedat(table3[num]);
delay1ms(2);
}
}
if(date==6) //星期六
{
for(num=20;num<23;num++)
{
LCD_writedat(table3[num]);
delay1ms(2);
}
} //星期日
if(date==7)
{
for(num=24;num<27;num++)
{
LCD_writedat(table3[num]);
delay1ms(2);
}
}
}
void write_sfm(uchar add,char date) //時分秒寫入顯示
{
char shi,ge;
shi=date/16;
ge=date%16;
LCD_writecom(0x80+0x40+add);
LCD_writedat(0x30+shi);
LCD_writedat(0x30+ge);
}
void write_nyrx(uchar add,char date) //年月日星期寫入顯示
{
char shi,ge;
shi=date/16;
ge=date%16;
LCD_writecom(0x80+add);
LCD_writedat(0x30+shi);
LCD_writedat(0x30+ge);
}
/*******************************************************************************************
* 以上為LCD1602驅動顯示程序 *
*******************************************************************************************/
void display3() //時間顯示程序
{
if(k==0) //時間顯示停止控制標志
{
DS1302_initR();
write_sfm(10,sec);
write_sfm(7,min);
write_sfm(4,hour);
write_nyrx(3,year);
write_nyrx(6,month);
write_nyrx(9,day);
display2(date);
}
}
void keyscan() //鍵盤掃描
{
display3();
if(K1==0)
{
delay1ms(5);
if(K1==0)
{
K1num++; //K1按鍵計數(shù)
while(!K1);
k=1;
DS1302_Write(0x8e,0x00); //寫保護關
DS1302_Write(0x80,0x80); //時間暫停
switch(K1num)
{
case 1:
LCD_writecom(0x80+0x40+11);
LCD_writecom(0x0f);
k=1; //時間暫停顯示
break;
case 2:
LCD_writecom(0x80+0x40+8);break;
case 3:
LCD_writecom(0x80+0x40+5);break;
case 4:
LCD_writecom(0x80+14);break;
case 5:
LCD_writecom(0x80+10);break;
case 6:
LCD_writecom(0x80+7);break;
case 7:
LCD_writecom(0x80+4);break;
case 8:
LCD_writecom(0x0c);
DS1302_initW(); //將設置的時間日期等寫入DS1302中
k=0; //時間繼續(xù)走
K1num=0; //K1按鍵計數(shù)清零
DS1302_Write(0x80,0x00); //時間繼續(xù)
// DS1302_Write(0x8e,0x80); //寫保護開
break;
}
}
}
if(K1num!=0) //如果K1按下進行以下操作
{
if(K2==0) //K1按下進行K2按鍵檢測
{
delay1ms(5);
if(K2==0)
{
while(!K2);
switch(K1num)
{ //秒++
case 1:
sec_h=sec/16;
sec_l=sec%16;
sec_l++;
if(sec_l==10)
{
sec_l=0;
sec_h++;
}
if(sec_h==6)
sec_h=0;
sec=sec_h*16+sec_l;
write_sfm(10,sec);
LCD_writecom(0x80+0x40+11);
break;
case 2:
min_h=min/16; //分++
min_l=min%16;
min_l++;
if(min_l==10)
{
min_l=0;
min_h++;
}
if(min_h==6)
min_h=0;
min=min_h*16+min_l;
write_sfm(7,min);
LCD_writecom(0x80+0x40+8);
break;
case 3:
hour_h=hour/16;
hour_l=hour%16; //時++
if(hour_h==2)
{
if(hour_l>3)
{
hour_h=0;
hour_l=0;
}
}
hour_l++;
if(hour_l==10)
{
hour_l=0;
hour_h++;
}
if((hour_h==2)&&(hour_l>3))
{
hour_h=0;
hour_l=0;
}
hour=hour_h*16+hour_l;
write_sfm(4,hour);
LCD_writecom(0x80+0x40+5);
break;
case 4: date++;
if(date==8)
date=1;
display2(date);
LCD_writecom(0x80+14);
break;
case 5:
day_h=day/16;
day_l=day%16;
if(day_h==3)
{
if(day_l>1)
{
day_h=0;
day_l=1;
}
}
day_l++;
if(day_l==10)
{
day_l=0;
day_h++;
}
if((day_h==3)&&(day_l>1))
{
day_h=0;
day_l=1;
}
day=day_h*16+day_l;
write_nyrx(9,day);
LCD_writecom(0x80+10);
break;
case 6:
month_h=month/16; //月++
month_l=month%16;
if(month_h==1)
{
if(month_l>2)
{
month_h=0;
month_l=1;
}
}
month_l++;
if(month_l==10)
{
month_l=0;
month_h++;
}
if((month_h==1)&&(month_l>2))
{
month_h=0;
month_l=1;
}
month=month_h*16+month_l;
write_nyrx(6,month);
LCD_writecom(0x80+7);
break;
case 7:
year_h=year/16;
year_l=year%16;
year_l++;
if(year_l==10)
{
year_l=0;
year_h++;
}
if(year_h==6)
year_h=0;
year=year_h*16+year_l;
write_nyrx(3,year);
LCD_writecom(0x80+4);
break;
}
}
}
if(K3==0) //K1按下進行K3按鍵檢測
{
delay1ms(5);
if(K3==0)
{
while(!K3);
switch(K1num)
{
case 1:
sec_h=sec/16;
sec_l=sec%16;
sec_l--;
if(sec_l==-1)
{
sec_l=9;
sec_h--;
}
if(sec_h==-1)
sec_h=5;
sec=sec_h*16+sec_l;
write_sfm(10,sec);
LCD_writecom(0x80+0x40+11);
break;
case 2:
min_h=min/16;
min_l=min%16;
min_l--;
if(min_l==-1)
{
min_l=9;
min_h--;
}
if(min_h==-1)
min_h=5;
min=min_h*16+min_l;
write_sfm(7,min);
LCD_writecom(0x80+0x40+8);
break;
case 3:
hour_h=hour/16;
hour_l=hour%16;
hour_l--;
if(hour_l==-1)
{
hour_l=9;
hour_h--;
}
if(hour_h==-1)
{
hour_h=2;
hour_l=3;
}
hour=hour_h*16+hour_l;
write_sfm(4,hour);
LCD_writecom(0x80+0x40+5);
break;
case 4:
date--;
if(date==0)
date=7;
display2(date);
LCD_writecom(0x80+14);
break;
case 5: day_l--;
if(day_l==-1)
{
day_l=9;
day_h--;
}
if(day_h==-1)
{
day_h=3;
day_l=1;
}
if((day_h==0)&&(day_l==0))
{
day_h=3;
day_l=1;
}
day=day_h*16+day_l;
write_nyrx(9,day);
LCD_writecom(0x80+10);
break;
case 6:
month_l--;
if(month_l==-1)
{
month_l=9;
month_h--;
}
if(month_h==-1)
{
month_h=1;
month_l=2;
}
if((month_h==0)&&(month_l==0))
{
month_h=1;
month_l=2;
}
month=month_h*16+month_l;
write_nyrx(6,month);
LCD_writecom(0x80+7);
break;
case 7:
year_h=year/16;
year_l=year%16;
year_l--;
if(year_l==-1)
{
year_l=9;
year_h--;
}
if(year_h==-1)
year_h=5;
year=year_h*16+year_l;
write_nyrx(3,year);
LCD_writecom(0x80+4);
break;
}
}
}
if(K4==0) //K1按下進行K2按鍵檢測
{
delay1ms(5);
if(K4==0)
{
while(!K4);
LCD_writecom(0x0c);
DS1302_initW(); //將設置的時間日期等寫入DS1302中
K1num=0; //K1按鍵計數(shù)清零
k=0; //時間繼續(xù)走
}
}
}
}
void main()
{
display1(); //初始化屏幕顯示
// DS1302_initW(); //初始化時間日期
// DS1302_initR(); //讀取時間日期
while(1)
{
keyscan();
}
}
|