Design of Electronic Clock Program Design of 51 Single Chip Computer with Alarm Clock and Adjustable Time

2020-12-16 10:45:34

Design of Electronic Clock Program Design of 51 Single Chip Computer with Alarm Clock and Adjustable Time


Hardware parts:


    Based on 51 single-chip microcomputer, ds1302 clock chip, ds18b20 temperature chip, and 1602 liquid crystal display real-time time and real-time temperature display. At the same time, the year, month, day, hour, minute, and day of the week can be set through the buttons. And you can set the alarm clock. When the alarm time is up, the buzzer keeps beeping. At the same time, the led light flashes and the designated stop button is not pressed within one minute. The alarm clock will automatically stop. . .




Software part:



#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初始失败(可设置返回值查看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;

 }


}