找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1205|回复: 0
打印 上一主题 下一主题
收起左侧

多功能电子时钟的设计

[复制链接]
跳转到指定楼层
楼主
#include<AT89X52.H>
#include<INTRINS.H>

#define TIME (0X10000-50000)
#define FLAG 0xFC
//0x0E,0x04,0x1F,0x15,0x17,0x11,0x1F,0x00                //闹钟标志
//引脚连接图
sbit rst=P3^5;
sbit clk=P3^4;
sbit dat=P3^3;
sbit rs=P1^5;
sbit rw=P1^6;
sbit e=P1^7;
sbit DQ=P1^4;        //温度输入口

sbit ACC_7=ACC^7;
//全局变量及常量定义
unsigned char i=20,j,time1[16];        
unsigned char alarm[2],time2[16],time[3];
unsigned char code Day[]={31,28,31,30,31,30,31,31,30,31,30,31};//12个月的最大日期(非闰年)
//音律表
unsigned int code table1[]={64260,64400,64524,64580,64684,64777,
64820,64898,64968,65030,65058,65110,65157,65178,65217};
//发声部分的延时时间
unsigned char code table2[]={0x12,0x12,0x22,0x32,0x31 ,0x22,0x21,0x22,
0x21,0x31,0x51,0x52,0x31,0x52,0x61,0x15,0x14,
0x51,0x52,0x31,0x52,0x62,0x13,0x11,0x13,0x32,0x28,0x08,0x28,
0x31,0x32,0x31, 0x32,0x11,0x21,0x51,0x52,0x51,0x52,
0x51,0x51,0x31,0x32,0x31,0x32,0x81,0x72,0x63,
0x62,0x71,0x81,0x72,0x61,0x61,0x52,0x31,0x21,0x32,0x51,0x54,
0x22,0x12,0x11,0x12,0x11,0x12,0x12,0x14,0x26,0x32,0x26,
0x32,0x61 ,0x51,0x51,0x31,0x31,0x21,0x31,0x51,0x61,0x51 ,0x31,0x51,
0x02,0x32,0x81,0x81,0x81,0x81,0x62,0x52,0x34,
0x31,0x81,0x81,0x81,0x61,0x91,0x82,
0x51,0x51,0x51,0x51,0x31,0x61,0x53,
0x21,0x11,0x21,0x11,0x22,0x11,0x21 ,0x26,
0x32,0x61,0x51,0x51,0x31 ,0x31,0x21 ,0x31,0x51,0x61,0x51,0x31,0x51,0x52,
0x31,0x31,0x81,0x81,0x81,0x61,0x91,0x81,0x61,0x31,0x56,
0x32,0x32,0x81,0x81,0x81,0x81,0x91,0x81,0x61 ,0x81,0x61 ,0x51,0x31 ,0x51,0x34,
0x21,0x31,0x51,0x31,0x21,0x11,0x61,0x21,0x16,0xff
};
//LCD自建字
unsigned char code tab[]={0x18,0x1b,5,4,4,5,3,0,//摄氏度
//0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,//年
//0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,//月
0x0e,0x04,0x1f,0x15,0x17,0x11,0x1f,0x00,//闹钟
//0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00,//日
0x00,0x1B,0x1F,0x1F,0x1F,0x0E,0x04,0x00,//爱心
0x00,0x00,0x3F,0xF8,0x21,0x08,0x21,0x08,0x2F,0xE8,0x21,0x08,0x21,0x08,0x3F,0xF8,0x20,0x08,0x27,0xC8,0x24,0x48,0x24,0x48,0x27,0xC8,0x40,0x08,0x40,0x28,0x80,0x10};//周




//*******温度小数部分用查表法**********//
unsigned char code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
//闹钟中用的全局变量
unsigned char th1,tl1;
unsigned char temp_data[2]={0x00,0x00};               // 读出温度暂放
bit flag;                //18b20存在标志位
/***********11微秒延时函数**********/
delay(unsigned int t)
{
        for(;t>0;t--);
}
/***********18B20复位函数**********/
RST18B20(void)
{
        unsigned char i;
        DQ=1;_nop_();_nop_();
        DQ=0;    //
        delay(50); // 550us
        DQ=1;    //
        delay(6);  // 66us
        for(i=0;i<0x30;i++)
        {
                if(!DQ)
                        goto d1;                        
        }
        flag=0;                //清标志位,表示ds1820不存在
        DQ=1;
        return;
d1:        delay(45);    //延时500us
        flag=1;
        DQ=1;                //置标志位,表示ds1820存在
}
/**********18B20写命令函数*********/
//向 1-WIRE 总线上写一个字节
void Write1Byte18B20(unsigned char val)
{
        unsigned char i;
        for (i=8; i>0; i--) //
        {
                DQ=1;_nop_();_nop_();
                DQ=0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us
                DQ=val&0x01;      //最低位移出
                delay(6);           //66us
                val=val/2;         //右移一位
        }
        DQ=1;
        delay(1);  
}
/*********18B20读1个字节函数********/
//从总线上读取一个字节
unsigned char Read1Byte18B20(void)
{
        unsigned char i;
        unsigned char value=0;
        for (i=8;i>0;i--)
        {
                DQ=1;_nop_();_nop_();
                value>>=1;
                DQ=0;             //
                _nop_();_nop_();_nop_();_nop_();   //4us
                DQ=1;_nop_();_nop_();_nop_();_nop_();   //4us
                if(DQ)
                        value|=0x80;
                delay(6);           //66us
        }
        DQ=1;
        return(value);
}
/***********读出温度函数**********/
Read18B20()
{
        RST18B20();                               //总线复位
        if(!flag)                //判断ds1820是否存在?若ds18b20不存在则返回
                return;                                

        //Write1Byte18B20(0xCC);                         // Skip ROM
        //Write1Byte18B20(0x44);                         // 发转换命令
        //delay(70);

        Write1Byte18B20(0xCC);                         //发Skip ROM命令
        Write1Byte18B20(0xBE);                         //发读命令
        temp_data[0]=Read1Byte18B20();   //温度低8位
        temp_data[1]=Read1Byte18B20();   //温度高8位        
        RST18B20();
        Write1Byte18B20(0xCC);                         // Skip ROM
        Write1Byte18B20(0x44);                         // 发转换命令
}
/***********温度数据处理函数**********/
DealTempData()
{
        unsigned char n=0,m;      
        if(temp_data[1]>127)//负温度求补码
        {
                temp_data[1]=(256-temp_data[1]);
                temp_data[0]=(256-temp_data[0]);
                n=1;
        }
        time2[13]=ditab[temp_data[0]&0x0f]+'0';
        time2[12]='.';
        m=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//
        if(n)
        {
                m-=16;
        }
        time2[9]=m/100+'0';
        time2[11]=m%100;
        time2[10]=time2[11]/10+'0';
        time2[11]=time2[11]%10+'0';
        if(time2[9]=='0')//最高位为0时都不显示
        {
                time2[9]=0x20;        
                if(n)//负温度时最高位显示"-"
                {
                        time2[9]='-';
                }
                if(time2[10]=='0')
                {
                        if(n)
                        {
                                time2[10]='-';
                                time2[9]=0x20;
                        }
                        else
                                time2[10]=0x20;
                        if(time2[11]=='0'&&time2[13]=='0')
                                time2[11]=time2[12]=0x20;
                }                        
        }
}
delay1ms(unsigned char time)                //延时1ms
{
        unsigned char i,j;
        for(i=0;i<time;i++)
        {
                for(j=0;j<250;j++);
        }
}

//使能1602
EnableLCD()
{
        rs=0;
        rw=0;
        e=0;
        delay1ms(3);
        e=1;
}
//写LCD函数
WriteLCD(unsigned char i)
{
        P0=i;
        rs=1;
        rw=0;
        e=0;
        delay1ms(2);
        e=1;
}
//写LCD内部地址函数
WriteLCDRAM(unsigned char data *address,m)
{
        unsigned char i,j;
        for(i=0;i<m;i++,address++)
        {
                j=*address;
                WriteLCD(j);
        }
}
//LCD显示
LCDSHOW()
{
        P0=0Xc;                                //显示器开、光标关
        EnableLCD();
        P0=0x80;                        //写入显示起始地址
        EnableLCD();
        WriteLCDRAM(time1,16);
        P0=0xc1;                       //写入显示起始地址
        EnableLCD();
        WriteLCDRAM(time2,15);
}
//自建字函数库
DesignHZ()
{
        unsigned char i;
        P0=0x40;
        EnableLCD();
        for(i=0;i<32;i++)
        {
                WriteLCD(tab[i]);
                delay1ms(2);        
        }
}

//写DS1302子程序
WriteDS1302(unsigned char address)
{
        unsigned char i;
        clk=0;
        _nop_();
        rst=1;
        _nop_();
        for(i=0;i<8;i++)
        {
                dat=address&1;
                _nop_();
                clk=1;
                address>>=1;
                clk=0;
        }
}
//读DS1302子程序
unsigned char ReadDS1302()
{
        unsigned char i,j=0;
        for(i=0;i<8;i++)
        {
                j>>=1;
                _nop_();
                clk=0;
                _nop_();
                if(dat)
                        j|=0x80;
                _nop_();
                clk=1;
        }
        return(j);
}
//部分显示数据初始化
TimeInit()
{
        time1[1]=time1[4]=time1[5]=time2[8]=time2[9]=time2[10]=0x20,time2[11]=0;
        time1[10]='/',time1[13]='/',time1[6]='2',time1[7]='0';
        time1[2]='W',time1[5]=2,time2[2]=time2[5]=':';
        WriteDS1302(0xc1);
        alarm[0]=ReadDS1302();
        rst=0;
        WriteDS1302(0xc3);
        alarm[1]=ReadDS1302();
        rst=0;
        WriteDS1302(0xc5);
        time1[0]=ReadDS1302();
        rst=0;
}
//读取时间
ReadTime()
{
        unsigned char i,m,n;
        WriteDS1302(0x8d);                        //读取年份
        m=ReadDS1302();
        rst=0;
        time1[8]=m/16+0x30;
        time1[9]=m%16+0x30;
        WriteDS1302(0x8b);                        //读取星期
        m=ReadDS1302();
        rst=0;
        time1[3]=m+0x30;
        for(i=11,n=0x89;i<15;i+=3,n-=2)       //读取月份和日期
        {
                WriteDS1302(n);
                m=ReadDS1302();
                rst=0;
                time1[i]=m/16+0x30;
                time1[i+1]=m%16+0x30;
        }
        for(m=0,i=0,n=0x85;i<7;i+=3,n-=2,m++)        //读取时,分,秒
        {
                WriteDS1302(n);
                time[m]=ReadDS1302();
                rst=0;
                time2[i]=time[m]/16+0x30;
                time2[i+1]=time[m]%16+0x30;
        }
}
time0() interrupt 1 using 1
{
        i--;
        if(i==0)
        {
                if(j!=0)
                        j--;                 
                i=20;
        }
        TH0=TIME/256,TL0=TIME%256;               
}
//闹钟部分
intime1() interrupt 3
{
        TH1=th1,TL1=tl1;
        P3_2=!P3_2;
}
//显示闹钟设置数据
showalarm()
{
        unsigned char i,j,a,b,n;
        ET1=1;
        for(j=0;j<6;j++)
        {
                i=0;
                while(1)
                {
                        a=table2[i];
                        if(a==0)
                                break;
                        b=a&0xf;
                        a>>=4;
                        if(a==0)
                        {
                                TR1=0;
                                goto  D1;
                        }
                        a=((--a)<<1)/2;
                        TH1=th1=table1[a]/256,TL1=tl1=table1[a]%256;
                        TR1=1;
D1:                        do
                        {
                                b--;
                                for(n=0;n<3;n++)
                                {
                                        ReadTime();
                                        LCDSHOW();
                                        P2=0xf7;
                                        if(P2==0xe7)
                                        {
                                                delay1ms(100);
                                                if(P2==0xe7)
                                                {
                                                        TR1=0;
                                                        ET1=0;
                                                        return;
                                                }        
                                        }
                                }
                        }while(b!=0);
                        i++;                                
                }
                TR1=0;                  
        }
        ET1=0;
}
//根据日期的变动自动调整星期
unsigned char setweek()
{
        unsigned char i=5,j,n;
        j=(time1[8]&0xf)*10+(time1[9]&0xf);
        n=j/4;
        i=i+5*n;
        n=j%4;
        if(n==1)
                i+=2;
        else if(n==2)
                i+=3;
        else if(n==3)
                i+=4;
        j=(time1[11]&0xf)*10+(time1[12]&0xf);
        if(j==2)
                i+=3;
        else if(j==3)
                i+=3;        
        else if(j==4)
                i+=6;        
        else if(j==5)
                i+=1;        
        else if(j==6)
                i+=4;        
        else if(j==7)
                i+=6;        
        else if(j==8)
                i+=2;        
        else if(j==9)
                i+=5;
        else if(j==11)
                i+=3;        
        else if(j==12)
                i+=5;
        if(n==0)
                if(j>2)        
                        i++;        
        j=(time1[14]&0xf)*10+(time1[15]&0xf);
        i+=j;
        i%=7;
        if(i==0)
                i=7;
        return(i);        
}
//设置时间
settime()
{
        unsigned char i=0x85,year,month,day,n;
        time2[6]=time2[7]=0x30,time1[2]=time1[3]=0x20;
        LCDSHOW();
        while(1)
        {               
                P0=0xe;                        //显示器开、光标开
                EnableLCD();
                P0=i;                        //定光标
                EnableLCD();
                P2=0xf7;
                if(P2!=0XF7)
                {
                        delay1ms(100);                                //延时0.1s去抖动
                        if(P2!=0XF7)
                        {
                                j=7;
                                if(P2==0X77)
                                {
                                        i+=3;
                                        if(i==0x8e)
                                                i=0xc2;
                                        else if(i>0xc5)
                                                i=0x85;
                                }
                                else if(P2==0xb7)
                                {
                                        year=(time1[8]&0xf)*10+(time1[9]&0xf);
                                        month=(time1[11]&0xf)*10+(time1[12]&0xf);
                                        day=(time1[14]&0xf)*10+(time1[15]&0xf);
                                        if(i==0x85)
                                        {
                                                year++;
                                                if(year>99)
                                                        year=0;
                                                if((year%4)!=0)
                                                        if(month==2&&day==29)
                                                                day=28;
                                        }
                                        else if(i==0x88)
                                        {
                                                month++;
                                                if(month>12)
                                                        month=1;
                                                if(day>Day[month-1])
                                                {
                                                        day=Day[month-1];
                                                        if(month==2&&(year%4)==0)        
                                                                day=29;
                                                }                                                        
                                        }
                                        else if(i==0x8b)
                                        {
                                                day++;
                                                if(day>Day[month-1])
                                                {
                                                        if(month==2&&(year%4)==0)
                                                        {
                                                                if(day>29)
                                                                        day=1;
                                                        }
                                                        if(month!=2)
                                                                day=1;
                                                }
                                        }
                                        else if(i==0xc2)
                                        {
                                                n=(time2[0]&0xf)*10+(time2[1]&0xf);
                                                n++;
                                                if(n>23)
                                                        n=0;
                                                time2[0]=n/10+0x30;
                                                time2[1]=n%10+0x30;
                                        }
                                        else
                                        {
                                                n=(time2[3]&0xf)*10+(time2[4]&0xf);
                                                n++;
                                                if(n>59)
                                                        n=0;
                                                time2[3]=n/10+0x30;
                                                time2[4]=n%10+0x30;
                                        }
                                        time1[8]=year/10+0x30;
                                        time1[9]=year%10+0x30;
                                        time1[11]=month/10+0x30;
                                        time1[12]=month%10+0x30;
                                        time1[14]=day/10+0x30;
                                        time1[15]=day%10+0x30;
                                        LCDSHOW();
                                }
                                else if(P2==0xd7)
                                {
                                        WriteDS1302(0x8c);
                                        WriteDS1302((time1[8]&0xf)*16+(time1[9]&0xf));
                                        rst=0;
                                        WriteDS1302(0x8a);
                                        WriteDS1302(setweek());
                                        rst=0;
                                        for(i=11,n=0x88;i<15;i+=3,n-=2)
                                        {        
                                                WriteDS1302(n);
                                                WriteDS1302((time1[i]&0xf)*16+(time1[i+1]&0xf));
                                                rst=0;
                                        }
                                        for(i=0;i<7;i+=3,n-=2)
                                        {
                                                WriteDS1302(n);
                                                WriteDS1302((time2[i]&0xf)*16+(time2[i+1]&0xf));
                                                rst=0;
                                        }
                                        TR0=0;
                                        time1[2]='W';
                                        return;
                                }
                                else
                                {
                                        TR0=0;
                                        time1[2]='W';
                                        return;
                                }
                        }
                }        
                if(j==0)
                {        
                        TR0=0;
                        time1[2]='W';
                        return;
                }
        }
}
//设置闹钟
setalarm()
{
        unsigned char i,n;
        for(i=1;i<16;i++)
        {
                time1[i]=0x20;
        }        
        time2[0]=alarm[0]/16+0x30;
        time2[1]=(alarm[0]&0xf)+0x30;
        time2[3]=alarm[1]/16+0x30;
        time2[4]=(alarm[1]&0xf)+0x30;
        time2[6]=time2[7]=0x30;
        LCDSHOW();
        i=0xc2;
        while(1)
        {
                P0=0xe;                        //显示器开、光标开
                EnableLCD();
                P0=i;                        //定光标
                EnableLCD();
                P2=0xf7;
                if(P2!=0XF7)
                {
                        delay1ms(100);                               //延时0.1s去抖动
                        if(P2!=0XF7)
                        {
                                j=7;
                                if(P2==0X77)
                                {
                                        i+=3;
                                        if(i>0xc5)
                                                i=0xc2;
                                }
                                else if(P2==0xb7)
                                {
                                        if(i==0xc2)
                                        {
                                                n=(time2[0]&0xf)*10+(time2[1]&0xf);
                                                n++;
                                                if(n>23)
                                                        n=0;
                                                time2[0]=n/10+0x30;
                                                time2[1]=n%10+0x30;
                                        }
                                        else
                                        {
                                                n=(time2[3]&0xf)*10+(time2[4]&0xf);
                                                n++;
                                                if(n>59)
                                                        n=0;
                                                time2[3]=n/10+0x30;
                                                time2[4]=n%10+0x30;
                                        }
                                        LCDSHOW();
                                }
                                else if(P2==0xd7)
                                {
                                        WriteDS1302(0xc0);
                                        WriteDS1302((time2[0]&0xf)*16+(time2[1]&0xf));
                                        rst=0;
                                        WriteDS1302(0xc2);
                                        WriteDS1302((time2[3]&0xf)*16+(time2[4]&0xf));
                                        rst=0;
                                        time1[0]=FLAG;
                                        WriteDS1302(0xc4);
                                        WriteDS1302(time1[0]);
                                        rst=0;
                                        TR0=0;
                                        TimeInit();
                                        return;
                                }
                                else
                                {
                                        TR0=0;
                                        TimeInit();
                                        return;
                                }
                        }
                }        
                if(j==0)
                {        
                        TR0=0;
                        TimeInit();
                        return;
                }
        }
}
main()
{
        IE=0X82;
        TMOD=0x11;
        WriteDS1302(0x8E);                        //禁止写保护
        WriteDS1302(0);
        rst=0;
        P0=1;                                //清屏并光标复位
        EnableLCD();
        P0=0X38;                        //设置显示模式:8位2行5x7点阵
        EnableLCD();
        P0=6;                                //文字不动,光标自动右移
        EnableLCD();
        DesignHZ();                        //自建字
        TimeInit();
        while(1)
        {        
                ReadTime();                                //读取时间
                Read18B20();                //读出18B20温度数据
                DealTempData();                //处理温度数据
                LCDSHOW();                                //显示时间
                if(time1[0]!=0x20)
                        if(time[0]==alarm[0])
                                if(time[1]==alarm[1])
                                        if(time[2]==0)
                                                showalarm();
                P2=0xf7;
                if((P2&0XF0)!=0XF0)
                {
                        delay1ms(100);                                //延时0.1s去抖动
                        if((P2&0XF0)!=0XF0)
                        {
                                j=7;
                                TH0=TIME/256,TL0=TIME%256;
                                TR0=1;
                                if(P2==0x77)
                                {
                                        settime();
                                }
                                else if(P2==0XB7)
                                {
                                        setalarm();
                                }
                                else if(P2==0XD7)
                                {
                                        TR0=0;
                                        if(time1[0]==FLAG)
                                                time1[0]=0x20;
                                        else
                                                time1[0]=FLAG;
                                        WriteDS1302(0xc4);
                                        WriteDS1302(time1[0]);
                                        rst=0;
                                }
                        }
                }
                delay1ms(100);        
        }
}


H~`ST~2E@S0IX}H[$8)NS1Z.png (71.23 KB, 下载次数: 26)

H~`ST~2E@S0IX}H[$8)NS1Z.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表