標題: 多功能電子鐘 [打印本頁]
作者: 1393352008 時間: 2017-10-26 20:10
標題: 多功能電子鐘
#include<reg52.h> //頭文件
#include<LCD1602.h>
#include<DS1302.h>
#include<AT24C02.h>
#include<INTERRUPT.h>
#define uchar unsigned char//宏定義
#define uint unsigned int
/***********************引腳定義***********************/
sbit key_mode = P1^0; //設置鍵
sbit key_jia = P1^1; //加鍵
sbit key_jian = P1^2; //減鍵
sbit key_ok = P1^3; //確定鍵/切換秒表
sbit key_dao = P1^4; //切換倒計時
sbit led = P2^4; //LED燈
/***********************變量定義***********************/
uchar set_f=0; //設置選擇標記,=0非設置,=1設置年,=2設置月,=3設置日。=4設置時,=5設置分,=6設置秒
// =7設置鬧鐘-時,=8設置鬧鐘-分。=9設置鬧鐘秒,=10設置鬧鐘-開關,=11整點報時-開關
uchar set_dao=0; //倒計時設置標記
uchar num; //計數(shù)變量
uchar naozhong[5]; //鬧鐘-秒、鬧鐘-分、鬧鐘-時、鬧鐘-開關、整點報時-開關
bit baoshi_f=0; //報時標記位,=1整點報時
bit naozhong_f=0; //鬧鐘開始標記位,=1鬧鐘開始,=0鬧鐘未開始
/********************************************************
函數(shù)名稱:void delayms(uint ms)
函數(shù)作用:毫秒延時函數(shù)
參數(shù)說明:
********************************************************/
void delayms(uint ms)
{
unsigned char i=100,j;
for(;ms;ms--)
{
while(--i)
{
j=10;
while(--j);
}
}
}
/********************************************************
函數(shù)名稱:void baoshi(uchar i)
函數(shù)作用:整點報時函數(shù)
參數(shù)說明:I為蜂鳴器響的次數(shù)
********************************************************/
void baoshi(uchar i)
{
uchar j;
for(j=0;j<i;j++)//循環(huán)i次
{
buzz=0; //蜂鳴器鳴叫
led=0; //LED燈點亮
delayms(20);//延時
buzz=1; //關閉蜂鳴器鳴叫
led=1; //關閉LED燈
delayms(20);//延時
}
}
/********************************************************
函數(shù)名稱:void display(void)
函數(shù)作用:正常顯示日期、時間函數(shù)
參數(shù)說明:
********************************************************/
void display(void)
{
uchar xq; //存儲星期
uchar temp2[2]; //存儲鬧鐘結束時間
//判斷整點報時
if(time[0]<3&&time[1]==0&&baoshi_f==0)//判斷是否為整點
{
baoshi_f=1; //標記整點報時開啟
if(naozhong[4]%2==1) //如果整點報時開關有打開
{
if(time[2]%12==0) //根據(jù)當前時間,控制蜂鳴器鳴叫次數(shù)
baoshi(12);
else
baoshi(time[2]%12);
}
}
if(time[0]>10&&time[1]==0) //整點報時結束
baoshi_f=0; //重置整點報時標志
//計算鬧鐘結束【時間】
if(naozhong[1]!=59) //鬧鐘-分 不等于59分 【例:11:11】
{
temp2[0]=naozhong[2]; //鬧鐘結束時間為:小時不變,分鐘+1
temp2[1]=naozhong[1]+1;
}
else //鬧鐘-分 等于59分
{
if(naozhong[2]!=23) //鬧鐘-時 不等于23時 【例:11:59】
{
temp2[0]=naozhong[2]+1;//鬧鐘結束時間為:小時加1,分鐘=0
temp2[1]=0;
}
else //鬧鐘-時 等于23時 【例:23:59】
{
temp2[0]=0; //鬧鐘結束時間為:小時=0,分鐘=0
temp2[1]=0;
}
}
if(time[2]==naozhong[2]&&time[1]==naozhong[1]&&time[0]==naozhong[0]&&naozhong[3]%2==1)//判斷當前是否為鬧鐘時間
{
buzz=0; //開啟鬧鈴,蜂鳴器鳴叫、LED燈點亮
led=0;
naozhong_f=1; //標記鬧鐘開啟
}
if(time[2]==temp2[0]&&time[1]==temp2[1]&&time[0]==naozhong[0]&&naozhong[3]%2==1) //判斷鬧鐘一分鐘是否結束
{
buzz=1; //關閉鬧鈴,蜂鳴器停止、LED燈關閉
led=1;
naozhong_f=0; //重置鬧鐘開啟標志
}
xq=GetWeekDay(time[6],time[4],time[3]);//獲取星期
//顯示星期
switch(xq)
{
case 1:lcd1602_write_character(11,2,"Mon"); break;
case 2:lcd1602_write_character(10,2,"Tues"); break;
case 3:lcd1602_write_character(9,2,"Wednes"); break;
case 4:lcd1602_write_character(10,2,"Thurs"); break;
case 5:lcd1602_write_character(10,2,"Frid"); break;
case 6:lcd1602_write_character(10,2,"Satur"); break;
case 7:lcd1602_write_character(11,2,"Sun"); break;
default: break;
}
//顯示時間
//12小時制
LCD_disp_char(0,2,ASCII[time[2]%12/10]);//顯示時【0:表示第1列,2:表示第2行,所有關于顯示都一樣】
LCD_disp_char(1,2,ASCII[time[2]%12%10]);//*/
//24小時制
/*LCD_disp_char(0,2,ASCII[time[2]/10]);//顯示時【0:表示第1列,2:表示第2行,所有關于顯示都一樣】
LCD_disp_char(1,2,ASCII[time[2]%10]); //*/
LCD_disp_char(2,2,':');
LCD_disp_char(3,2,ASCII[time[1]/10]); //顯示分
LCD_disp_char(4,2,ASCII[time[1]%10]);
LCD_disp_char(5,2,':');
LCD_disp_char(6,2,ASCII[time[0]/10]); //顯示秒
LCD_disp_char(7,2,ASCII[time[0]%10]);
if(time[2]/12==0) //小于12小時,判斷為上午
lcd1602_write_character(11,1,"AM");
else //否者,下午
lcd1602_write_character(11,1,"PM");
//顯示日期
LCD_disp_char(0,1,ASCII[time[6]/10]);//顯示年
LCD_disp_char(1,1,ASCII[time[6]%10]);
LCD_disp_char(2,1,'/');
LCD_disp_char(3,1,ASCII[time[4]/10]);//顯示月
LCD_disp_char(4,1,ASCII[time[4]%10]);
LCD_disp_char(5,1,'/');
LCD_disp_char(6,1,ASCII[time[3]/10]);//顯示日
LCD_disp_char(7,1,ASCII[time[3]%10]);
}
/********************************************************
函數(shù)名稱:void display2(void)
函數(shù)作用:顯示調整日期、時間函數(shù)
參數(shù)說明:
********************************************************/
void display2()
{
num++;
lcd1602_write_character(1,1,"Date:");
lcd1602_write_character(1,2,"Time:");
if(num%2==0) ////偶數(shù)次顯示,奇數(shù)次不顯示。這樣就會有閃爍效果,可以清楚看到當前設置的是哪個值
{
LCD_disp_char(6,1,ASCII[time[6]/10]); //顯示年
LCD_disp_char(7,1,ASCII[time[6]%10]);
LCD_disp_char(8,1,'/');
LCD_disp_char(9,1,ASCII[time[4]/10]); //顯示月
LCD_disp_char(10,1,ASCII[time[4]%10]);
LCD_disp_char(11,1,'/');
LCD_disp_char(12,1,ASCII[time[3]/10]);//顯示日
LCD_disp_char(13,1,ASCII[time[3]%10]);
LCD_disp_char(6,2,ASCII[time[2]/10]); //顯示時
LCD_disp_char(7,2,ASCII[time[2]%10]);
LCD_disp_char(8,2,':');
LCD_disp_char(9,2,ASCII[time[1]/10]); //顯示分
LCD_disp_char(10,2,ASCII[time[1]%10]);
LCD_disp_char(11,2,':');
LCD_disp_char(12,2,ASCII[time[0]/10]);//顯示秒
LCD_disp_char(13,2,ASCII[time[0]%10]);
}
else //奇數(shù)次不顯示
{
switch(set_f)//根據(jù)當前設置的內(nèi)容,對應位置閃爍
{
case 1: lcd1602_write_character(6,1," "); break;
case 2: lcd1602_write_character(9,1," "); break;
case 3: lcd1602_write_character(12,1," "); break;
case 4: lcd1602_write_character(6,2," "); break;
case 5: lcd1602_write_character(9,2," "); break;
case 6: lcd1602_write_character(12,2," "); break;
default: break;
}
}
}
/********************************************************
函數(shù)名稱:void display3(void)
函數(shù)作用:顯示調整鬧鐘函數(shù)
參數(shù)說明:
********************************************************/
void display3()
{
num++;
lcd1602_write_character(3,1,"Alarm clock");
if(num%2==0) ////偶數(shù)次顯示,奇數(shù)次不顯示。這樣就會有閃爍效果,可以清楚看到當前設置的是哪個值
{
LCD_disp_char(2,2,ASCII[naozhong[2]/10]);//顯示鬧鐘-時
LCD_disp_char(3,2,ASCII[naozhong[2]%10]);
LCD_disp_char(4,2,':');
LCD_disp_char(5,2,ASCII[naozhong[1]/10]);//顯示鬧鐘-分
LCD_disp_char(6,2,ASCII[naozhong[1]%10]);
LCD_disp_char(7,2,':');
LCD_disp_char(8,2,ASCII[naozhong[0]/10]);//顯示鬧鐘-秒
LCD_disp_char(9,2,ASCII[naozhong[0]%10]);
if(naozhong[3]%2==0)
lcd1602_write_character(11,2,"OFF"); //顯示鬧鐘-開/關
else
lcd1602_write_character(11,2,"ON");
}
else //奇數(shù)次不顯示
{
switch(set_f)//根據(jù)當前設置的內(nèi)容,對應位置閃爍
{
case 7: lcd1602_write_character(2,2," "); break;
case 8: lcd1602_write_character(5,2," "); break;
case 9: lcd1602_write_character(8,2," "); break;
case 10: lcd1602_write_character(11,2," "); break;
default: break;
}
}
}
/********************************************************
函數(shù)名稱:void display4(void)
函數(shù)作用:顯示調整整點報時開關函數(shù)
參數(shù)說明:
********************************************************/
void display4()
{
num++;
lcd1602_write_character(2,1,"On time alarm");
if(num%2==0) //偶數(shù)次顯示,奇數(shù)次不顯示。這樣就會有閃爍效果,可以清楚看到當前設置的是哪個值
{
if(naozhong[4]%2==0) //顯示設置整點報時-開/關
lcd1602_write_character(7,2,"OFF");
else
lcd1602_write_character(7,2,"ON");
}
else //奇數(shù)次不顯示
lcd1602_write_character(7,2," "); //顯示空格
}
/********************************************************
函數(shù)名稱:void display5(void)
函數(shù)作用:顯示秒表計時函數(shù)
參數(shù)說明:
********************************************************/
void display5()
{
lcd1602_write_character(0,1,"Seconds counter");
LCD_disp_char(4,2,ASCII[fens/100]); //顯示秒表-分
LCD_disp_char(5,2,ASCII[fens%100/10]);
LCD_disp_char(6,2,ASCII[fens%10]);
LCD_disp_char(7,2,':');
LCD_disp_char(8,2,ASCII[times/10]); //顯示秒表-秒
LCD_disp_char(9,2,ASCII[times%10]);
LCD_disp_char(10,2,'.');
LCD_disp_char(11,2,ASCII[T0_num/2]); //顯示秒表-分秒
}
/********************************************************
函數(shù)名稱:void display6()
函數(shù)作用:倒計時顯示函數(shù)
參數(shù)說明:
********************************************************/
void display6()
{
lcd1602_write_character(1,1,"The countdown");
LCD_disp_char(4,2,ASCII[fens/100]); //顯示倒計時-分
LCD_disp_char(5,2,ASCII[fens%100/10]);
LCD_disp_char(6,2,ASCII[fens%10]);
LCD_disp_char(7,2,':');
LCD_disp_char(8,2,ASCII[times/10]); //顯示倒計時-秒
LCD_disp_char(9,2,ASCII[times%10]);
LCD_disp_char(10,2,'.');
LCD_disp_char(11,2,ASCII[T0_num/2]); //顯示倒計時-分秒
}
/********************************************************
函數(shù)名稱:void display7()
函數(shù)作用:倒計時設置顯示函數(shù)
參數(shù)說明:
********************************************************/
void display7()
{
num++;
lcd1602_write_character(1,1,"The countdown");
if(num%2==0) //偶數(shù)次顯示,奇數(shù)次不顯示。這樣就會有閃爍效果,可以清楚看到當前設置的是哪個值
{
LCD_disp_char(4,2,ASCII[fens/100]); //顯示設置倒計時-分
LCD_disp_char(5,2,ASCII[fens%100/10]);
LCD_disp_char(6,2,ASCII[fens%10]);
LCD_disp_char(7,2,':');
LCD_disp_char(8,2,ASCII[times/10]); //顯示設置倒計時-秒
LCD_disp_char(9,2,ASCII[times%10]);
LCD_disp_char(10,2,'.');
LCD_disp_char(11,2,ASCII[T0_num/2]); //顯示設置倒計時-分秒
}
else //奇數(shù)次不顯示
{
switch(set_dao)//根據(jù)當前設置的內(nèi)容,對應位置閃爍
{
case 1: lcd1602_write_character(4,2," "); break;
case 2: lcd1602_write_character(8,2," "); break;
case 3: lcd1602_write_character(11,2," "); break;
default: break;
}
}
}
/********************************************************
函數(shù)名稱:void scan(void)
函數(shù)作用:按鍵查詢處理函數(shù)
參數(shù)說明:
********************************************************/
void scan(void)
{
//設置鍵
if(key_mode==0) //按鍵按下
{
delayms(7); //延時消抖
if(key_mode==0) //再次確認按鍵按下
{
if(miaobiao_f==0&&dao_f==0)//非秒表/非倒計時模式
{
buzz=1; //進入設置關閉鬧鐘聲光提示
led=1;
if(set_f==0||set_f==6||set_f==10) //進入設置先清除屏幕,顯示設置部分
{
Writeds1302 (WRITE_PROTECT,0X00); //禁止DS1302寫保護
LCD_write_command(0x01); //清除屏幕顯示
delay_n40us(100); //延時等待全部清除完畢
}
set_f++; //設置變量+1
if(set_f>11) //全部設置完成,退出設置
{
set_f=0; //重置設置變量
AT24C02_write_date(0,naozhong[0]);//寫入【鬧鐘-秒】數(shù)據(jù)保存
AT24C02_write_date(1,naozhong[1]);//寫入【鬧鐘-分】數(shù)據(jù)保存
AT24C02_write_date(2,naozhong[2]);//寫入【鬧鐘-時】數(shù)據(jù)保存
AT24C02_write_date(3,naozhong[3]);//寫入【鬧鐘-開關】數(shù)據(jù)保存
AT24C02_write_date(4,naozhong[4]);//寫入【整點報時-開關】數(shù)據(jù)保存
Writeds1302 (WRITE_MINUTE,(time[1]/10)*16+time[1]%10);//將設置好的時間寫入DS1302
Writeds1302 (WRITE_SECOND,(time[0]/10)*16+time[0]%10);
LCD_write_command(0x01); //清除屏幕顯示
delay_n40us(100); //延時等待全部清除完畢
}
}
else //否則,秒表模式或者倒計時模式
{
if(set_dao==0) //如果,非倒計時設置起始時間狀態(tài)下
TR0=~TR0; //切換 秒表計時或倒計時-開始/暫停
}
}
while(!key_mode); //等待按鍵松開
}
//確定
if(key_ok==0) //按鍵按下
{
delayms(7); //延時消抖
if(key_ok==0&&set_f!=0)//再次確認按鍵按下,并且當前處于設置模式
{
set_f=0; //重置設置變量
AT24C02_write_date(0,naozhong[0]);//寫入【鬧鐘-秒】數(shù)據(jù)保存
AT24C02_write_date(1,naozhong[1]);//寫入【鬧鐘-分】數(shù)據(jù)保存
AT24C02_write_date(2,naozhong[2]);//寫入【鬧鐘-時】數(shù)據(jù)保存
AT24C02_write_date(3,naozhong[3]);//寫入【鬧鐘-開關】數(shù)據(jù)保存
AT24C02_write_date(4,naozhong[4]);//寫入【整點報時-開關】數(shù)據(jù)保存
Writeds1302 (WRITE_MINUTE,(time[1]/10)*16+time[1]%10);//將設置好的時間寫入DS1302
Writeds1302 (WRITE_SECOND,(time[0]/10)*16+time[0]%10);
LCD_write_command(0x01); //清除屏幕顯示
delay_n40us(100); //延時等待全部清除完畢
}
else
if(key_ok==0&&naozhong_f==1) //否則,當前鬧鐘響起,進入暫停鬧鐘
{
buzz=1; //關閉蜂鳴器
led=1; //熄滅LED燈
}
else
if(key_ok==0&&set_f==0&&dao_f==0)//否者,切換秒表模式和正常模式
{
miaobiao_f=~miaobiao_f; //切換秒表模式和正常模式
LCD_write_command(0x01); //清除屏幕顯示
delay_n40us(100); //延時等待全部清除完畢
if(miaobiao_f==0) //退出秒表模式時,關閉秒表計時
{
TR0=0; //關閉定時器
T0_num=0; //重置所有秒表的時間
times=0;
fens=0;
}
AT24C02_write_date(5,miaobiao_f);//寫入【秒表標志】數(shù)據(jù)保存
}
else
if(dao_f==1) //否者,倒計時模式
{
if(buzz==0) //如果蜂鳴器響
buzz=1; //先關閉蜂鳴器
else //否者
{
if(set_dao==0||set_dao==3)
{
LCD_write_command(0x01);//清除屏幕顯示
delay_n40us(100); //延時等待全部清除完畢
}
set_dao++; //倒計時起始時間設置標志+1
if(set_dao==4) //全部設置完成
set_dao=0; //重置倒計時起始時間設置標志
}
}
while(!key_ok); //等待按鍵松開
}
//加鍵
if(key_jia==0)
{
delayms(7);
if(key_jia==0&&set_f!=0)
{
if(set_f==1) //設置年
{
time[6]++; //年份+1
time[6]=(time[6]/10)*16+time[6]%10; //將年份轉換成16進制,例如:16年-->0x16
if(time[6]>0x79) //判斷是否達到最大年份79年
time[6]=0x00; //重新回到00年
Writeds1302 (WRITE_YEA,time[6]); //將設置好的年份寫入到DS1302存儲起來
time[6]=Read1302(0x8d); //讀取當前年份
}
if(set_f==2) //設置月
{
time[4]++; //月份+1
time[4]=(time[4]/10)*16+time[4]%10; //將月份轉換成16進制,例如:08月-->0x08
if(time[4]>0x12) //判斷是否達到最大月份12月
time[4]=0x01; //重新回到01月
Writeds1302 (WRITE_MONTH,time[4]); //將設置好的月份寫入到DS1302存儲起來
}
if(set_f==3) //設置日
{
time[3]++; //日份+1
time[3]=(time[3]/10)*16+time[3]%10; //將日份轉換成16進制,例如:15日-->0x15
if(time[4]==1||time[4]==3||time[4]==5||time[4]==7||time[4]==8||time[4]==10||time[4]==12)//1,3,5,7,8,10,12為大月,每月31天
{
if(time[3]>0x31) //判斷是否達到最大日份31日
time[3]=0x01; //重新回到01日
}
else //否者2,4,6,9,11為小月
{
if(time[4]==0x02) //如果是2月,需要區(qū)分閏、平年
{
if(((!(time[6]%4) && (time[6]%100)) || !(time[6]%400))==0)//如果閏年
{
if(time[3]>0x28) //判斷是否達到最大日份28日
time[3]=0x01; //重新回到01日
}
else //否者平年
{
if(time[3]>0x29) //判斷是否達到最大日份29日
time[3]=0x01; //重新回到01日
}
}
else //否者為剩下的月份
{
if(time[3]>0x30) //判斷是否達到最大日份30日
time[3]=0x01; //重新回到01日
}
}
Writeds1302 (WRITE_DAY,time[3]); //將設置好的日份寫入到DS1302存儲起來
}
if(set_f==4) //設置時,同上
{
time[2]++;
time[2]=(time[2]/10)*16+time[2]%10;
if(time[2]>0x23)
time[2]=0x00;
Writeds1302 (WRITE_HOUR,time[2]);
}
if(set_f==5) //設置分,同上
{
time[1]++;
time[1]=(time[1]/10)*16+time[1]%10;
if(time[1]>0x59)
time[1]=0x00;
Writeds1302 (WRITE_MINUTE,time[1]);
}
if(set_f==6) //設置秒,同上
{
time[0]++;
time[0]=(time[0]/10)*16+time[0]%10;
if(time[0]>0x59)
time[0]=0x00;
Writeds1302 (WRITE_SECOND,time[0]);
}
if(set_f==7) //設置鬧鐘-時
{
naozhong[2]++; //鬧鐘-時 +1
if(naozhong[2]>23) //判斷鬧鐘-時 是否大于23時
naozhong[2]=0; //如果是,回到0時
}
if(set_f==8) //設置鬧鐘-分
{
naozhong[1]++; //鬧鐘-分 +1
if(naozhong[1]>59) //判斷鬧鐘-分 是否大于59時
naozhong[1]=0; //如果是,回到0分
}
if(set_f==9) //設置鬧鐘-秒
{
naozhong[0]++; //鬧鐘-秒 +1
if(naozhong[0]>59) //判斷鬧鐘-秒 是否大于59秒
naozhong[0]=0; //如果是,回到0秒
}
if(set_f==10) //設置鬧鐘-開/關
{
naozhong[3]++; //切換鬧鐘開/關,只需要0表示關,1表示開就可以。
if(naozhong[3]==2)
naozhong[3]=0;
}
if(set_f==11) //設置整點報時-開/關
{
naozhong[4]++; //切換整點報時開/關,只需要0表示關,1表示開就可以。
if(naozhong[4]==2)
naozhong[4]=0;
}
}
if(key_jia==0&&miaobiao_f==1)//秒表模式下
{
T0_num=0; //復位秒表時間
times=0;
fens=0;
}
if(key_jia==0&&set_dao!=0&&set_f==0)//設置倒計時起始時間
{
if(set_dao==1) //設置倒計時起始時間-分
{
if(fens!=255)
fens++;
}
if(set_dao==2) //設置倒計時起始時間-秒
{
if(times==59)
{
fens++;
times=0;
}
else
times++;
}
if(set_dao==3) //設置倒計時起始時間-分秒
{
if(T0_num==18)
{
times++;
T0_num=0;
}
else
T0_num=T0_num+2;
}
}
}
//減鍵
if(key_jian==0)
{
delayms(7);
if(key_jian==0&&set_f!=0)
{
if(set_f==1) //設置年
{
if(time[6]==0) //判斷當前是否為00年
time[6]=79; //如果是回到最大年份:79年
else
time[6]--; //否者,年份-1
time[6]=(time[6]/10)*16+time[6]%10;//將年份轉換成16進制,例如:16年-->0x16
Writeds1302 (WRITE_YEA,time[6]); //將設置好的年份寫入到DS1302存儲起來
}
if(set_f==2) //設置月,同上
{
if(time[4]==1)
time[4]=12;
else
time[4]--;
time[4]=(time[4]/10)*16+time[4]%10;
Writeds1302 (WRITE_MONTH,time[4]);
}
if(set_f==3) //設置日,同上
{
time[3]--;
time[3]=(time[3]/10)*16+time[3]%10;
if(time[4]==1||time[4]==3||time[4]==5||time[4]==7||time[4]==8||time[4]==10||time[4]==12)
{
if(time[3]<0x01)
time[3]=0x31;
}
else
{
if(time[4]==0x02)
{
if(((!(time[6]%4) && (time[6]%100)) || !(time[6]%400))==0)
{
if(time[3]<0x01)
time[3]=0x28;
}
else
{
if(time[3]<0x01)
time[3]=0x29;
}
}
else
{
if(time[3]<0x01)
time[3]=0x30;
}
}
Writeds1302 (WRITE_DAY,time[3]);
}
if(set_f==4) //設置時,同上
{
if(time[2]==0)
time[2]=23;
else
time[2]--;
time[2]=(time[2]/10)*16+time[2]%10;
Writeds1302 (WRITE_HOUR,time[2]);
}
if(set_f==5) //設置分,同上
{
if(time[1]==0)
time[1]=59;
else
time[1]--;
time[1]=(time[1]/10)*16+time[1]%10;
Writeds1302 (WRITE_MINUTE,time[1]);
}
if(set_f==6) //設置秒,同上
{
if(time[0]==0)
time[0]=59;
else
time[0]--;
time[0]=(time[0]/10)*16+time[0]%10;
Writeds1302 (WRITE_SECOND,time[0]);
}
if(set_f==7) //設置鬧鐘-時,同上
{
if(naozhong[2]==0)
naozhong[2]=23;
else
naozhong[2]--;
}
if(set_f==8) //設置鬧鐘-分,同上
{
if(naozhong[1]==0)
naozhong[1]=59;
else
naozhong[1]--;
}
if(set_f==9) //設置鬧鐘-秒,同上
{
if(naozhong[0]==0)
naozhong[0]=59;
else
naozhong[0]--;
}
if(set_f==10) //設置鬧鐘-開/關,同上
{
naozhong[3]++;
if(naozhong[3]==2)
naozhong[3]=0;
}
if(set_f==11) //設置整點報時-開/關,同上
{
naozhong[4]++;
if(naozhong[4]==2)
naozhong[4]=0;
}
}
if(key_jian==0&&miaobiao_f==1)//秒表模式
{
T0_num=0; //復位秒表時間
times=0;
fens=0;
}
if(key_jian==0&&set_dao!=0&&set_f==0)//設置倒計時起始時間
{
if(set_dao==1) //設置倒計時起始時間-分
{
if(fens!=0)
fens--;
}
if(set_dao==2) //設置倒計時起始時間-秒
{
if(times!=0)
times--;
}
if(set_dao==3) //設置倒計時起始時間-分秒
{
if(T0_num!=0)
T0_num=T0_num-2;
}
}
}
//倒計時
if(key_dao==0&&set_f==0&&miaobiao_f==0)
{
delayms(7);
if(key_dao==0)
{
dao_f=~dao_f; //切換倒計時模式/正常模式
LCD_write_command(0x01);//清除屏幕顯示
delay_n40us(100); //延時等待全部清除完畢
TR0=0; //關閉定時器
buzz=1; //關閉蜂鳴器
set_dao=0; //重置倒計時起始時間設置標志
AT24C02_write_date(6,dao_f);//寫入【倒計時標志】數(shù)據(jù)保存
}
while(!key_dao); //等待按鍵松開
}
}
/********************************************************
函數(shù)名稱:void mian()
函數(shù)作用:主函數(shù)
參數(shù)說明:
********************************************************/
void main()
{
uchar i;
if(key_dao==0)
{
delayms(100);
if(key_dao==0)
{
for(i=0;i<7;i++)
{
AT24C02_write_date(i,0);//寫入數(shù)據(jù)保存
}
}
}
naozhong[0]=AT24C02_read_date(0);//讀取存儲的【鬧鐘-秒】數(shù)據(jù)
naozhong[1]=AT24C02_read_date(1);//讀取存儲的【鬧鐘-分】數(shù)據(jù)
naozhong[2]=AT24C02_read_date(2);//讀取存儲的【鬧鐘-時】數(shù)據(jù)
naozhong[3]=AT24C02_read_date(3);//讀取存儲的【鬧鐘-開關】數(shù)據(jù)
naozhong[4]=AT24C02_read_date(4);//讀取存儲的【整點報時-開關】數(shù)據(jù)
miaobiao_f=(bit)AT24C02_read_date(5);//讀取存儲的【秒表標志】數(shù)據(jù)
dao_f=(bit)AT24C02_read_date(6);//讀取存儲的【倒計時標志】數(shù)據(jù)
T0_init(); //定時器初始化
LCD_init(); //LCD1602初始化
Read_time(); //這邊初始化先讀取一次日期時間,是為了防止模式記憶到倒計時或秒表時退出秒表或倒計時時會誤認為是整點進行報時。
while(1) //死循環(huán)
{
scan(); //按鍵檢測處理
if(miaobiao_f==0&&dao_f==0)//非秒表模式/非倒計時模式,正常顯示模式
{
if(set_f==0) //非設置模式下
{
Read_time(); //讀取DS1302時間
display(); //更新顯示數(shù)據(jù)
}
else
if(set_f<7) //設置日期、時間模式
{
Read_time(); //讀取時間、日期
display2(); //顯示
}
else
if(set_f<11) //設置鬧鐘模式
display3();
else
if(set_f==11)//設置整點報時開關模式
display4();
}
else
if(miaobiao_f==1) //秒表模式
display5();
else
if(dao_f==1&&set_dao==0)//倒計時模式
display6();
else //倒計時設置倒計時的時間模式
display7();
}
}
#ifndef _DS1302_H_
#define _DS1302_H_
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
/*****************DS1302引腳定義*******************/
sbit SCLK = P3^5; // DS1302時鐘信號 7腳
sbit DIO = P3^6; // DS1302數(shù)據(jù)信號 6腳
sbit CE = P3^7; // DS1302片選 5腳
/*****************位尋址寄存器定義*******************/
sbit ACC_7 = ACC^7;
/*****************DS1302寄存器宏定義*****************/
#define WRITE_SECOND 0x80
#define WRITE_MINUTE 0x82
#define WRITE_HOUR 0x84
#define WRITE_DAY 0x86
#define WRITE_MONTH 0x88
#define WRITE_WEEK 0x8a
#define WRITE_YEA 0x8c
#define READ_SECOND 0x81
#define READ_MINUTE 0x83
#define READ_HOUR 0x85
#define READ_DAY 0x87
#define READ_MONTH 0x89
#define READ_WEEK 0x8b
#define READ_YEA 0x8d
#define WRITE_PROTECT 0x8E
/*****************DS1302函數(shù)定義*********************/
void Writeds1302 ( uchar addr,dat); //DS1302指定地址,寫數(shù)據(jù)
uchar Read1302 ( uchar addr ); //DS1302指定地址,讀數(shù)據(jù)
uchar Read1302_yuanshi(uchar addr); //DS1302讀原始數(shù)據(jù)函數(shù)
void Read_time(void); //DS1302讀時間日期函數(shù)
void DS1302_init(void); //DS1302初始化函數(shù)
/*****************DS1302變量定義*********************/
uchar data time[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //存儲秒,分,時,日,月,星期,年
uchar code Mon1[2][13]=
{0,31,28,31,30,31,30,31,31,30,31,30,31, //陽歷閏年
0,31,29,31,30,31,30,31,31,30,31,30,31};//陽歷平年
/********************************************************
函數(shù)名稱:void Writeds1302 ( unsigned char addr,dat )
函數(shù)作用:DS1302發(fā)送地址,數(shù)據(jù)
參數(shù)說明:addr:地址,dat:數(shù)據(jù)
********************************************************/
void Writeds1302 ( uchar addr,dat )
{
unsigned char i,temp;
CE=0; //CE引腳為低,數(shù)據(jù)傳送中止
SCLK=0; //清零時鐘總線
CE = 1; //CE引腳為高,邏輯控制有效
//發(fā)送地址
for ( i=8; i>0; i-- ) //循環(huán)8次移位
{
SCLK = 0;
temp = addr;
DIO = (bit)(temp&0x01); //每次傳輸?shù)妥止?jié)
addr >>= 1; //右移一位
SCLK = 1;
}
//發(fā)送數(shù)據(jù)
for ( i=8; i>0; i-- )
{
SCLK = 0;
temp = dat;
DIO = (bit)(temp&0x01);
dat >>= 1;
SCLK = 1;
}
SCLK=1;
CE = 0;
}
/********************************************************
函數(shù)名稱:uchar Read1302 ( uchar addr )
函數(shù)作用:DS1302讀取數(shù)據(jù)并轉化成十進制
參數(shù)說明:addr參考DS1302寄存器宏定義
********************************************************/
uchar Read1302 ( uchar addr )
{
unsigned char i,temp,dat1,dat2;
CE=0;
SCLK=0;
CE = 1;
//發(fā)送地址
for ( i=8; i>0; i-- ) //循環(huán)8次移位
{
SCLK = 0;
temp = addr;
DIO = (bit)(temp&0x01); //每次傳輸?shù)妥止?jié)
addr >>= 1; //右移一位
SCLK = 1;
}
//讀取數(shù)據(jù)
for ( i=8; i>0; i-- )
{
ACC_7=DIO;
SCLK = 1;
ACC>>=1;
SCLK = 0;
}
SCLK=1;
CE=0;
dat1=ACC;
dat2=dat1/16; //數(shù)據(jù)進制轉換
dat1=dat1%16; //十六進制轉十進制
dat1=dat1+dat2*10;
return (dat1);
}
/********************************************************
函數(shù)名稱:void Read_time(void)
函數(shù)作用:DS1302讀取時間日期
參數(shù)說明:
********************************************************/
void Read_time(void)
{
time[0]=Read1302(0x81);
time[1]=Read1302(0x83);
time[2]=Read1302(0x85);
time[3]=Read1302(0x87);
time[4]=Read1302(0x89);
time[5]=Read1302(0x8b);
time[6]=Read1302(0x8d);
}
/********************************************************
函數(shù)名稱:bit YearFlag(uchar cYear)
函數(shù)作用:計算是否閏年
參數(shù)說明:輸入:1:閏年,0:平年
********************************************************/
bit YearFlag(uchar cYear)
{
if( (!(cYear%4) && (cYear%100)) || !(cYear%400) ) return 1; else return 0;
}
/********************************************************
函數(shù)名稱:uchar GetWeekDay(uchar cYear,uchar cMon,uchar cDay)
函數(shù)作用:計算陽歷日期對應的星期數(shù)
參數(shù)說明:輸入:陽歷GreYear(年),GreMon(月),GreDay(日)
輸出:星期幾
********************************************************/
uchar GetWeekDay(uchar cYear,uchar cMon,uchar cDay)
{
char i;
int Sum=0,tmpyear=2000+cYear;
for(i=1;i<=cMon-1;i++)
Sum+=Mon1[YearFlag(cYear)];
Sum+=cDay-1;
return (((tmpyear-1)+(tmpyear-1)/4-(tmpyear-1)/100+(tmpyear-1)/400+Sum)%7)+1;
}
#endif
#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
/**********************引腳定義************************/
sbit buzz =P2^7; //蜂鳴器
/**********************變量定義************************/
uchar T0_num; //記錄定時中斷次數(shù)
uchar times; //記錄定時秒鐘數(shù)
uchar fens; //記錄定時分鐘數(shù)
bit dao_f=0; //倒計時標記位,=0非倒計時模式,=1倒計時模式
bit miaobiao_f=0;//秒表標記位,=0非秒表模式,=1秒表模式
/*********************************************************
函數(shù)名稱:void T0_init()
函數(shù)作用:定時器0初始化函數(shù)
參數(shù)說明:
*********************************************************/
void T0_init()
{
EA=1; //開總中斷
ET0=1; //定時器T0中斷允許
TMOD=0x01; //使用定時器T0的模式1
TH0=(65536-50000)/256; //定時器T0的高8位賦初值
TL0=(65536-50000)%256; //定時器T0的低8位賦初值
TR0=0; //關閉定時器
}
/*********************************************************
函數(shù)名稱:void T0_interrupt(void) interrupt 1 using 0
函數(shù)作用:定時器0中斷處理函數(shù)
參數(shù)說明:定時50ms中斷一次
*********************************************************/
void T0_interrupt(void) interrupt 1 using 0
{
TH0=(65536-50000)/256; //定時器T0的高8位重新賦初值
TL0=(65536-50000)%256; //定時器T0的低8位重新賦初值
if(miaobiao_f==1) //秒表模式
{
T0_num++; //定時中斷次數(shù)+1
if(T0_num==20) //定時1S完成,50ms*20=1S
{
T0_num=0; //重置定時中斷次數(shù)
times++; //秒數(shù)+1S
if(times==60) //如果秒數(shù)等于60S
{
times=0; //重置秒鐘數(shù)
fens++; //分鐘數(shù)+1min
}
}
}
else //否則,倒計時模式
if(dao_f==1)
{
if(fens==0&×<5&&T0_num%4==0)//如果倒計時最后剩下5秒
buzz=~buzz; //蜂鳴器鳴叫
if(T0_num==0) //如果分秒倒計時到0
{
if(times==0) //如果秒鐘=0
{
if(fens==0) //如果分鐘=0
{
TR0=0; //關閉定時器,倒計時結束
buzz=0; //開啟蜂鳴器鳴叫提示
}
else //否者,分鐘不為0
{
fens--; //分鐘數(shù)-1
times=59;//秒鐘=59
T0_num=19;//計數(shù)變量=19
}
}
else //否者,秒鐘數(shù)不為0
{
times--; //秒鐘數(shù)-1S
T0_num=19; //計數(shù)變量=19
}
}
else
T0_num--; //計數(shù)變量-1。減到0表示1秒倒計時完成
}
}
#endif
歡迎光臨 (http://www.torrancerestoration.com/bbs/) |
Powered by Discuz! X3.1 |