• 歡迎光臨東莞市飛江電子科技有限公司官網!
    全國咨詢熱線

    13926563901

    18925580829

    飛江淘寶店鋪

    首頁>技術資料>51單片機

    51單片機帶鬧鐘可調時間的電子時鐘程序設計

    發布時間:2018-03-26   瀏覽量:

    件部分

       基于51單片機、 ds1302時鐘芯片、 ds18b20溫度芯片、 以及1602液晶顯示的    實時時間   和   實時溫度顯示 。同時可通過按鍵 設置 年、月、日、時、分、星期。                                                      并且可以設置鬧鐘  當鬧鐘時間到時 蜂鳴器持續發出 滴..聲 同時led燈不停閃爍   且在一分鐘內沒有按指定停止按鍵 鬧鐘將自動停止  。。。



     

    軟件部分

    如果網頁上復制的代碼不能編譯可以從這里下載keil工程: http://www.51hei.com/f/dszdec.rar

    #include
    #define uchar unsigned char
    #define uint unsigned int
    sbit spk=P1^7;
    sbit led=P1^5;
    sbit DQ=P1^0;
    sbit RS=P2^4;
    sbit RW=P2^5;
    sbit EN=P2^6;
    sbit key1=P2^0;
    sbit key2=P2^1;
    sbit key3=P2^2;
    sbit key4=P2^3;
    sbit IO=P3^6;
    sbit RST=P3^7;
    sbit SCLK=P3^5;
    uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
    int nian,xing,yue,ri,shi,fen,miao;
    uchar num,temp,c,d,time[7],a,b,aa,bb,ns,ng,ys,yg,rs,rg,ss,sg,fs,fg,ms,mg,flag;

    /*******************1602************************/

    void delay(int z)
    {
     int x,y;
     for(x=z;x>0;x--)
      for(y=100;y>0;y--); 
    }

    void write_com(uchar com)   //寫命令
    {
     RS=0;
     P0=com;
     delay(5);
     EN=1;
     delay(5);
     EN=0;
    }

    void write_data(uchar date)      //寫數據
    {
     RS=1;
     P0=date;
     delay(5);
     EN=1;
     delay(5);
     EN=0;
    }
    void init()          //初始化
    {
     RW=0;
     EN=0;
     write_com(0x38);    //顯示模式設置
     write_com(0x0c);    //開顯示 不顯示光標 不閃
     write_com(0x06); //寫一個字符 地址指針 光標 加一 整屏不移動
     write_com(0x01);    //顯示清零

     write_com(0x80+0x04);
     write_data('2');     
     write_com(0x80+0x05);
     write_data('0');     
     write_com(0x80+0x00);
     write_data('c');     
     write_com(0x80+0x01);
     write_data('a');
     write_com(0x80+0x02);
     write_data('i');      
     write_com(0x80+0x4e);
     write_data(0xdf);    
     write_com(0x80+0x4f);
     write_data('C');     
     write_com(0x80+0x4b);
     write_data(0x2e);       //顯示"。"
    }
     
    /**************DS18B20****************/

    void delay1(unsigned int t) //延時函數
    {
     while(t--);
    }

    void init1()  //初始化
    {
     uchar n=0;
     DQ=1;      //DQ復位
     delay1(8);  
     DQ=0;      //主機將DQ拉低
     delay1(80);     //大于480us的延時
     DQ=1;
     delay1(5);    //延時15~60us
     n=DQ;
     delay1(5);   //若n=0初始成功 n=1初始失?。稍O置返回值查看n是否為1) 
    }
     
    void write_byte(uchar dat)    //寫入一個字節
    {
     uint i;
     for(i=0;i<8;i++)
     {
      DQ=0;
      DQ=dat&0x01;
      delay1(12);
      DQ=1;
      dat>>=1;
     }
     delay1(4);
    }

    uchar read_byte()    //讀入一個字節
    {
     uint k=0;
     uchar value=0;
     for(k=0;k<8;k++)
     {
      DQ=0;
      value>>=1;
      DQ=1;
      if(DQ)
      value|=0x80;
      delay1(4);
     } 
     return value; 
    }

    uchar read_temp()    //讀取溫度函數
    {
     uchar a=0,b=0;
     init1();
     write_byte(0xcc);
     write_byte(0x44);
     delay1(200);

     init1();
     write_byte(0xcc);
     write_byte(0xbe);
     a=read_byte();  
     b=read_byte();
     c=b;
     d=a;
     b<<=4;
     b+=(a&0xf0)>>4; 
     return b;
    }

    /***********************1302**********************/

    void wirte_byte1(uchar date)    //寫入一個字節
    {
     uchar i;
     for(i=8;i>0;i--)
     {
      IO=date&0x01;
      SCLK=0;
      SCLK=1;
      date=date>>1;
       }
    }

    uchar read_byte1()       //讀一個字節
    {
     uchar dat,i;
     for(i=8;i>0;i--)
     {
      dat=dat>>1;
      SCLK=0;
      if(IO)
      dat=dat|0x80;
      SCLK=1;
     }
     return(dat);
    }

    void write_ds1302(uchar add,uchar date)     //將數據寫入1302中
    {
     RST=0;
     SCLK=0;
     RST=1;
     wirte_byte1(add);
     wirte_byte1(date);
     RST=0;
     SCLK=1;
    }

    uchar read_ds1302(uchar add)  //讀出1302中數據
    {
     uchar temp;
     RST=0;
     SCLK=0;
     RST=1;
     wirte_byte1(add);
     temp=read_byte1();
     RST=0;
     SCLK=0;
     return (temp);
    }

    uchar huan_BCD(uint z)   //將數據 轉換成BCD
    {
     uint a,b;
      a=z/10;
      b=z;
      a=a&0xff;
      b=b&0xff;
      a<<=4;
      a=a|b;
     return (a);
    }

    void xian_shi()       //液晶顯示函數
    {
     if(b==0&a==0)
     { 
      ms=time[0]/16;
      mg=time[0];

      fs=time[1]/16;
      fg=time[1];
      fen=fs*10+fg;
     
      ss=time[2]/16;
      sg=time[2];
      shi=ss*10+sg;

      rs=time[3]/16;
      rg=time[3];
      ri=rs*10+rg;

      ys=time[4]/16;
      yg=time[4];
      yue=ys*10+yg;

      ns=time[6]/16;
      ng=time[6];
      nian=ns*10+ng;

      xing=time[5]; 
     }
     if(a==1|b==1)
     {
      ss=shi/10;
      sg=shi;

      write_com(0x80+0x41);
      write_data(0xff);

      write_com(0x80+0x40);    
      write_data(table[ss]);
      write_com(0x80+0x41);    
      write_data(table[sg]);

     }
     if(a==2|b==2)
        { 
      fs=fen/10;
      fg=fen;

      write_com(0x80+0x44);
      write_data(0xff);

      write_com(0x80+0x43);    
      write_data(table[fs]);
      write_com(0x80+0x44);    
      write_data(table[fg]);
     }

     if(a==3)
        { 
      rs=ri/10;
      rg=ri;

      write_com(0x80+0x0d);
      write_data(0xff);

      write_com(0x80+0x0c);    
      write_data(table[rs]);
      write_com(0x80+0x0d);    
      write_data(table[rg]);
     }
     if(a==4)
        { 
      ys=yue/10;
      yg=yue;

      write_com(0x80+0x0a);
      write_data(0xff);

      write_com(0x80+0x09);    
      write_data(table[ys]);
      write_com(0x80+0x0a);    
      write_data(table[yg]);
     }
     if(a==5)
        { 
      ns=nian/10;
      ng=nian;

      write_com(0x80+0x07);
      write_data(0xff);

      write_com(0x80+0x06);    
      write_data(table[ns]);
      write_com(0x80+0x07);    
      write_data(table[ng]);
     }
     if(a==6)
        { 
      write_com(0x80+0x0f);
      write_data(0xff);
      write_com(0x80+0x0f);    
      write_data(table[xing]);
     }
      write_com(0x80+0x06); //在液晶第一行第七八位顯示  年   
      write_data(table[ns]);
      write_com(0x80+0x07);    
      write_data(table[ng]);

      write_com(0x80+0x08);    
      write_data('-');

      write_com(0x80+0x09); //在液晶第一行第十十一位顯示  月   
      write_data(table[ys]);
      write_com(0x80+0x0a);    
      write_data(table[yg]);

      write_com(0x80+0x0b);    
      write_data('-');

      write_com(0x80+0x0c); //在液晶第一行第十三 十四位顯示  日   
      write_data(table[rs]);
      write_com(0x80+0x0d);    
      write_data(table[rg]);

      write_com(0x80+0x0f);   //在液晶第一行第十七位顯示  星期 
      write_data(table[xing]);

      write_com(0x80+0x40);   //在液晶第二行第二三位顯示    時 
      write_data(table[ss]);
      write_com(0x80+0x41);    
      write_data(table[sg]);

      write_com(0x80+0x42);    
      write_data(':');

      write_com(0x80+0x43);   //在液晶第二行第五六位顯示  分 
      write_data(table[fs]);
      write_com(0x80+0x44);    
      write_data(table[fg]);

      write_com(0x80+0x45);    
      write_data(':');

      write_com(0x80+0x46);   //在液晶第二行第八九位顯示  秒 
      write_data(table[ms]);
      write_com(0x80+0x47);    
      write_data(table[mg]);
    }

    void keyscan()    //按鍵設置函數  可任意設置年月日時分秒星期的數值
    {
     if(key4!=0)
     {
      if(key1==0)   //key1按鍵 選擇需設置的位
      {
       if(key1==0)
       { 
        a++;
        delay(1);
       }
             while(!key1)
       {      
        delay(1);
       }       
      }
     
      if(a!=0)
      {
       if(key2==0)    //key2按鍵 可將需設置的數 調大
       {
        if(a==1)
        {
         shi++;
         if(shi>=24)
         {
          shi=0;
         }
        }
        if(a==2)
        {
         fen++;
         if(fen>=60)
         {
          fen=0;
         }
        }
        if(a==3)
        {
         ri++;
         if(ri>=32)
         {
          ri=1;
         }
        }
        if(a==4)
        {
         yue++;
         if(yue>=12)
         {
          yue=1;
         }
        }
        if(a==5)
        {
         nian++;
         if(nian>=99)
         {
          nian=0;
         }
        }
        if(a==6)
        {
         xing++;
         if(xing>=8)
         {
          xing=1;
         }
        }
       }
       if(key3==0)    //key3按鍵 可將需設置的數 調小
       {
       
        if(a==1)
        {
         shi--;
         if(shi<0)
         {
          shi=23;
         }
        }
        if(a==2)
        {
         fen--;
         if(fen<0)
         {
          fen=59;
         }
        }
        if(a==3)
        {
         ri--;
         if(ri<1)
         {
          ri=31;
         }
        }
        if(a==4)
        {
         yue--;
         if(yue<1)
         {
          yue=12;
         }
        }
        if(a==5)
        {
         nian--;
         if(nian<0)
         {
          nian=99;
         }
        }
        if(a==6)
        {
         xing--;
         if(xing<1)
         {
          xing=7;
         }
        } 
       } 
       if(a==7)       //當按下key1 7次后  將個數據寫入1302 
       {
        a=0;
        write_ds1302(0x8e,0x00);   //WP=0 寫操作
        write_ds1302(0x80,0x00);   //0x80是寫秒數據 
        write_ds1302(0x82,huan_BCD(fen)); //0x82是寫分數據 
        write_ds1302(0x84,huan_BCD(shi)); //0x84是寫時數據
        write_ds1302(0x86,huan_BCD(ri)); //0x84是寫日數據
        write_ds1302(0x88,huan_BCD(yue)); //0x84是寫月數據
        write_ds1302(0x8a,huan_BCD(xing)); //0x84是寫星期數據
        write_ds1302(0x8c,huan_BCD(nian)); //0x84是寫年數據
        write_ds1302(0x8e,0x80);   //WP=1 寫保護    
       }
      }
     }
    }

    void naozhong()      //通過按鍵設置鬧鐘  時 分
    {
     if(key1!=0)
     {
      if(key4==0)
      {
       if(key4==0)
       { 
        b++;
        delay(1);
       }
             while(!key4)
       {      
        delay(1);
       }
      }
      if(b!=0)
      {
       if(key2==0)    //key2按鍵 可將需設置的數 調大
       {
        if(b==1)
        {
         shi++;
         if(shi>=24)
         {
          shi=0;
         }
        }
        if(b==2)
        {
         fen++;
         if(fen>=60)
         {
          fen=0;
         }
        }
       }
       if(key3==0)    //key3按鍵 可將需設置的數 調小
       {
        if(b==1)
        {
         shi--;
         if(shi<0)
         {
          shi=23;
         }
        }
        if(b==2)
        {
         fen--;
         if(fen<0)
         {
          fen=59;
         }
        }
       }
       aa=huan_BCD(shi);   //將設置的時鐘 賦值給aa
       bb=huan_BCD(fen); //將設置的分鐘 賦值給bb
       if(b==3)       //當按下key4 3次后 鬧鐘設置完成 
       {
        b=0;
       }
      }
     }
    }

    void main()
    {
     uint i,temp;
     init();
     TMOD=0x10;
     EA=1;
     TH1=(65536-51200)/256;
     TL1=(65536-51200)%256;
     ET1=1;
     while(1)
     {
      temp=0x81;          //讀的初始地址                   
            for(i=0;i<7;i++)             //分別把秒分時日月年星期數據讀出分7次讀好一次地址加2" temp+=2;"
          {
             time[i]=read_ds1302(temp);
          temp+=2;
            }
      if(bb==time[1]&aa==time[2]&!time[0])  //如果讀出來的時鐘 分鐘與1302讀出來的值相等且讀出來的秒鐘為零時 進入中斷
      {
       TR1=1;
       flag=1;   //標志位設置為1
      }
      if(key3==0)   //進入鬧鐘后 可由key3按下 停止中斷 標志位置零 允許調時鬧鐘設置按鍵動作 停止鬧鈴
      {
       led=1;
       spk=1;
       flag=0;
       TR1=0;
      }
            if(flag!=1)   //當進入鬧鐘中斷后 調時與設置鬧鐘的按鍵  無效
         {
             naozhong();
       keyscan();
      }
      xian_shi();
      temp=read_temp();
      write_com(0x80+0x49);    
      write_data(table[temp/10]);    //在液晶第二行第十位顯示溫度的十位
      write_com(0x80+0x4a);  
      write_data(table[temp]);    //在液晶第二行第十一位顯示溫度的個位
      write_com(0x80+0x4c);    
      write_data(table[(d&0x0f)*625/1000]);   //在液晶第二行第十三位顯示溫度的小數點后一位
      write_com(0x80+0x4d);    
      write_data(table[(d&0x0f)*625/100]);   //在液晶第二行第十四位顯示溫度的小數點后二位 
     }
    }


    void timer1() interrupt 3     //定時器 
    {
     uint t;
     TH1=(65536-50000)/256;
     TL1=(65536-50000)%256;
     t++;
     spk=0;      //蜂鳴器  發出 滴答 聲
     led=!led;      //發光二極管  不停閃爍
     delay1(10);
     if(t==1120)    //約1分鐘后 鬧鐘自動停止 標志位
     {
      led=1;
      spk=1;
      t=0;
      TR1=0;
      flag=0;
     }

    }

    黑人粗大无码AV人妻一区