硬件部分 基于51单片机、 ds1302时钟芯片、 ds18b20温度芯片、 以及1602液晶显示的 实时时间 和 实时温度显示 。同时可通过按键 设置 年、月、日、时、分、星期。并且可以设置闹钟 当闹钟时间到时 蜂鸣器持续发出 滴..声 同时led灯不停闪烁 且在一分钟内没有按指定停止按键 闹钟将自动停止 。。。












 软件部分 #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 写?;?nbsp; } } } } 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; } } |