#include<reg52.h>
#include<INTRINS.H>
/************************************************************/
#define uchar unsigned char
#define uint unsigned int
#define TIME (0X10000-50000)
#define FLAG 0XEF //鬧鐘標志
/************************************************************/
//引腳連接圖
sbit CLK=P1^2;
sbit RST=P1^4;
sbit DAT=P1^3;
sbit RS=P1^5;
sbit RW=P1^6;
sbit E=P1^7;
sbit P32=P3^2;
sbit KEY1 = P2^7;
sbit KEY2 = P2^6;
sbit KEY3 = P2^5;
sbit KEY4 = P2^4;
sbit ACC_7=ACC^7;
/************************************************************/
/*全局變量及常量定義*/
uchar i=20,j;
uchar DataBuf[16] = {};//日期
uchar TimeBuf[16] = {};//時間
uchar alarm[2],time[3];
uchar code Day[]={31,28,31,30,31,30,31,31,30,31,30,31};//12個月的最大日期(非閏年)
/*閏年月星期表*/
const uchar WeekTab[]=
{
(3 << 5) + 31,///1月
(6 << 5) + 29,///2月
(0 << 5) + 31,///3月
(3 << 5) + 30,///4月
(5 << 5) + 31,//5月
(1 << 5) + 30,//6月
(3 << 5) + 31,//7月
(6 << 5) + 31,//8月
(1 << 5) + 30,//9月
(4 << 5) + 31,//10月
(0 << 5) + 30,//11月
(2 << 5) + 31 //12月
};
/*音律表*/
uint code table1[]=
{
64260,64400,64524,64580,64684,
64777,64820,64898,64968,65030,
65058,65110,65157,65178,65217
};
/*發聲部分的延時時間*/
uchar code table2[]=
{0x82,1,0x81,0xf4,0xd4,
0xb4,0xa4,0x94,0xe2,1,
0xe1,0xd4,0xb4,0xc4,0xb4,4,0
};
/*鬧鐘中用的全局變量*/
uchar th1,tl1;
/************************************************************/
delay1ms(uchar time)//延時1ms函數
{
uchar i,j;
for(i=0;i<time;i++)
{
for(j=0;j<250;j++);
}
}
/************************************************************/
Enable() //LCD控制函數
{
RS=0;
RW=0;
E=0;
delay1ms(3);
E=1;
}
/************************************************************/
LCD1602_WriteSChr(uchar i)//LCD1602寫入字符函數
{
P0=i;
RS=1;
RW=0;
E=0;
delay1ms(2);
E=1;
}
/************************************************************/
/*LCD1602寫入字符串函數
//入口函數
//uchar data *address : 寫入數據首地址
//ucharm:寫入字節數*/
LCD1602_WriteStr(uchar *address,uchar m)
{
uchar i,j;
for(i=0;i<m;i++,address++)
{
j=*address;
LCD1602_WriteSChr(j);
}
}
/************************************************************/
void LCDShow(void)//LCD顯示
{
P0=0XC; //顯示器開、光標關
Enable();
//P0=0x80; //寫入顯示起始地址
//Enable();
//LCD1602_WriteStr(DataBuf,16); //寫入日期顯示緩存
P0=0xc1; //寫入顯示起始地址
Enable();
LCD1602_WriteStr(TimeBuf,16); //寫入時間顯示緩存
}
/************************************************************/
void DS1302_Write(uchar temp)//DS1302寫入子程序
{
uchar i;
CLK=0; //將DS1320時鐘脈沖拉低
_nop_();//延時一指令周期
RST=1; //RST置高電平
_nop_();//延時一指令周期
for(i=0;i<8;i++) //循環8次
{
DAT=temp&0x01; //向DS1302寫入一字節數據
_nop_(); //延時一指令周期
CLK=1; //拉高時鐘脈沖
temp>>=1; //右移一位
CLK=0; //拉低時鐘脈沖
}
}
/************************************************************/
uchar DS1302_Read()//DS1302讀取子程序
{
uchar i,j=0;
for(i=0;i<8;i++)//循環8次
{
j>>=1; //右移一位
_nop_(); //延時一指令周期
CLK=0; //拉低時鐘脈沖
_nop_(); //延時一指令周期
if(DAT) //判斷接收該位數據是否為1
j|=0x80;//該位置1
_nop_(); //延時一指令周期
CLK=1; //拉高時鐘脈沖
}
return(j); //返回數值
}
/************************************************************/
TimeStart()//部分顯示數據初始化
{
TimeBuf[0]=TimeBuf[8]=TimeBuf[9]=TimeBuf[10]=0x20; //不顯示字符
TimeBuf[2]=TimeBuf[5]=':'; //時間分隔顯示
DS1302_Write(0xc1);
alarm[0]=DS1302_Read();
RST=0;
DS1302_Write(0xc3);
alarm[1]=DS1302_Read();
RST=0;
DS1302_Write(0xc5);
DataBuf[0]=DS1302_Read();
RST=0;
}
/************************************************************/
ReadTime()//讀取時間
{
uchar i,m,n;
for(m=0,i=0,n=0x85;i<7;i+=3,n-=2,m++) //連續讀取時,分,秒
{
DS1302_Write(n); //寫入讀取寄存器指令
time[m]=DS1302_Read(); //讀取數據
RST=0; //將RST電平拉低,停止傳輸
TimeBuf[i]=time[m]/16+0x30; //將兩位數據的十位轉為字符格式
TimeBuf[i+1]=time[m]%16+0x30;//將兩位數據的個位轉為字符格式
}
}
/************************************************************/
time0() interrupt 1 using 1//功能選擇超時定時器
{
i--;
if(i==0)
{
if(j!=0)
j--;
i=20;
}
TH0=TIME/256,TL0=TIME%256;
}
/************************************************************/
intime1() interrupt 3//產生鬧鈴音調
{
TH1=th1,TL1=tl1;
P32=!P32;
}
/************************************************************/
void AlarmShow(void)//鬧鐘顯示
{
uchar i,j,a,b,n;
ET1=1;
for(j=0;j<6;j++)
{
i=0;
while(1)
{
a=table2[i];
if(a==0)
break;
b=a&0xf;
a>>=4;
if(a==0)
{
TR1=0;
goto D1;
}
a=((--a)<<1)/2;
TH1=th1=table1[a]/256,TL1=tl1=table1[a]%256;
TR1=1;
D1: do
{
b--;
for(n=0;n<3;n++)
{
ReadTime();
LCDShow();
P2=0xff;
if(KEY4 == 1)
{
delay1ms(100);
if(KEY4 == 1)
{
TR1=0;
ET1=0;
P32 = 1;
return;
}
}
}
}
while(b!=0);
i++;
}
TR1=0;
}
ET1=0;
}
/************************************************************/
void SetTime(void)//設置日期、時間
{
uchar i=0xc2,year,month,day,n;
TimeBuf[6]=TimeBuf[7]=0x30;
DataBuf[14]=DataBuf[15]=0x20;
LCDShow();
while(1)
{
P0=0xe; //顯示器開、光標開
Enable();
P0=i; //定光標
Enable();
P2=0xff;
if((KEY1 == 1)||(KEY2 == 1)||(KEY3 == 1)||(KEY4 == 1))
{
delay1ms(100); //延時0.1s去抖動
if((KEY1 == 1)||(KEY2 == 1)||(KEY3 == 1)||(KEY4 == 1))
{
j=7;
if(KEY1 == 1)
{
i+=3; //更改設置項目
if(i==0x8e)
i=0xc2;
else if(i>0xc5)
i=0xc2;
}
else if(KEY2 == 1)
{
year=(DataBuf[4]&0xf)*10+(DataBuf[5]&0xf); //將字符格式的年份轉換為數值格式
month=(DataBuf[7]&0xf)*10+(DataBuf[8]&0xf); //將字符格式的月份轉換為數值格式
day=(DataBuf[10]&0xf)*10+(DataBuf[11]&0xf); //將字符格式的日數轉換為數值格式
if(i==0x85) //設置年份
{
year++;
if(year>99)
year=0;
if((year%4)!=0)
if(month==2&&day==29)
day=28;
}
else if(i==0x88) //設置月份
{
month++;
if(month>12)
month=1;
if(day>Day[month-1])
{
day=Day[month-1];
if(month==2&&(year%4)==0) //計算是否閏年
day=29;
}
}
else if(i==0x8b) //設置日期
{
day++;
if(day>Day[month-1])
{
if(month==2&&(year%4)==0) //計算是否閏年
{
if(day>29)
day=1;
}
if(month!=2)
day=1;
}
}
else if(i==0xc2) //設置小時
{
n=(TimeBuf[0]&0xf)*10+(TimeBuf[1]&0xf);
n++;
if(n>23)
n=0;
TimeBuf[0]=n/10+0x30;
TimeBuf[1]=n%10+0x30;
}
else //設置分鐘
{
n=(TimeBuf[3]&0xf)*10+(TimeBuf[4]&0xf);
n++;
if(n>59)
n=0;
TimeBuf[3]=n/10+0x30;
TimeBuf[4]=n%10+0x30;
}
DataBuf[4]=year/10+0x30; //將數值格式的日期轉換為字符形式
DataBuf[5]=year%10+0x30;
DataBuf[7]=month/10+0x30;
DataBuf[8]=month%10+0x30;
DataBuf[10]=day/10+0x30;
DataBuf[11]=day%10+0x30;
LCDShow();
}
else if(KEY3 == 1) //按保存退出鍵后,向DS1302寫入設置后的日期時間
{
DS1302_Write(0x8c);
DS1302_Write((DataBuf[4]&0xf)*16+(DataBuf[5]&0xf));
RST=0;
DS1302_Write(0x8a);
DS1302_Write(SetWeek());
RST=0;
for(i=7,n=0x88;i<11;i+=3,n-=2)
{
DS1302_Write(n);
DS1302_Write((DataBuf[i]&0xf)*16+(DataBuf[i+1]&0xf));
RST=0;
}
for(i=0;i<7;i+=3,n-=2)
{
DS1302_Write(n);
DS1302_Write((TimeBuf[i]&0xf)*16+(TimeBuf[i+1]&0xf));
RST=0;
}
TR0=0;
return;
}
else
{
TR0=0;
return;
}
}
}
if(j==0)
{
TR0=0;
return;
}
}
}
/************************************************************/
void SetAlarm(void)//設置鬧鐘
{
uchar i,n;
for(i=1;i<16;i++)
{
DataBuf[i]=0x20;
}
TimeBuf[0]=alarm[0]/16+0x30;
TimeBuf[1]=(alarm[0]&0xf)+0x30;
TimeBuf[3]=alarm[1]/16+0x30;
TimeBuf[4]=(alarm[1]&0xf)+0x30;
TimeBuf[6]=TimeBuf[7]=0x30;
LCDShow();
i=0xc2;
while(1)
{
P0=0xe; //顯示器開、光標開
Enable();
P0=i; //定光標
Enable();
P2=0xff;
if((KEY1 == 1)||(KEY2 == 1)||(KEY3 == 1)||(KEY4 == 1))
{
delay1ms(100); //延時0.1s去抖動
if((KEY1 == 1)||(KEY2 == 1)||(KEY3 == 1)||(KEY4 == 1))
{
j=7;
if(KEY1 == 1)
{
i+=3;
if(i>0xc5)
i=0xc2;
}
else if(KEY2 == 1)
{
if(i==0xc2)
{
n=(TimeBuf[0]&0xf)*10+(TimeBuf[1]&0xf);
n++;
if(n>23)
n=0;
TimeBuf[0]=n/10+0x30;
TimeBuf[1]=n%10+0x30;
}
else
{
n=(TimeBuf[3]&0xf)*10+(TimeBuf[4]&0xf);
n++;
if(n>59)
n=0;
TimeBuf[3]=n/10+0x30;
TimeBuf[4]=n%10+0x30;
}
LCDShow();
}
else if(KEY3 == 1)
{
DS1302_Write(0xc0);
DS1302_Write((TimeBuf[0]&0xf)*16+(TimeBuf[1]&0xf));
RST=0;
DS1302_Write(0xc2);
DS1302_Write((TimeBuf[3]&0xf)*16+(TimeBuf[4]&0xf));
RST=0;
DataBuf[0]=FLAG;
DS1302_Write(0xc4);
DS1302_Write(DataBuf[0]);
RST=0;
TR0=0;
TimeStart();
return;
}
else
{
TR0=0;
TimeStart();
return;
}
}
}
if(j==0)
{
TR0=0;
TimeStart();
return;
}
}
}
/************************************************************/
void DS1302_Init(void)//DS1302初始化程序
{
uchar i,n;
DS1302_Write(0x8c);
DS1302_Write((DataBuf[4]&0xf)*16+(DataBuf[5]&0xf));
RST=0;
DS1302_Write(0x8a);
DS1302_Write(SetWeek());
RST=0;
for(i=7,n=0x88;i<11;i+=3,n-=2)
{
DS1302_Write(n);
DS1302_Write((DataBuf[i]&0xf)*16+(DataBuf[i+1]&0xf));
RST=0;
}
for(i=0;i<7;i+=3,n-=2)
{
DS1302_Write(n);
DS1302_Write((TimeBuf[i]&0xf)*16+(TimeBuf[i+1]&0xf));
RST=0;
}
}
/************************************************************/
void zhu_Init()
{
IE=0x82;
TMOD=0x11;
DS1302_Write(0x8E); //禁止寫保護
DS1302_Write(0);
RST=0;
P0=1; //清屏并光標復位
Enable();
P0=0x38; //設置顯示模式:8位2行5x7點陣
Enable();
P0=6; //文字不動,光標自動右移
Enable();
DS1302_Init();
TimeStart();
}
main()//主函數
{
zhu_Init()
while(1)
{
ReadTime(); //讀取時間
LCDShow(); //顯示時間
if(DataBuf[0]!=0x20)
if(time[0]==alarm[0])
if(time[1]==alarm[1])
if(time[2]==0)
AlarmShow();
P2=0xff;
if((KEY1 == 1)||(KEY2 == 1)||(KEY3 == 1))
{
delay1ms(100); //延時0.1s去抖動
if((KEY1 == 1)||(KEY2 == 1)||(KEY3 == 1))
{
j=7;
TH0=TIME/256,TL0=TIME%256;
TR0=1;
if(KEY1 == 1)
{
SetTime();
}
else if(KEY2 == 1)
{
SetAlarm();
}
else if(KEY3 == 1)
{
TR0=0;
if(DataBuf[0]==FLAG)
DataBuf[0]=0x20;
else
DataBuf[0]=FLAG;
DS1302_Write(0xc4);
DS1302_Write(DataBuf[0]);
RST=0;
}
}
}
delay1ms(100);
}
}
|