- #include <reg52.h>
- #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%10;
- 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]%16;
- fs=time[1]/16;
- fg=time[1]%16;
- fen=fs*10+fg;
-
- ss=time[2]/16;
- sg=time[2]%16;
- shi=ss*10+sg;
- rs=time[3]/16;
- rg=time[3]%16;
- ri=rs*10+rg;
- ys=time[4]/16;
- yg=time[4]%16;
- yue=ys*10+yg;
- ns=time[6]/16;
- ng=time[6]%16;
- nian=ns*10+ng;
- xing=time[5];
- }
- if(a==1|b==1)
- {
- ss=shi/10;
- sg=shi%10;
- 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%10;
- 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%10;
- 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%10;
- 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%10;
- 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%10]); //在液晶第二行第十一位显示温度的个位
- write_com(0x80+0x4c);
- write_data(table[(d&0x0f)*625/1000]); //在液晶第二行第十三位显示温度的小数点后一位
- write_com(0x80+0x4d);
- write_data(table[(d&0x0f)*625/100%10]); //在液晶第二行第十四位显示温度的小数点后二位
- }
- }
- 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;
- }
- }