找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2200|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

多功能電子鐘

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:243235 發(fā)表于 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;         //設(shè)置鍵
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;                //設(shè)置選擇標(biāo)記,=0非設(shè)置,=1設(shè)置年,=2設(shè)置月,=3設(shè)置日。=4設(shè)置時,=5設(shè)置分,=6設(shè)置秒
                                        //   =7設(shè)置鬧鐘-時,=8設(shè)置鬧鐘-分。=9設(shè)置鬧鐘秒,=10設(shè)置鬧鐘-開關(guān),=11整點報時-開關(guān)
uchar set_dao=0;        //倒計時設(shè)置標(biāo)記
uchar num;                        //計數(shù)變量
uchar naozhong[5];        //鬧鐘-秒、鬧鐘-分、鬧鐘-時、鬧鐘-開關(guān)、整點報時-開關(guān)
bit   baoshi_f=0;        //報時標(biāo)記位,=1整點報時
bit   naozhong_f=0;        //鬧鐘開始標(biāo)記位,=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;                //關(guān)閉蜂鳴器鳴叫
                led=1;                //關(guān)閉LED
                delayms(20);//延時
        }
}
/********************************************************
函數(shù)名稱:void display(void)
函數(shù)作用:正常顯示日期、時間函數(shù)
參數(shù)說明:
********************************************************/
void display(void)
{
           uchar xq;                                           //存儲星期
           uchar temp2[2];                                   //存儲鬧鐘結(jié)束時間
       
        //判斷整點報時
        if(time[0]<3&&time[1]==0&&baoshi_f==0)//判斷是否為整點
        {
                baoshi_f=1;                                   //標(biāo)記整點報時開啟
                if(naozhong[4]%2==1)           //如果整點報時開關(guān)有打開
                {
                        if(time[2]%12==0)           //根據(jù)當(dāng)前時間,控制蜂鳴器鳴叫次數(shù)
                                baoshi(12);
                        else
                                baoshi(time[2]%12);       
                }               
        }
        if(time[0]>10&&time[1]==0)           //整點報時結(jié)束
                baoshi_f=0;                                   //重置整點報時標(biāo)志
        //計算鬧鐘結(jié)束【時間】
        if(naozhong[1]!=59)                           //鬧鐘-分 不等于59分 【例:11:11】  
        {
                temp2[0]=naozhong[2];           //鬧鐘結(jié)束時間為:小時不變,分鐘+1
                temp2[1]=naozhong[1]+1;
        }
        else                                                   //鬧鐘-分 等于59
        {
                if(naozhong[2]!=23)                   //鬧鐘-時 不等于23時 【例:11:59
                {
                        temp2[0]=naozhong[2]+1;//鬧鐘結(jié)束時間為:小時加1,分鐘=0
                        temp2[1]=0;       
                }
                else                                           //鬧鐘-時 等于23時   【例:23:59
                {
                        temp2[0]=0;                           //鬧鐘結(jié)束時間為:小時=0,分鐘=0
                        temp2[1]=0;       
                }
        }
        if(time[2]==naozhong[2]&&time[1]==naozhong[1]&&time[0]==naozhong[0]&&naozhong[3]%2==1)//判斷當(dāng)前是否為鬧鐘時間
        {
                buzz=0;                                                //開啟鬧鈴,蜂鳴器鳴叫、LED燈點亮
                led=0;
                naozhong_f=1;                            //標(biāo)記鬧鐘開啟
        }
        if(time[2]==temp2[0]&&time[1]==temp2[1]&&time[0]==naozhong[0]&&naozhong[3]%2==1)           //判斷鬧鐘一分鐘是否結(jié)束
        {
                buzz=1;                                            //關(guān)閉鬧鈴,蜂鳴器停止、LED燈關(guān)閉
                led=1;
                naozhong_f=0;                                //重置鬧鐘開啟標(biāo)志
        }
          
   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行,所有關(guān)于顯示都一樣】
        LCD_disp_char(1,2,ASCII[time[2]%12%10]);//*/       
        //24小時制
        /*LCD_disp_char(0,2,ASCII[time[2]/10]);//顯示時【0:表示第1列,2:表示第2行,所有關(guān)于顯示都一樣】
        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ù)作用:顯示調(diào)整日期、時間函數(shù)
參數(shù)說明:
********************************************************/
void display2()
{
        num++;
        lcd1602_write_character(1,1,"Date:");
        lcd1602_write_character(1,2,"Time:");
       
        if(num%2==0)        ////偶數(shù)次顯示,奇數(shù)次不顯示。這樣就會有閃爍效果,可以清楚看到當(dāng)前設(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ù)當(dāng)前設(shè)置的內(nèi)容,對應(yīng)位置閃爍
                {
                        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ù)作用:顯示調(diào)整鬧鐘函數(shù)
參數(shù)說明:
********************************************************/
void display3()
{
        num++;
        lcd1602_write_character(3,1,"Alarm clock");
        if(num%2==0)        ////偶數(shù)次顯示,奇數(shù)次不顯示。這樣就會有閃爍效果,可以清楚看到當(dāng)前設(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"); //顯示鬧鐘-/關(guān)
                else
                        lcd1602_write_character(11,2,"ON");       
        }
        else                         //奇數(shù)次不顯示
        {
                switch(set_f)//根據(jù)當(dāng)前設(shè)置的內(nèi)容,對應(yīng)位置閃爍
                {
                        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ù)作用:顯示調(diào)整整點報時開關(guān)函數(shù)
參數(shù)說明:
********************************************************/
void display4()
{
        num++;
        lcd1602_write_character(2,1,"On time alarm");
        if(num%2==0)        //偶數(shù)次顯示,奇數(shù)次不顯示。這樣就會有閃爍效果,可以清楚看到當(dāng)前設(shè)置的是哪個值
        {       
                if(naozhong[4]%2==0)                                   //顯示設(shè)置整點報時-/關(guān)
                        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ù)
參數(shù)說明:
********************************************************/
void display7()
{
        num++;
        lcd1602_write_character(1,1,"The countdown");
        if(num%2==0)        //偶數(shù)次顯示,奇數(shù)次不顯示。這樣就會有閃爍效果,可以清楚看到當(dāng)前設(shè)置的是哪個值
        {               
                LCD_disp_char(4,2,ASCII[fens/100]);                //顯示設(shè)置倒計時-
                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]);                //顯示設(shè)置倒計時-
                LCD_disp_char(9,2,ASCII[times%10]);
                LCD_disp_char(10,2,'.');
                LCD_disp_char(11,2,ASCII[T0_num/2]);        //顯示設(shè)置倒計時-分秒
        }
        else                         //奇數(shù)次不顯示
        {
                switch(set_dao)//根據(jù)當(dāng)前設(shè)置的內(nèi)容,對應(yīng)位置閃爍
                {
                        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)
{
        //設(shè)置鍵
        if(key_mode==0)                                           //按鍵按下
        {  
                delayms(7);                                           //延時消抖
                if(key_mode==0)                                   //再次確認(rèn)按鍵按下
                {
                        if(miaobiao_f==0&&dao_f==0)//非秒表/非倒計時模式
                        {
                                buzz=1;                           //進(jìn)入設(shè)置關(guān)閉鬧鐘聲光提示
                            led=1;
                                if(set_f==0||set_f==6||set_f==10)     //進(jìn)入設(shè)置先清除屏幕,顯示設(shè)置部分
                                {
                                        Writeds1302 (WRITE_PROTECT,0X00); //禁止DS1302寫保護(hù)
                                        LCD_write_command(0x01);          //清除屏幕顯示
                                        delay_n40us(100);                          //延時等待全部清除完畢
                                }                               
                                set_f++;                                                          //設(shè)置變量+1
       
                                if(set_f>11)                          //全部設(shè)置完成,退出設(shè)置
                                {
                                        set_f=0;                                                  //重置設(shè)置變量
                                        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]);//寫入【鬧鐘-開關(guān)】數(shù)據(jù)保存
                                        AT24C02_write_date(4,naozhong[4]);//寫入【整點報時-開關(guān)】數(shù)據(jù)保存
                                       
                                        Writeds1302 (WRITE_MINUTE,(time[1]/10)*16+time[1]%10);//將設(shè)置好的時間寫入DS1302
                                        Writeds1302 (WRITE_SECOND,(time[0]/10)*16+time[0]%10);
                                        LCD_write_command(0x01);          //清除屏幕顯示
                                        delay_n40us(100);                          //延時等待全部清除完畢
                                }
                        }
                        else                           //否則,秒表模式或者倒計時模式
                        {
                                if(set_dao==0) //如果,非倒計時設(shè)置起始時間狀態(tài)下
                                        TR0=~TR0;  //切換 秒表計時或倒計時-開始/暫停
                        }                       
                }
                while(!key_mode);      //等待按鍵松開
        }
        //確定
        if(key_ok==0)                           //按鍵按下
        {
                delayms(7);                           //延時消抖
                if(key_ok==0&&set_f!=0)//再次確認(rèn)按鍵按下,并且當(dāng)前處于設(shè)置模式
                {
                        set_f=0;                                                  //重置設(shè)置變量       
                        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]);//寫入【鬧鐘-開關(guān)】數(shù)據(jù)保存
                        AT24C02_write_date(4,naozhong[4]);//寫入【整點報時-開關(guān)】數(shù)據(jù)保存       
                       
                        Writeds1302 (WRITE_MINUTE,(time[1]/10)*16+time[1]%10);//將設(shè)置好的時間寫入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)          //否則,當(dāng)前鬧鐘響起,進(jìn)入暫停鬧鐘
                        {
                                buzz=1;                                                  //關(guān)閉蜂鳴器
                                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)                  //退出秒表模式時,關(guān)閉秒表計時
                                        {
                                                TR0=0;                                  //關(guān)閉定時器
                                                T0_num=0;                          //重置所有秒表的時間
                                                times=0;
                                                fens=0;
                                        }
                                        AT24C02_write_date(5,miaobiao_f);//寫入【秒表標(biāo)志】數(shù)據(jù)保存
                                }
                                else
                                        if(dao_f==1)                          //否者,倒計時模式
                                        {
                                                if(buzz==0)                          //如果蜂鳴器響
                                                        buzz=1;                          //先關(guān)閉蜂鳴器
                                                else                                  //否者
                                                {
                                                        if(set_dao==0||set_dao==3)       
                                                        {
                                                                LCD_write_command(0x01);//清除屏幕顯示
                                                                    delay_n40us(100);                //延時等待全部清除完畢
                                                        }
                                                        set_dao++;                                        //倒計時起始時間設(shè)置標(biāo)志+1
                                                        if(set_dao==4)                            //全部設(shè)置完成
                                                                set_dao=0;                                //重置倒計時起始時間設(shè)置標(biāo)志
                                                }
                                        }
                               
                while(!key_ok);                                        //等待按鍵松開
        }
        //加鍵               
        if(key_jia==0)
        {
                delayms(7);
                if(key_jia==0&&set_f!=0)
                {
                        if(set_f==1)           //設(shè)置年
                        {
                                time[6]++;                                                        //年份+1
                                time[6]=(time[6]/10)*16+time[6]%10;        //將年份轉(zhuǎn)換成16進(jìn)制,例如:16-->0x16
                                if(time[6]>0x79)                                        //判斷是否達(dá)到最大年份79
                                        time[6]=0x00;                                        //重新回到00
                                Writeds1302 (WRITE_YEA,time[6]);        //將設(shè)置好的年份寫入到DS1302存儲起來
                                time[6]=Read1302(0x8d);                                //讀取當(dāng)前年份
                        }
               
                        if(set_f==2)           //設(shè)置月
                        {
                                time[4]++;                                                        //月份+1
                                time[4]=(time[4]/10)*16+time[4]%10;        //將月份轉(zhuǎn)換成16進(jìn)制,例如:08-->0x08
                                if(time[4]>0x12)                                        //判斷是否達(dá)到最大月份12
                                        time[4]=0x01;                                        //重新回到01
                                Writeds1302 (WRITE_MONTH,time[4]);        //將設(shè)置好的月份寫入到DS1302存儲起來
                        }
               
                        if(set_f==3)         //設(shè)置日
                        {
                                time[3]++;                                                        //日份+1
                                time[3]=(time[3]/10)*16+time[3]%10;        //將日份轉(zhuǎn)換成16進(jìn)制,例如: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)                                //判斷是否達(dá)到最大日份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)                //判斷是否達(dá)到最大日份28
                                                                time[3]=0x01;                //重新回到01
                                                }
                                                else                                                //否者平年
                                                {
                                                        if(time[3]>0x29)                //判斷是否達(dá)到最大日份29
                                                                time[3]=0x01;                //重新回到01
                                                }
                                        }
                                        else                                                        //否者為剩下的月份
                                        {
                                                if(time[3]>0x30)                        //判斷是否達(dá)到最大日份30
                                                        time[3]=0x01;                        //重新回到01
                                        }
                                }       
                                Writeds1302 (WRITE_DAY,time[3]);        //將設(shè)置好的日份寫入到DS1302存儲起來
                        }
               
                        if(set_f==4)          //設(shè)置時,同上
                        {                       
                                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)          //設(shè)置分,同上
                        {
                                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)         //設(shè)置秒,同上
                        {
                                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)         //設(shè)置鬧鐘-
                        {
                                naozhong[2]++;                //鬧鐘-+1
                                if(naozhong[2]>23)        //判斷鬧鐘-時 是否大于23
                                        naozhong[2]=0;        //如果是,回到0
                        }
               
                        if(set_f==8)    //設(shè)置鬧鐘-
                        {
                                naozhong[1]++;                //鬧鐘-+1
                                if(naozhong[1]>59)        //判斷鬧鐘-分 是否大于59
                                        naozhong[1]=0;        //如果是,回到0       
                        }
                       
                        if(set_f==9)        //設(shè)置鬧鐘-
                        {
                                naozhong[0]++;                //鬧鐘-+1
                                if(naozhong[0]>59)        //判斷鬧鐘-秒 是否大于59
                                        naozhong[0]=0;        //如果是,回到0
                        }
                       
                        if(set_f==10)        //設(shè)置鬧鐘-/關(guān)
                        {
                                naozhong[3]++;                //切換鬧鐘開/關(guān),只需要0表示關(guān),1表示開就可以。       
                                if(naozhong[3]==2)
                                        naozhong[3]=0;
                        }
                       
                        if(set_f==11)        //設(shè)置整點報時-/關(guān)
                        {
                                naozhong[4]++;                //切換整點報時開/關(guān),只需要0表示關(guān),1表示開就可以。               
                                if(naozhong[4]==2)
                                        naozhong[4]=0;
                        }
                }
                if(key_jia==0&&miaobiao_f==1)//秒表模式下
                {
                        T0_num=0;                                 //復(fù)位秒表時間
                        times=0;
                        fens=0;
                }
                if(key_jia==0&&set_dao!=0&&set_f==0)//設(shè)置倒計時起始時間
                {
                        if(set_dao==1)                  //設(shè)置倒計時起始時間-
                        {
                                if(fens!=255)
                                        fens++;
                        }
                        if(set_dao==2)                  //設(shè)置倒計時起始時間-
                        {
                                if(times==59)
                                {
                                        fens++;
                                        times=0;
                                }
                                else
                                        times++;
                        }
                        if(set_dao==3)                  //設(shè)置倒計時起始時間-分秒
                        {
                                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)         //設(shè)置年
                        {
                                if(time[6]==0)                                           //判斷當(dāng)前是否為00
                                        time[6]=79;                                           //如果是回到最大年份:79
                                else
                                        time[6]--;                                           //否者,年份-1
                                time[6]=(time[6]/10)*16+time[6]%10;//將年份轉(zhuǎn)換成16進(jìn)制,例如:16-->0x16                       
                                Writeds1302 (WRITE_YEA,time[6]);   //將設(shè)置好的年份寫入到DS1302存儲起來
                        }
       
                        if(set_f==2)         //設(shè)置月,同上
                        {
                                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)        //設(shè)置日,同上
                        {
                                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)        //設(shè)置時,同上
                        {                       
                                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)        //設(shè)置分,同上
                        {
                                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)        //設(shè)置秒,同上
                        {
                                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)         //設(shè)置鬧鐘-時,同上
                        {
                                if(naozhong[2]==0)
                                        naozhong[2]=23;
                                else       
                                        naozhong[2]--;                                               
                        }
       
                        if(set_f==8)        //設(shè)置鬧鐘-分,同上
                        {
                                if(naozhong[1]==0)
                                        naozhong[1]=59;
                                else       
                                        naozhong[1]--;
                        }
                       
                        if(set_f==9)        //設(shè)置鬧鐘-秒,同上
                        {
                                if(naozhong[0]==0)
                                        naozhong[0]=59;
                                else       
                                        naozhong[0]--;
                        }
                       
                        if(set_f==10)        //設(shè)置鬧鐘-/關(guān),同上
                        {
                                naozhong[3]++;                       
                                if(naozhong[3]==2)
                                        naozhong[3]=0;
                        }
                       
                        if(set_f==11)  //設(shè)置整點報時-/關(guān),同上
                        {
                                naozhong[4]++;                       
                                if(naozhong[4]==2)
                                        naozhong[4]=0;
                        }
                }
                if(key_jian==0&&miaobiao_f==1)//秒表模式
                {
                        T0_num=0;                                  //復(fù)位秒表時間
                        times=0;
                        fens=0;
                }
                if(key_jian==0&&set_dao!=0&&set_f==0)//設(shè)置倒計時起始時間
                {
                        if(set_dao==1)                                //設(shè)置倒計時起始時間-
                        {
                                if(fens!=0)
                                        fens--;
                        }
                        if(set_dao==2)                            //設(shè)置倒計時起始時間-
                        {
                                if(times!=0)
                                        times--;
                        }
                        if(set_dao==3)                            //設(shè)置倒計時起始時間-分秒
                        {
                                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;                                        //關(guān)閉定時器
                        buzz=1;                                        //關(guān)閉蜂鳴器
                        set_dao=0;                            //重置倒計時起始時間設(shè)置標(biāo)志
                        AT24C02_write_date(6,dao_f);//寫入【倒計時標(biāo)志】數(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);//讀取存儲的【鬧鐘-開關(guān)】數(shù)據(jù)
        naozhong[4]=AT24C02_read_date(4);//讀取存儲的【整點報時-開關(guān)】數(shù)據(jù)
        miaobiao_f=(bit)AT24C02_read_date(5);//讀取存儲的【秒表標(biāo)志】數(shù)據(jù)
        dao_f=(bit)AT24C02_read_date(6);//讀取存儲的【倒計時標(biāo)志】數(shù)據(jù)
        T0_init();         //定時器初始化
        LCD_init();  //LCD1602初始化
        Read_time(); //這邊初始化先讀取一次日期時間,是為了防止模式記憶到倒計時或秒表時退出秒表或倒計時時會誤認(rèn)為是整點進(jìn)行報時。
                               
        while(1)         //死循環(huán)
        {
                scan();         //按鍵檢測處理
                if(miaobiao_f==0&&dao_f==0)//非秒表模式/非倒計時模式,正常顯示模式
                {
                        if(set_f==0)                   //非設(shè)置模式下
                        {
                                Read_time();           //讀取DS1302時間
                                display();                   //更新顯示數(shù)據(jù)
                        }
                        else
                                if(set_f<7)                         //設(shè)置日期、時間模式
                                {                               
                                        Read_time();         //讀取時間、日期
                                        display2();                 //顯示
                                }
                                else
                                        if(set_f<11)         //設(shè)置鬧鐘模式
                                                display3();       
                                        else
                                                if(set_f==11)//設(shè)置整點報時開關(guān)模式
                                                        display4();
                }
                else
                        if(miaobiao_f==1)                  //秒表模式
                                display5();
                        else
                                if(dao_f==1&&set_dao==0)//倒計時模式
                                        display6();
                                else                                        //倒計時設(shè)置倒計時的時間模式
                                        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ù)并轉(zhuǎn)化成十進(jìn)制
參數(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ù)進(jìn)制轉(zhuǎn)換
       dat1=dat1%16;                         //十六進(jìn)制轉(zhuǎn)十進(jìn)制
       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ù)作用:計算陽歷日期對應(yīng)的星期數(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;         //倒計時標(biāo)記位,=0非倒計時模式,=1倒計時模式
bit miaobiao_f=0;//秒表標(biāo)記位,=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;                                   //關(guān)閉定時器
}
/*********************************************************
函數(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;        //關(guān)閉定時器,倒計時結(jié)束
                                                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
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表