i黑马网:89s52+ds1302电子钟

来源:百度文库 编辑:中财网 时间:2024/03/29 06:54:21
89s52+ds1302电子钟

/*===================================
/--------------------------------------
项目名称:89s52+ds1302电子钟
功能说明:6位数码管显示-时--分--秒,约30秒钟。然后显示星期--月--年约10秒钟
设置说明:
         P0--段,P2--位(p2.5为个位),自带充电功能(470UF电容作为电源)

作者:朱世民
说明:通过实验板验证通过
时间:2010.2.11
==========================================*/
#include "reg51.h"
#include "ds1302.h" //自建库文件


//unsigned char code tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
//                         0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
                                 //0~~9段码   abcdefgh,共阳
unsigned char code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
                          0x7F,0x6F,0x77,0x7C,0x39,0x80,0x79,0xC0};
//                          师大版显示代码
/*************************ds1302与at89s52引脚连接********************/

                        

sbit k1=P1^0;   //调时分秒按键(移位)
sbit k2=P1^1;   //加1按键
sbit k3=P1^3;   //调星期,月,日,按键(移位)
sbit k4=P1^4;   //加1按键
sbit flag=P3^1; //秒显标志(板上接p3.1)
unsigned char k,ks;
unsigned char time[6]; //秒,分,时寄存器初始值
/***********************显示程序**********************************************/
/* 动态扫描条件(单个LED在1秒内): count >=50次   //点亮次数               */
/*                                                  */
/* DS1302秒,分,时寄存器是BCD码形式: 用16求商和余进行"高4位"和"低4位"分离 */
/* 0xdf,0xef,0xf7,0xfb,0xfd,0xfe    :   位选                                 */
/****************************************************************************/          
void disp()//
{ unsigned char m; //m为缓冲;

   m=time[0];    //把
   P0=tab[m%16];                    //取秒低4位BCD码
   P2=0xdf;                       //显示秒(个位);
   delay(500);                             //持续2ms
   P2=0xff;                              //消影
  
  
   P0=tab[m/16];               //取高4位BCD码:显示秒(十位);
   P2=0xef;
   delay(500);
   P2=0xff;

   m=time[1]; //把分--送缓存

   P0=tab[m%16];           //第3个数码管:显示分(个位)
   P2=0xf7;
   delay(500);
   P2=0xff;

   P0=tab[m/16];            //第4个数码管:显示分(十位)
   P2=0xfb;
   delay(500);
   P2=0xff;

   m=time[2]; //把时--送缓存
   P0=tab[m%16];             //第5个数码管:显示时(个位)
   P2=0xfd;
   delay(500);
   P2=0xff;
  

   P0=tab[m/16];             //第6个数码管:显示时(十位)
   P2=0xfe;
   delay(500);
   P2=0xff;
}
//==============
//显示星期---月---日
void disp2()
{ unsigned char m; //m为缓冲;

   m=time[3];    //把日
   P0=tab[m%16];                    //取秒低4位BCD码
   P2=0xdf;                       //显示秒(个位);
   delay(500);                             //持续2ms
   P2=0xff;                              //消影
  
  
   P0=tab[m/16];               //取高4位BCD码:显示秒(十位);
   P2=0xef;
   delay(500);
   P2=0xff;

   m=time[4];   //把月--送缓存

   P0=tab[m%16];           //第3个数码管:显示分(个位)
   P2=0xf7;
   delay(500);
   P2=0xff;
  
   m=m/16;
   if(m==0) m=13;//若十位为0,关闭显示 0x80
   P0=tab[m];            //第4个数码管:显示分(十位)
   P2=0xfb;
   delay(500);
   P2=0xff;

   m=time[5]; //把星期--送缓存
   P0=tab[15];             //第5个数码管:显示时(个位)
   P2=0xfd;
   delay(500);
   P2=0xff;
  

   P0=tab[m%16];             //第6个数码管:显示时(十位)
   P2=0xfe;
   delay(500);
   P2=0xff;
}
//========初始化
void Write_time()
{ unsigned char i,addr;                     
    addr=0x80;         
   write_1302(0x8e,0x00);         //WP=0 写操作
    for(i=0;i<6;i++)
    {
    write_1302(addr,time[i]);
    addr+=2;
    }
   write_1302(0x8e,0x80);        //WP=1 写保护
}
//===================================
void testk1()
{k1=1;
if(!k1)//
{disp();//延时去抖
   if(!k1)//
    {while(!k1)disp();//等待松开
    if(++k>6)k=0; //移位标志,只调
    }
}

}

//=======加一键=================
void testk2()
{ unsigned char n,buf;
k2=1;
if(!k2)
{disp();disp();disp();
if(!k2)
do //按键没有松开,连续加
    {disp();disp();disp();
       switch(k)
     {case 6:buf=time[0];//
                 buf&=0xf0; //保留高四位;
               if(++n>9)n=0; //加数
               time[0]=buf|n;break;//秒的个wei加一
      case 5:buf=time[0]; buf&=0x0f; if(++n>5)n=0; time[0]=buf+n*16;break;//分的十位加1
         
          case 4:buf=time[1]; buf&=0xf0; if(++n>9)n=0; time[1]=buf|n;break;//分的个wei加一
      case 3:buf=time[1]; buf&=0x0f; if(++n>5)n=0; time[1]=buf+n*16;break;//分的十位加1
        
          case 2:buf=time[2];buf&=0xf0; if(++n>9)n=0; time[2]=buf|n;break;//时的个位加一
      case 1:buf=time[2];buf&=0x0f; if(++n>2)n=0; time[2]=buf+n*16; break;//

                               //时十位加1
      default:break;
     }
       disp();disp();disp();
      }
    while(!k2);//直到按键松开
    Write_time(); //写进1302去
}
}

//==========
void testk3()
{k3=1;
if(!k3)//
{disp2();//延时去抖
   if(!k3)//
    {while(!k3)disp2();//等待松开
    if(++ks>5)ks=0; //移位标志,只调
    }
}

}

//=======加一键=================
void testk4()
{ unsigned char n,buf;
k4=1;
if(!k4)
{disp2();disp2();
if(!k4)
do //按键没有松开,连续加
    {disp2();disp2();disp2();
       switch(ks)
     {case 5:buf=time[3];//
                 buf&=0xf0; //保留高四位;
               if(++n>9)n=0; //加数
               time[3]=buf|n;break;//秒的个wei加一
      case 4:buf=time[3]; buf&=0x0f; if(++n>3)n=0; time[3]=buf+n*16;break;//分的十位加1
         
          case 3:buf=time[4]; buf&=0xf0; if(++n>9)n=0; time[4]=buf|n;break;//分的个wei加一
      case 2:buf=time[4]; buf&=0x0f; if(++n>1)n=0; time[4]=buf+n*16;break;//分的十位加1
        
          case 1:buf=time[5];buf&=0xf0; if(++n>7)n=1; time[5]=buf|n;break;//时的个位加一
    

                               //时十位加1
      default:break;
     }
       disp2();disp2();
      }
    while(!k4);//直到按键松开
    Write_time(); //写进1302去
}
}

/************************主程序**********************************************/
void main(void)
{ unsigned char i,addr,s,n;
   k=0,ks=0;                            
     write_1302(0x8e,0x00);         //WP=0 写操作
    write_1302(0x90,0xa5);         // 开涓流充电
      write_1302(0x8e,0x80);        //WP=1 写保护

      write_1302(0x80,0x00);

     while(1)
    {
        testk1(); //调时移位键k=1,2,3,4分别分个、十,时个,十
        while(k!=0)   //若进入调节
            { testk2();disp();testk1(); }//调时间
      
    {    //否则取数,显示                
        for(n=0;n<100;n++)
          { addr=0x81;
             for(i=0;i<3;i++)
         {
         time[i]=read_1302(addr);// 读出时间
               disp();   //星期,月,日
                 addr+=2;//地址加2
               }  
              if(time[0]!=s) // 读出秒,和上次比较不等
                 {flag=!flag;//秒闪指示(变化一次闪一次)
                s=time[0]; // 将秒的值送入缓存,以便下次比较,取出跳变
                 }
    }
    }

       testk3(); //调时移位键k=1,2,3,4分别调节星期,月,日
       while(ks!=0)   //若进入调节星期,月,日
        { testk4();disp2();testk3(); }//进入调节
       
         { addr=0x87;
           for(i=3;i<6;i++)
         {
        time[i]=read_1302(addr);// 读出星期,月,日
              addr+=2;//地址加2
               }
          for(n=0;n<80;n++) disp2();//显示星期,月,日
     
     }
     }
}