程序
- #include<AT89C52.H>
- #include<INTRINS.H>
- #define TIME (0X10000-50000)
- #define FLAG 0XEF //闹钟标志
- //引脚连接图
- 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[15],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[]={0x82,1,0x81,0xf4,0xd4,0xb4,0xa4,
- 0x94,0xe2,1,0xe1,0xd4,0xb4,0xc4,0xb4,4,0};
- //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,//月
- 0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00};//日
- //*******温度小数部分用查表法**********//
- 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[13]=time2[8]=time2[9]=time2[10]=0x20,time2[14]=0;
- time1[6]=1,time1[9]=2,time1[12]=3,time1[2]='2',time1[3]='0';
- time1[14]='W',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[4]=m/16+0x30;
- time1[5]=m%16+0x30;
- WriteDS1302(0x8b); //读取星期
- m=ReadDS1302();
- rst=0;
- time1[15]=m+0x30;
- for(i=7,n=0x89;i<11;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[4]&0xf)*10+(time1[5]&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[7]&0xf)*10+(time1[8]&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[10]&0xf)*10+(time1[11]&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[14]=time1[15]=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[4]&0xf)*10+(time1[5]&0xf);
- month=(time1[7]&0xf)*10+(time1[8]&0xf);
- day=(time1[10]&0xf)*10+(time1[11]&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[4]=year/10+0x30;
- time1[5]=year%10+0x30;
- time1[7]=month/10+0x30;
- time1[8]=month%10+0x30;
- time1[10]=day/10+0x30;
- time1[11]=day%10+0x30;
- LCDSHOW();
- }
- else if(P2==0xd7)
- {
- WriteDS1302(0x8c);
- WriteDS1302((time1[4]&0xf)*16+(time1[5]&0xf));
- rst=0;
- WriteDS1302(0x8a);
- WriteDS1302(setweek());
- rst=0;
- for(i=7,n=0x88;i<11;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[14]='W';
- return;
- }
- else
- {
- TR0=0;
- time1[14]='W';
- return;
- }
- }
- }
- if(j==0)
- {
- TR0=0;
- time1[14]='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);
- }
- }
复制代码 |