返回主页  单片机教程 XL2000开发板  单片机学习  自制编程器 单片机资料  电子技术 产品介绍  如何购买  进入论坛

学林杯第二届单片机征文大赛公开评奖稿件 深圳学林电子www.51c51.com 版权所有 转载注明出处   请不要忘了:现在为你喜欢的稿件投票!
作品1:征文-我是怎样开始学习电子的 山西省大同市作品6:多功能自行车测速仪  北京大学      崔健
作品2:数字温度计的设计  杭州电子科技大学      陈智杰作品7:带闹钟智能电子钟 深圳市天安数码城      谢玉平 
作品3:如何使自制的单片机电子钟走时精准      舒新生作品8:电话回拨服务告知装置 武汉市桥口区      詹显德
作品4:宽带数控放大器 陕西省西安通信学院     韩宏伟作品9:单片机应用之摩斯密码电子锁广东省顺德    吴志光
作品5:一些事,一些情  韶关市      冯敬锋作品10:基于aduc842瞬态波形存储器 华中师范大学物理学院     杨程泽
作品11:基于AT89S52单片机的毫欧表电路设计中南林业科技大学涉外学院     郭海

作品1:字符型液晶显示模块        邓杰   作品6:基于89C51的智能转速计   淮安信息学院     宋炎
作品2:8X8LED点阵屏循环显示作品7:用虚拟IIC总线实现24C02 的应用  南阳理工学院     张全领
作品3:虚拟仿真仪器UMPS的应用     牛余朋作品8:语音编程、远程控制试验板      社区乞丐
作品4:万年历数字钟及可调时钟系统作品9:定时开关控制器的制作      魏军丞
作品5:点矩阵显示器的应用会员lfgbody     林发根作品10:AD080951单片机中的应用      文/黄海

万年历数字钟及可调时钟系统

 

一、    引言

万年历数字钟是一种用万年历时钟芯片实现年、月、日、时、分、秒计时,并通过单片机处理后送给显示芯片显示的装置,与机械式时钟相比具有更高的准确性和直观性,且具有更长的使用寿命。本系统还可以扩展为可调的自动开关,对家电对用电设备进行控制,笔者在随后改制成为可调时的自动断电的供电系统.

二、    原理图设计

1.  单片机及其外围电路设计

复位采用X25045芯片,复位电路如图1所示。

1  复位电路设计

 

单片机采用贴片封装的AT89S51,晶振为11.0592MHz。其中P1.5~P1.7为下载程序使用,电路如图2所示。

2  单片机89S51外围电路设计

 

2.  时钟芯片电路设计

时钟芯片采用PCF8563,晶振采用32.768K,电容使用15pfPCF8563 PHILIPS 公司推出的一款工业级内含I2C 总线接口功能的具有极低功耗的多功能时钟/日历芯片。内部时钟电路、内部振荡电路、内部低电压检测电路(1.0V以及两线制I2C 总线通讯方式,不但使外围电路及其简洁,而且也增加了芯片的可靠性。同时每次读写数据后,内嵌的字地址寄存器会自动产生增量。电路如图3所示。

3  时钟芯片电路设计

 


3.  显示芯片电路设计

显示芯片采用ZLG7289,晶振为12MHzZLG7289A 是广州周立功单片机发展有限公司自行设计的,具有SPI 串行接口功能的可同时驱动8 位共阴式数码管(或64 只独立LED )的智能显示驱动芯片,该芯片同时还可连接多达64 键的键盘矩阵,单片即可完成LED 显示﹑键盘接口的全部功能。电路如图4所示。

4  显示芯片电路设计

4.  双电源电路设计

系统采用双电源,平时使用V110V的外接电源,停电时使用电池,由V2输入。电池有6节,其电压为9V。当电池电压低于6V时,LED亮,说明电池电量不足。电路如图5所示。

5  双电源电路设计


三、    程序设计

程序开始时先对系统初始化,并设置好各种中断。下步操作主要是对时钟芯片进行操作,首先要给时钟芯片设置初值,时钟芯片便自行计数。此时检测是否有按键按下,按键是为了调整时钟。有按键按下则执行按键中断程序,没有按键按下则执行下一步的操作,即取时钟芯片中的时钟值,然后送显示。程序流程图如下。

6  总体流程图

 

四、          源程序

#include  <reg51.h>

#include  <intrins.h>

#include  <math.h>

 

#define  uchar unsigned char /*宏定义*/

#define  uint  unsigned int

uchar  close_date,open_date;

void  RESWDI(void);

void  WREN(void);

void  WRDI(void);

void  WRSR(void);

unsigned char RSDR(void);

void WIPCHK(void);

void OUTByte(unsigned char Byte);

unsigned char INPUTByte(void);

unsigned char ReadByte(unsigned char ADD);

void WriteByte(unsigned char Byte,ADD);

#define  _Nop()  _nop_()       

 

 

 

sbit  zlg7289_cs     =P1^1;

sbit  zlg7289_clk    =P2^6;

sbit  zlg7289_dio    =P2^7;

sbit  zlg7289_key   =P3^2;

sbit    p07=P0^7;

sbit    p06=P0^6;

sbit    CS=P2^4;

sbit    SCK=P2^2;

sbit    SO=P2^5;

sbit    SI=P2^3;

sbit    p10=P1^0;

 

sbit        SDA=P1^2;            /*模拟I2C数据传送位*/

sbit        SCL=P1^3;            /*模拟I2C时钟控制位*/

 

 

 

uchar            buf[9]={0x00,0x00,0x30,0x23,0x15,0x1,0x05,0x04,0x05};

uchar   bufdata,bb,date;

uchar     SLA=0xA2,SUBA=0x00;

uchar      *p;         

 

uchar keychange=0;

uchar key=0;         /*键盘值*/

bit keyint=0;          /*按键中断标志*/

bit keyok=1;          /*数据是否修改好*/

uchar num=0; /*移位键移到哪个LED*/

 

 

 

void delay(uchar i)

{

       while(i--);

}

 

//******************** TIMER1 interrupt  process ***************************//

 timer0 (void) interrupt 1  using 1

{

   TH0=0x3c;

   TL0=0xb0;

 

   RESWDI();

 

}

 

 

void RESWDI(void) ////复位看门狗(喂狗)

{

zlg7289_cs=1;

CS =1;

CS =0;

CS =1;

zlg7289_cs=1;

}

 

void WREN(void) //写使能复位使用)?

 

{

zlg7289_cs=1;

SCK=0;

CS=0;

OUTByte(0x06); //发送06H写使能命令字

SCK=0;

CS=1;

zlg7289_cs=1;

}

 

 

 

void WRDI(void) //写使能复位(禁止写{

{

zlg7289_cs=1;

SCK=0;

CS=0;

OUTByte(0x04); //发送04H写禁止命令字SCK=0;

CS=1;

zlg7289_cs=1;

}

 

 

 

void WRSR(void) //写状态寄存器

{

WREN();

zlg7289_cs=1;

SCK=0;

CS=0;

OUTByte(0x01); //发送01H写寄存器命令字

OUTByte(0x00); //发送寄存器值BL0,BL10没写保护,WD0=0 W01=1

//WD1=0WD1=0看门狗复位时间1.4S

SCK=0;

CS=1;

zlg7289_cs=1;

WIPCHK(); //判断是否写入

}

 

 

 

unsigned char RSDR(void) //读状态寄存器

{

unsigned char Temp;

zlg7289_cs=1;

SCK=0;

CS=0;

OUTByte(0x05); //发送05H读状态寄存器命令字

Temp =INPUTByte(); //读状态寄存器值

SCK=0;

CS=1;

return Temp;;//这一个调试时没有执行,Temp的值总是0xFF;???????????

zlg7289_cs=1;

}

 

 

 

void WIPCHK(void) //检查WIP位,判断是否写入完成

 

{

unsigned char Temp,TempCyc;

for(TempCyc=0;TempCyc<50;TempCyc++)

{

Temp =RSDR(); //读状态寄存器

if (Temp&0x01==0)

TempCyc =50;

}

}

 

 

//单字节指令或数据写入X25045

//SI线上输入的数据在SCK的上升沿被锁存。

 

void OUTByte(unsigned char Byte) //输出一个定节

{

unsigned char TempCyc;

zlg7289_cs=1;

for(TempCyc=0;TempCyc<8;TempCyc++)

{

  SCK =0;

  if(Byte&0x80)

     SI =1;

   else

     SI =0;

  SCK =1;

  Byte =Byte<<1; //右移

 }

SI=0; //使SI处于确定的状态

zlg7289_cs=1;

}

 

 

//单字节数据从X25045读到单片机

//数据由SCK的下降沿输出到SO线上。

unsigned char INPUTByte(void) //输入一个字节

{

unsigned char Temp=0, TempCyc;

 

 

zlg7289_cs=1;

for(TempCyc=0;TempCyc<8;TempCyc++)

{

Temp =Temp<<1; //右移

SCK =1;

SCK=0;

if (SO)

Temp =Temp|0x01; //SO1,则最低位为1

 else

Temp&=0xFE;

}

return Temp;;//这一个调试时没有执行,Temp的值总是0

zlg7289_cs=1;

}

 

 

 

unsigned char ReadByte(unsigned char ADD) //读地址中的数据这里不做先导字处理,只能读00-FFH

 

{

unsigned char Temp;

zlg7289_cs=1;

SCK=0;

CS=0;

SO=1;

SI=1;

OUTByte(0x3); //发送读指令03H 如要支持000-FFF则要把高位地址左移3位再为03H相或

OUTByte(ADD); //发送低位地址

Temp =INPUTByte();

SCK=0;

CS=1;

return Temp;//这一个调试时没有执行,Temp

zlg7289_cs=1;

}

 

 

 

void WriteByte(unsigned char Byte,ADD) //向地址写入数据这里同样不做先导字处理,只能写00-FFH

{

WREN();

zlg7289_cs=1;

SCK=0;

CS=0;

SO=1;

SI=1;

OUTByte(0x2); //发送写指令02H 如要支持000-FFF则要把高位地址左移2位再为02H相或

OUTByte(ADD); //发送低位地址

OUTByte(Byte); //发送数据

SCK=0;

CS=1;

WIPCHK();

zlg7289_cs=1;

}

 

 

 

 

/********************************************************************

***************模拟I2C总线传输程序***********************************

********************************************************************/

bit   ack;          /*应答标志位*/

 

/*******************************************************************

                     起动总线函数             

********************************************************************/

void Start_I2c()

{

      SDA=1;   /*发送起始条件的数据信号*/

      _Nop();

      SCL=1;

      _Nop();    /*起始条件建立时间大于4.7us,延时*/

      _Nop();

      _Nop();

      _Nop();

      _Nop();   

      SDA=0;   /*发送起始信号*/

      _Nop();    /* 起始条件锁定时间大于4μs*/

      _Nop();

      _Nop();

      _Nop();

      _Nop();      

      SCL=0;   /*钳住I2C总线,准备发送或接收数据*/

      _Nop();

      _Nop();

}

 

/*******************************************************************

                      结束总线函数              

********************************************************************/

void Stop_I2c()

{

      SDA=0;  /*发送结束条件的数据信号*/

      _Nop();   /*发送结束条件的时钟信号*/

      SCL=1;  /*结束条件建立时间大于4μs*/

      _Nop();

      _Nop();

      _Nop();

      _Nop();

      _Nop();

      SDA=1;  /*发送I2C总线结束信号*/

      _Nop();

      _Nop();

      _Nop();

      _Nop();

}

 

/*******************************************************************

                 字节数据传送函数              

********************************************************************/

void  SendByte(uchar c)

{

      uchar BitCnt;

 

      for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8*/

    {

          if((c<<BitCnt)&0x80)SDA=1;  

         else  SDA=0;               

          _Nop();

          SCL=1;               /*置时钟线为高,通知被控器开始接收数据位*/

          _Nop();

          _Nop();               /*保证时钟高电平周期大于4μs*/

          _Nop();

          _Nop();

          _Nop();        

          SCL=0;

    }

   

    _Nop();

    _Nop();

    SDA=1;               /*8位发送完后释放数据线,准备接收应答位*/

    _Nop();

    _Nop();  

    SCL=1;

    _Nop();

    _Nop();

    _Nop();

    if(SDA==1)ack=0;    

       else ack=1;        /*判断是否接收到应答信号*/

    SCL=0;

    _Nop();

    _Nop();

}

 

 

/*******************************************************************

                 字节数据接收函数              

********************************************************************/     

uchar  RcvByte()

{

      uchar retc;

      uchar BitCnt;

 

      retc=0;

      SDA=1;             /*置数据线为输入方式*/

      for(BitCnt=0;BitCnt<8;BitCnt++)

    {

        _Nop();          

        SCL=0;       /*置时钟线为低,准备接收数据位*/

        _Nop();

        _Nop();         /*时钟低电平周期大于4.7s*/

        _Nop();

        _Nop();

        _Nop();

        SCL=1;       /*置时钟线为高使数据线上数据有效*/

        _Nop();

        _Nop();

        retc=retc<<1;

        if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc */

        _Nop();

        _Nop();

    }

      SCL=0;   

      _Nop();

      _Nop();

      return(retc);

}

 

/********************************************************************

                     应答子函数

********************************************************************/

void Ack_I2c(bit a)

{

 

      if(a==0)SDA=0;     /*在此发出应答或非应答信号*/

        else SDA=1;

      _Nop();

      _Nop();

      _Nop();     

      SCL=1;

    _Nop();

    _Nop();              /*时钟低电平周期大于4μs*/

    _Nop();

    _Nop();

    _Nop(); 

      SCL=0;                /*清时钟线,钳住I2C总线以便继续接收*/

    _Nop();

    _Nop();   

}

 

/*******************************************************************

                    向有子地址器件发送多字节数据函数              

********************************************************************/

bit ISendStr(uchar sla,uchar suba,uchar *s)

{

     uchar i;

 

     Start_I2c();               /*启动总线*/

     SendByte(sla);            /*发送器件地址*/

    if(ack==0)return(0);

     SendByte(suba);            /*发送器件子地址*/

    if(ack==0)return(0);

 

     for(i=0;i<9;i++)

    {  

          SendByte(*s);               /*发送数据*/

         if(ack==0)return(0);

          s++;

    }

    Stop_I2c();                 /*结束总线*/

    return(1);

}

 

/*******************************************************************

                    向有子地址器件读取多字节数据函数              

********************************************************************/

bit IRcvStr(uchar sla,uchar suba,uchar *s)

{

     uchar i;

 

     Start_I2c();               /*启动总线*/

     SendByte(sla);            /*发送器件地址*/

     if(ack==0)return(0);

     SendByte(suba);            /*发送器件子地址*/

     if(ack==0)return(0);

 

     Start_I2c();

     SendByte(sla+1);

      if(ack==0)return(0);

 

     for(i=0;i<8;i++)

    {  

     *s=RcvByte();               /*发送数据*/

      Ack_I2c(0);                /*发送就答位*/ 

     s++;

    }

      *s=RcvByte();

    Ack_I2c(1);                 /*发送非应位*/

      Stop_I2c();                   

      return(1);

}

 

/**********模拟I2C程序结束***************************/

 

void display(uint dis)

{

       uchar j;

       zlg7289_clk=0;

       delay(20);

      zlg7289_cs=0;

      for(j=0;j<16;j++)

      {

             if((dis&0x8000)==0x8000) zlg7289_dio=1;

             else zlg7289_dio=0;

            delay(20);

            zlg7289_clk=1;

            delay(10);

            zlg7289_clk=0;

            delay(10);

             dis=dis<<1;

      }

      zlg7289_cs=1;

      delay(20);

}

 

void dis_play(uchar aa)

{

       uchar i;

       for(i=0;i<8;i++)

       {

              if(_crol_(aa,i)&0x80)

                     zlg7289_dio =1;

              else

                     zlg7289_dio =0;

              zlg7289_clk =1;

              delay(10);             

              zlg7289_clk =0;

       }

}

void displaymonth()

{

       bufdata=buf[5]&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xc8);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

 

       bufdata=buf[5]&0x30;

       bufdata=bufdata>>4;

       bufdata=bufdata&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xc9);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

 

       bufdata=buf[7]&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xca);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

 

       bufdata=buf[7]&0x10;

       bufdata=bufdata>>4;

       bufdata=bufdata&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xcf);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

}

void displaytime()

{

       bufdata=buf[3]&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xce);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

      

       bufdata=buf[3]&0x70;

       bufdata=bufdata>>4;

       bufdata=bufdata&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xcd);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

      

       bufdata=buf[4]&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xcc);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

      

       bufdata=buf[4]&0x30;

       bufdata=bufdata>>4;

       bufdata=bufdata&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xcb);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

}

 

void display_x5045()

{

    date=ReadByte(0x40);

       close_date=date;

       bufdata=date&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xce);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

      

       bufdata=date&0x70;

       bufdata=bufdata>>4;

       bufdata=bufdata&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xcd);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

       date=ReadByte(0x42);

       bufdata=date&0x0f;

       zlg7289_cs=0;

       open_date=ReadByte(0x42);

       delay(10);

       dis_play(0xcc);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

      

       bufdata=date&0x30;

       bufdata=bufdata>>4;

       bufdata=bufdata&0x0f;

       zlg7289_cs=0;

       delay(10);

       dis_play(0xcb);

       delay(10);

       dis_play(bufdata);         

       zlg7289_cs=1;

       delay(70);

}

/****************按键处理程序*********************/

//key=47: 闪烁移位键(shift)

//key=39: +

//key=39: -

//key=31: 确认键(ok)

void key_int() interrupt 0     

{

       keyint=1;

}

void keyexe()

{

 

       uchar i;

       uchar temp=0;

       uchar aa;

       p06=1;

       EX0=1;

       zlg7289_cs =0;

       delay(10);

       dis_play(0x15);            /*写入读键盘数据指令*/

       delay(10);

       for(i=0;i<8;i++)

       {

              temp=temp<<1;

              aa=zlg7289_dio; // 按位或

              if(aa==1) // 读数据位,接收的数据位放入retc

              temp=temp+1;

              zlg7289_clk=1;

              delay(10); // 延时

              zlg7289_clk=0;

       }

       zlg7289_cs=1;

       key=temp;

 

       if(key==47)    //闪烁移位键

       {

              key=0;

              keyok=0;

           EX0=0;

              if(num==8)    

                     {

                        num=1;

                  }

              else

                     num++;

              switch(num)

              {     case 1:    {display(0x88fe);}break;

                     case 2:    {display(0x88fd);}break;

                     case 3:    {display(0x88fb);}break;

                     case 4:    {display(0x88f7);}break;

                     case 5:    {display(0x88ef);}break;

                     case 6:    {display(0x88df);}break;

                     case 7:    {display(0x88bf);}break;

                     case 8:    {display(0x887f);}break;

                     default:    ;

              }    

   EX0=1;    

       }

       else if(key==39)     //+

       {  

           EX0=0;

              key=0;

                     RESWDI();

              if(num!=0)

              {

                     keyok=0;

                     keychange=1;

                            RESWDI();

              }

              if(num==7)            //在分个位上

              {

                     if((buf[3]&0x0f)==0x09)      buf[3]&=0xf0;

                     else ++buf[3];

               EX0=1;

                     bufdata=buf[3]&0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xce);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                            RESWDI();

                    

              }

              else if(num==6)     //在分十位上

              {

                     if((buf[3]&0xf0)==0x50)      buf[3]&=0x0f;

                     else buf[3]+=0x10;

                                   EX0=1;

                     bufdata=buf[3]&0x70;

                     bufdata=bufdata>>4;

                     bufdata=bufdata&0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xcd);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                            RESWDI();

              }

              else if(num==5)     //在小时个位上

              {

                     if((buf[4]&0xf0)==0x20)

                     {

                            if((buf[4]&0x0f)>0x02) buf[4]&=0xf0;

                            else  ++buf[4];

                     }

                     else if((buf[4]&0x0f)==0x09)      buf[4]&=0xf0;

                     else        ++buf[4];

                                   EX0=1;

                     bufdata=buf[4]&0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xcc);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                            RESWDI();

              }

              else if(num==4)     //在小时十位上

              {

                     if((buf[4]&0x0f)>0x03)

                     {

                            if((buf[4]&0xf0)>0x00) buf[4]&=0x0f;

                            else  buf[4]+=0x10;

                     }

                     else if((buf[4]&0xf0)==0x20)       buf[4]&=0x0f;

                     else buf[4]+=0x10;

                                   EX0=1;

                     bufdata=buf[4]&0x30;

                     bufdata=bufdata>>4;

                     bufdata&=0x0f;

                     zlg7289_cs=0;

                            RESWDI();

                     delay(10);

                     dis_play(0xcb);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                            RESWDI();

              }

              else if(num==1)     //在日的个位上

              {

                     if((buf[5]&0xf0)==0x30)

                     {

                            if((buf[5]&0x0f)>0x00) buf[5]&=0xf0;

                            else        ++buf[5];

                     }

                     else if((buf[5]&0x0f)==0x09)       buf[5]&=0xf0;

                     else  ++buf[5];

                                   EX0=1;

                     bufdata=buf[5]&0x0f;

                            RESWDI();

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xc8);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                            RESWDI();

              }

              else if(num==2)     //在日的十位上

              {

                     if((buf[5]&0x0f)>0x01)

                     {    

                            if((buf[5]&0xf0)>0x10) buf[5]&=0x0f;

                            else buf[5]+=0x10;

                     }

                     else if((buf[5]&0xf0)==0x30)       buf[5]&=0x0f;

                     else buf[5]+=0x10;

                                   EX0=1;

                     bufdata=buf[5]&0x30;

                            RESWDI();

                     bufdata=bufdata>>4;

                     bufdata&=0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xc9);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                            RESWDI();

              }

              else if(num==4)     //在月个位上

              {

                     if((buf[7]&0xf0)==0x10)

                     {

                            if((buf[7]&0x0f)>0x01) buf[7]&=0x0f;

                            else ++buf[7];

                     }

                     else if((buf[7]&0x0f)==0x09)       buf[7]&=0xf0;

                     else  ++buf[7];

                                   EX0=1;

                     bufdata=buf[7]&0x0f;

                            RESWDI();

                     zlg7289_cs=0;

 

                     delay(10);

                     dis_play(0xca);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                            RESWDI();

              }

              else if(num==8) //在月十位上

              {

                     if((buf[7]&0x0f)>0x02)

                     {

                            buf[7]&=0x0f;

                     }

                     else if((buf[7]&0xf0)==0x10)       buf[7]&=0x0f;

                     else buf[7]+=0x10;

                                   EX0=1;

                     bufdata=buf[7]&0x10;

                     bufdata=bufdata>>4;

                     bufdata&=0x0f;

                            RESWDI();

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xcf);

                     delay(10);

                     dis_play(bufdata);          /*显示月十位*/

                     zlg7289_cs=1;

                     delay(70);

                            RESWDI();

 

              }

              else  ;

       }

 

       else if(key==15)     //存放断电时间,数据存放于5045,每按键数据减少一

       {

          display_x5045();

           EX0=1;

              key=0;

              if(num!=0)

              {

                     keyok=0;

                     keychange=1;

              }

              if(num==7)            //在分个位上

              {

                  date=ReadByte(0x40);

                     if((date&0x0f)==0x00)  date|=0x09;

                     else --date;

                                   EX0=1;

                     bufdata=date&0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xce);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                     WriteByte(date,0x40);

              }

              else if(num==6)     //在分十位上

              {

                   date=ReadByte(0x40);

                     if((date&0xf0)==0x00)  date|=0x50;

                     else date-=0x10;

                                   EX0=1;

                     bufdata=date&0x70;

                     bufdata=bufdata>>4;

                     bufdata&=0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xcd);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                     WriteByte(date,0x40);

              }

              else if(num==5)     //在小时个位上

              {

                    date=ReadByte(0x42);

                     if((date&0xf0)==0x20)

                     {

                            if(((date&0x0f)==0x00)||((date&0x0f)>0x03))    date|=0x03;

                            else  --date;

                     }

                     else if((date&0x0f)==0x00)   date|=0x09;

                     else --date;

                                   EX0=1;

                     bufdata=date&0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xcc);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                     WriteByte(date,0x42);

              }

              else if(num==4)     //在小时十位上

              {

                  date=ReadByte(0x42);

                     if((date&0x0f)>0x03)

                     {

                            if((date&0xf0)==0x00)  date|=0x10;

                            else date-=0x10;

                     }

                     else if((date&0xf0)==0x00)   date|=0x20;

                     else date-=0x10;

                                   EX0=1;

                     bufdata=date&0x30;

                     bufdata=bufdata>>4;

                     bufdata&=0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xcb);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                     WriteByte(date,0x42);

              }

              else if(num==1)     //在日的个位上

              {

                     if((buf[5]&0xf0)==0x30)

                     {

                            if(((buf[5]&0x0f)==0x00)||((buf[5]&0x0f)>0x01))     buf[5]|=0x01;

                            else  --buf[5];

                     }

                     else if((buf[5]&0x0f)==0x00)       buf[5]|=0x09;

                     else  --buf[5];

                     bufdata=buf[5]&0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xc8);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

              }

              else if(num==2)     //在日的十位上

              {

                     if((buf[5]&0x0f)>0x01)

                     {

                            if((buf[5]&0xf0)==0x00)      buf[5]|=0x20;

                            else  buf[5]-=0x10;

                     }

                     else if((buf[5]&0xf0)==0x00)       buf[5]|=0x30;

                     else buf[5]-=0x10;

                     bufdata=buf[5]&0x30;

                     bufdata=bufdata>>4;

                     bufdata&=0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xc9);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

              }

              else if(num==3)     //在月个位上

              {

                     if((buf[7]&0xf0)==0x10)

                     {

                            if(((buf[7]&0x0f)==0x00)||((buf[7]&0x0f)>0x01))     buf[7]|=0x01;

                            else --buf[7];

                     }

                     else if((buf[7]&0x0f)==0x00)       buf[7]|=0x09;

                     else  --buf[7];

                     bufdata=buf[7]&0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xca);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

              }

              else if(num==8) //在月十位上

              {

                     if((buf[7]&0x0f)>0x02) buf[7]&=0x0f;

                     else if((buf[7]&0xf0)==0x00)       buf[7]|=0x10;

                     else buf[7]-=0x10;

                     bufdata=buf[7]&0x10;

                     bufdata=bufdata>>4;

                     bufdata&=0x0f;

                     zlg7289_cs=0;

                     delay(10);

                     dis_play(0xcf);

                     delay(10);

                     dis_play(bufdata);         

                     zlg7289_cs=1;

                     delay(70);

                     EX0=1;

              }

              else  ;

       }

       else if(key==31)     //ok

       {

           EX0=0;

              key=0;

              keyok=1;

              num=0;

              if(keychange==1)

              {

                     keychange=0;

                     p=buf;

                     SUBA=0x00;

                     buf[0]=0x00;

                     buf[1]=0x00;

                     buf[2]=0x00;

                     ISendStr(SLA,SUBA,p);

                     for (i=0;i<250;i++)

                            delay(250);    

              }

              else  ;            

              zlg7289_cs=0;

              delay(10);

              dis_play(0x88);

              delay(10);

              dis_play(0xff);              /*LED闪烁*/

              zlg7289_cs=1;

              delay(70);

       }

    EX0=1;

}

 

 

/************************************************************

*******主函数************************************************

void main()

{

unsigned char i,j,word2;

       /*程序的初始化**************************/

 

    TMOD=0x09;

       TH0=0x3c;

       TL0=0xb0;

       TR0=1;

       ET0=1;

       IP=0x02;    //中断优先级敲定

       IT0=1;

       EX0=1;

       IE0=1;          

    EA=1;       /*打开全部中断*/

       p10=1;

       p06=1;

       p07=1;

   WREN();

    WRSR();

    WRDI(); 

WriteByte(0x07,0x40);//0x20中写入0x10,( 为了验证)

WriteByte(0x0a,0x42);

WRDI();

word2=ReadByte(0x22);

 

       /*初始化结束********************************/

       /*LED显示****************************************/

       zlg7289_cs=0;

       delay(10);

       dis_play(0xA4);                    //复位

       zlg7289_cs=1;

       delay(70);

 

       /*给时钟芯片附初值********************************/

       Stop_I2c();

       EX0=0;

       p=buf;

       SUBA=0x00;

       buf[0]=0x00;

       buf[1]=0x00;

       for(j=0;j<8;j++)

       {

              for(i=0;i<250;i++)

                     delay(250);

       }

       ISendStr(SLA,SUBA,p);

       delay(100);

       EX0=1;

       while(1)

       {

     

              if(keyint==1)

              {  

                     EX0=1;

                     ET0=1;

                     keyexe();

                     if(keychange==0)

                     {

                            keyint=0;

                            ET0=1;

                     }

                     for (i=0;i<250;i++)

                            delay(250);    

                     EX0=1;

              }

              if((keyok==1)&&(keychange==0)&&(keyint==0))

              {

                  EX0=0;

                     p=buf;

                     SUBA=0x00;

                     IRcvStr(SLA,SUBA,p);

                     for (i=0;i<250;i++)

                            delay(25);      

                     buf[3]&=0x7f;

                     buf[4]&=0x3f;

                     buf[5]&=0x3f;

                     buf[7]&=0x1f;

            displaymonth();

                     displaytime();

                     EX0=1;

              }

        if((buf[4]>=close_date)||(buf[4]<=open_date)) p10=0;

              for (i=0;i<250;i++)

                     delay(25);

       }

}