很久前做过的一个电子万年历,拿来和大家分享一下,做成实物在家里放着跑了2年多了,极其稳定,日误差小于1秒。

唯一的问题:不用DS1302虽然是省去了不少焊接的功夫,但是程序掉电又得重设时间,所以建议接交流电+蓄电池浮充,这样就不会掉电了,完美解决问题,可以跑一个月都不用调时间。

源代码:

#include <reg52.h>
typedef  unsigned int u16;
typedef  unsigned char u8;
sbit k2=P3^2;                                            //K1 K2 K3 K4按键接口,建议从左到右接K1-K4
sbit k1=P3^5;
sbit k3=P3^3;
sbit k4=P3^4;
sbit DQ=P3^6;
sbit beep=P1^6;
sbit Data=P2^0;                                             //有源蜂鸣器在P16口
sbit lcden=P1^4;                                                //LCD1602接口定义
sbit lcdrs=P1^0;
sbit lcdrw=P2^6;
sbit bg=P2^7;                                                //背光变量接入LCD1602的K极,通过bg的高低电平就可控制自动熄灭与点亮
u8 k,e,d,o=1,p=1,temp,nxflag=0,mbflag=0,tianmax;
float temperature;                                           //温度变量,18B20接收时为浮点数
u8 miao1,miao2,fen1,fen2,shi1,shi2,tian1,tian2,wk,tem1,tem2,tem3,wendufu;
u8 day=1,mon=1,day1,day2,yue1,yue2,mbw,n=0,m=0,beiguang,RH,RL,TH,TL,tempH,tempL;
u8 se1,se2,mon1,mon2,hou1,hou2,min1,min2,MB2,nian1,nian2,nian3,nian4;
u16 y,MB1;
u16 temper,buchang,tempwarn=0,tempwarn1=500;                //tempwarn为温度下限,1为温度上限
u8 code set[]={"NaoZhong  Status"};                                    //上电后傻瓜调节模块
u8 code tempwarng[]={"Wendu Waring!"};
u8 code temmin[]={"Min"};
u8 code temmax[]={"Max"};
u8 code naozhongON[]={" ON"};
u8 code naozhongOFF[]={"OFF"};
u8 code setsucces[]={"Set Success!"};
u8 code thanks[]={"Welcome to use !"};
u8 code thanksu[]={"thanks for using"};
u8 code make[]={"Designed by LY"};
u8 code MB[]={"Stopwatch"};
u8 code week1[]={"[MON]"};
u8 code week2[]={"[TUE]"};
u8 code week3[]={"[WED]"};
u8 code week4[]={"[THU]"};
u8 code week5[]={"[FRI]"};
u8 code week6[]={"[SAT]"};
u8 code week7[]={"[SUN]"};
void delay(unsigned int z)                                   //定义延时函数
{                                           unsigned int x,y;           for(x=z;x>0;x--)for(y=1;y>0;y--);
}
void DHT11_delay_us(u8 n)
{while(--n);
}
void DHT11_delay_ms(u16 z)               //定义DHT11延迟函数
{u16 i,j;for(i=z;i>0;i--)for(j=110;j>0;j--);
}void DHT11_start()
{Data=1;DHT11_delay_us(2);Data=0;DHT11_delay_ms(20);   //延时18ms以上Data=1;DHT11_delay_us(30);
}
u8 DHT11_rec_byte()      //接收一个字节
{u8 i,dat=0;for(i=0;i<8;i++)       //从高到低依次接收8位数据{          while(!Data);       //等待50us低电平过去DHT11_delay_us(8);   //延时60us,如果还为高则数据为1,否则为0 dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位if(Data==1)        //数据为1时,使dat加1来接收数据1dat+=1;while(Data);       //等待数据线拉低    }  return dat;
}
void DHT11_receive()      //接收40位的数据{u8 R_H,R_L,T_H,T_L,revise; DHT11_start();if(Data==0){while(Data==0);   //等待拉高     DHT11_delay_us(40);      //拉高后延时80usR_H=DHT11_rec_byte();    //接收湿度高八位  R_L=DHT11_rec_byte();    //接收湿度低八位  T_H=DHT11_rec_byte();    //接收温度高八位  T_L=DHT11_rec_byte();    //接收温度低八位revise=DHT11_rec_byte(); //接收校正位DHT11_delay_us(25);      //结束if((R_H+R_L+T_H+T_L)==revise)      //校正{RH=R_H;RL=R_L;TH=T_H;TL=T_L;} }}
void beepon()                                                //PWM(如果你是无源蜂鸣器,这里写PWM函数)
{                                                        //当前为有源蜂鸣器,有源蜂鸣器无需更改beep=0;delay(1200);beep=1;
}
void write_nian();                                  //预定义
void write_yue();
void write_tian();
void write_shi();
void write_fen();
void write_miao();
void write_week();
void zhuanhuan();
void write_temp();
void write_nz();
void nzON();
void write_setsuccess();
void beiguangpd();void write_com(u8 com)                                    //LCD1602初始化程序,了解1602时序图后新手的话可以直接照搬使用
{lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;
}
void write_data(u8 date)
{lcdrs=1;P0=date;delay(5);lcden=1;delay(5);lcden=0;
}
void init()
{lcdrw=0;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80+0x10);
}
void Timer0Init()                                               //定时器0工作方式1 中断初始化,923位12M晶振在KEIL仿真后的计算结果
{   TMOD=0X01;TH0=(65535-901)/256;    TL0=(65535-901)%256;   ET0=1;                                          //打开定时器0中断允许位EA=1;                                         //打开总中断允许TR0=1;                                    //打开 定时器0,开始计时
}Init_DS18B20(void)                                    //DS18B20初始化与时序图程序,仿真时温度问题改进这个初始化程序就解决了{ DQ=1;delay(70); DQ=0; delay(485); DQ=1; delay(50); }
ReadOneChar(void)                                      //18B20读一个字节 {  unsigned char i=0; unsigned char dat=0; for (i=8;i>0;i--) { DQ=1; delay(1); DQ=0; dat>>=1; DQ=1; if(DQ) dat|=0x80; delay(4); } return(dat); }
WriteOneChar(unsigned char dat)                     //18B20写一个字节{ unsigned char i=0; for(i=8;i>0;i--) { DQ=0; DQ=dat&0x01; delay(5); DQ=1; dat>>=1; } delay(4); }
ReadTemperature(void)                           //读取温度函数定义,返回值为浮点数{ Init_DS18B20(); WriteOneChar(0xcc); WriteOneChar(0x44); delay(125); Init_DS18B20(); WriteOneChar(0xcc); WriteOneChar(0xbe); tempL=ReadOneChar(); tempH=ReadOneChar(); if(tempH>0x7f){tempH=~tempH;tempL=~tempL+1;wendufu=1;}elsewendufu=0;temperature=(((tempH*256)+tempL)*0.0625)*10;delay(200); return(temperature); }
void welcome()                                       //定义欢迎函数
{ static u8 i;init();                                              //初始化1602delay(5000);for(i=0;i<16;i++){write_com(0x80+i);write_data(thanks[i]); delay(4000);}delay(50000);for(i=0;i<14;i++){write_com(0x81+0x40+i);write_data(make[i]);delay(4000);}delay(50000);delay(50000);
}void pdtian1()                          //PD在上电后设置完毕主界面处的天数判断
{if((p==1||p==3)||(p==5||p==7)||(p==8||p==10)||p==12) tianmax=31;if((p==4||p==6)||(p==9||p==11))tianmax=30;if(p==2){if(((y%4==0)&&(y%100!=0))||(y%400==0))tianmax=29;elsetianmax=28;}
}
void pdxingqi1()                     //PD在上电后设置完毕至主界面处的星期判断
{static char c,yi,mt,xwk1,xwk2,xwk3;static int xwk,yn,xwk4;yn=y;if(p==1||p==2){ yn=yn-1; mt=p+12;}elsemt=p;yi=yn%100;c=yn/100;xwk1=yi+(yi/4);xwk2=c/4;xwk3=2*c;xwk4=(26*mt+26)/10;xwk=xwk1+xwk2-xwk3+xwk4+o-1;while(xwk<0){xwk+=7; }wk=xwk%7;
}
void Display()                                //定义主程序 显示部分函数模块
{    static u16 xunhuan;RH=RH%100;write_nian();                          //1602写入显示年write_com(0x84);write_data('-');                               write_yue();                        //写入月write_com(0x87);write_data('-');write_com(0x88);write_tian();                         //写入天write_week();write_shi();write_com(0x82+0x40);write_data(':');write_fen();write_com(0x85+0x40);write_data(':');write_miao();                     //写入温度,温度TEM1与2与3是温度的三位数                           xunhuan++;if(xunhuan<180){if(wendufu==1){   if((temper/100)!=0){write_com(0x89+0x40); write_data('-'); write_com(0x8a+0x40); write_data(tem1);   }else{write_com(0x89+0x40); write_data(' ');  write_com(0x8a+0x40); write_data('-');  }}else {write_com(0x89+0x40); write_data(' ');if((temper/100)!=0)  {write_com(0x8a+0x40); write_data(tem1);}else{write_com(0x8a+0x40); write_data(' ');} }write_com(0x8b+0x40);write_data(tem2);write_com(0x8c+0x40);write_data('.');write_com(0x8d+0x40);write_data(tem3);write_com(0x8e+0x40);write_data(0xdf);write_com(0x8f+0x40);write_data('C');}if(xunhuan>180){write_com(0x89+0x40); write_data(' ');write_com(0x8a+0x40); write_data(' ');write_com(0x8b+0x40); write_data(RH/10+0x30);write_com(0x8c+0x40); write_data(RH%10+0x30);write_com(0x8d+0x40); write_data('%');write_com(0x8e+0x40);write_data('R');write_com(0x8f+0x40); write_data('H');}if(xunhuan==360)xunhuan=0;
}
void NZdisplay()                                    //定义闹钟模块
{static u8 nzflag=2,nzwei;                        delay(2000); init();delay(2000);nzON();                                         //闹钟开关选择模块while(k4)                                     //没有检测到K4键退出时无限循环{  write_nz();                         //写入闹钟模块if(k3==0)                        //判断K3键是否按下{ delay(5000);if(k3==0)                      //延时消抖{beepon();                       //响一声if(nxflag==0)                        //如果NXFLAG为0,闹钟为关闭状态,给其赋值为1,nxflag=1;elsenxflag=0;                                }nzON();                           //判断闹钟的状态}if(k1==0)                             //如果K1键按下后{delay(8000);if(k1==0){beepon();if(nzwei==0)                             //通过NZWEI来判断当前光标的位置与设置小时还是分钟nzflag=0;if(nzwei==1)nzflag=1;} }if(nzflag==0){ while(1){ write_com(0x83+0x40);             //光标闪烁write_data(0xff);delay(5000);write_nz();                        //写入闹钟delay(5000); if(k2==0)                           //如果K2为0{delay(50);if(k2==0){ beepon();                         //判断小时状态,进行+1if(n<23)n+=1;elsen=0;}}if(k3==0)                         //如果K3为0{delay(50);if(k3==0)                       //判断小时状态,进行-1 最大溢出重回最小,最小溢出重回最大{ beepon();if(n>0)                          n-=1;elsen=23;}}if(k1==0){ delay(1000);                  //如果K1按下,更改NZFLAG,更改闹钟光标位if(k1==0){nzflag=1;   beepon();break;}}if(k4==0)                          //如果K4按下,退出。给NZFLAG重新赋值为2,取消光标并下次进入不会直接进入光标{beepon();delay(6000);nzflag=2;nzwei=0;break;   }}}if(nzflag==1)                             //如果NZ为1,同上,此时为分钟调节{  while(1){   write_com(0x86+0x40);write_data(0xff);delay(5000);write_nz();delay(5000);if(k2==0){delay(50);if(k2==0){ beepon();if(m<59)m+=1;elsem=0;}}if(k3==0){delay(50);if(k3==0){ beepon();if(m>0)m-=1;elsem=59;}}if(k1==0){delay(1000);if(k1==0){beepon();nzflag=0;break;}}if(k4==0){ beepon();delay(6000);nzflag=2;nzwei=1;break;    }}}if(k4==0){beepon();delay(30000);break;}   }nzflag=2;init();
}
void temperwaring()                           //定义温度警报模块
{  static u8 temflag=2,temwei;                        delay(5000);init();delay(5000);while(k4){    write_temp();                                //写入温度if(k3==0)                           //如果K3为0,为其赋值为N0-N0,关闭温度警报,并且不会闪烁光标{ beepon();delay(3000);tempwarn=(0X4e-0x30)*100;tempwarn1=(0X4e-0x30)*100;}if(k1==0)                        //如果K1为0,进入光标位,光标闪烁,根据temwei不同进入不同的初始闪烁位置{delay(8000);               if(k1==0){beepon();if(temwei==0)                     //为只需单独打开温度上限或下限报警时提供方便temflag=0;if(temwei==1)temflag=1;} }if(temflag==0)                       //和闹钟模块 类似,如果temflag为0的话进入下限调整,否则进入上限调整{ while(1){  write_com(0x86+0x40);write_data(0xff);delay(6000);write_temp();delay(4000);if(k2==0){delay(50);if(k2==0){ beepon();if(tempwarn<500)                              //温度范围为精确到小数点后1位,500为50.0度,自己设置每次只调节1度tempwarn+=10;                                 //如果需要温度报警精确到0.1度,请将此处改为1并重新修改界面elsetempwarn=0;}}if(k3==0)                  {delay(50);if(k3==0){ beepon();if(tempwarn>0&&(tempwarn!=(0X4e-0x30)*100))       //K3键按下,判断当在关闭状态与一般状态时,温度阀门下限减1度tempwarn-=10;elsetempwarn=500;}}if(k1==0)                                 //如果检测K1按下,跳出循环,给FLAG重新赋值为1,光标开始在温度上限处闪烁{ delay(1000);                              //并且开始调节温度上限temflag=1;                                  beepon();break;}if(k4==0)                            //如果K4等于0,第一次确定,光标停止闪烁,K2K3不会更改数值{                                    //目的是在确定无误后在下次按下K4时可以直接退出beepon();delay(6000);                    temflag=2;temwei=0;break;  }}}if(temflag==1)                   //进入温度修改上限部分,同温度修改下限{  while(1){  write_com(0x89+0x40);write_data(0xff);delay(6000);write_temp();delay(4000);if(k2==0){delay(50);if(k2==0){ beepon();if(tempwarn1<500)tempwarn1+=10;elsetempwarn1=0;}}if(k3==0){delay(50);if(k3==0){ beepon();if((tempwarn1>0)&&(tempwarn1!=(0X4e-0x30)*100))tempwarn1-=10;elsetempwarn1=500;}}if(k1==0){beepon();delay(1000);temflag=0;break;}if(k4==0){ beepon();delay(6000);temflag=2;temwei=1;break;   }}}if(k4==0)                                           //当光标不闪烁时,按下K4键,直接退出{beepon();delay(30000);break;}  }temflag=2;                           //temflag重新赋值为2,目的是确保下次进入不会直接进入光标调节模块init();ET0=1;                       //这样就可以方便的快速关闭温度报警及快速设置上下限}
void miaobiaods()                           //定义秒表显示模块
{static u8 i,times;delay(1000);init();delay(10000);while(1)
{
if(MB1==10000)                           //MB1位16位数,所以秒表在0.00-100.00的计数范围使用MB1,超出后清0累加MB2
{MB1=0;MB2++;}if(MB2==100)                  //如果秒表超出了10000秒,直接清零,若想修改更大秒表范围请将MB2定义为16位数再修改,并修改显示界面{MB2=0;MB1=0;mbflag=0;}for(i=0;i<9;i++)                   //1602循环显示STOPWATCH{write_com(0x84+i);write_data(MB[i]);                }write_com(0x83+0x40);                   //显示秒表运行状态模块write_data(times/10+0x30);write_com(0x84+0x40);write_data(times%10+0x30);                 //TIMES为计数部分,不为0时每次暂停可以计数一次write_com(0x86+0x40);write_data(MB2/10+0x30);write_com(0x87+0x40);                     //秒表高位MB2与低位MB1转换为16进制数显示write_data(MB2%10+0x30);write_com(0x88+0x40);write_data('.');write_data((MB1/1000)+0x30);write_com(0x8a+0x40);write_data(MB1%1000/100+0x30);write_com(0x8b+0x40);write_data('.');write_com(0x8c+0x40);write_data(MB1%1000%100/10+0x30);write_com(0x8d+0x40);write_data(MB1%1000%100%10+0x30);if(k1==0)                                      //由于秒表对精度要求很高,必须直接中断不能延时{mbflag=1;                                     //因此也不能只用一个K1进行开始于暂停beepon();    }                             //此时按下K1键为打开秒表,会有立刻的响铃以便直观表明计时开始if(k2==0)                                             //和以上原因一样,秒表暂停{mbflag=0;                                           //按下K2键为暂停beepon(); if(MB1!=0)                                          //如果不为0,计次+1{ delay(40000);if(times<99)                                       //计次范围0-99times+=1;}}if(k3==0)                                         //按下K3,秒表数据清0{beepon();mbflag=0;times=0;MB1=0;MB2=0;}if(k4==0){beepon();                             //K4为0,退出秒表,如果打开秒表也可直接退出,秒表与时间并不冲突break;}}delay(1000);init();                            //延时初始化,确保时间充足无乱码delay(10000);
}
void naozhongfamen()                            //主界面上判断是否进入闹钟设置界面的模块
{ if(k3==0){  delay(50000);                                  //如果K3长按,进入闹钟if(k3==0){beepon();delay(3000);NZdisplay();delay(10000);write_setsuccess();delay(30000);                                    init();}}
}
void wendufamen()                                 //主界面上判断是否进入温度报警设置界面的模块
{ if(k2==0){  delay(50000);if(k2==0){ beepon();delay(3000);temperwaring();                                    delay(10000);write_setsuccess();delay(30000);init();}}
}
void miaobiao()                       //主界面上判断是否进入秒表的模块
{  if(mbflag==1)
{if(MB1>10000)
{MB1=0;MB2++;}if(MB2==100){MB2=0;MB1=0;mbflag=0;}
}if(k4==0){ delay(50000);if(k4==0){beepon();delay(3000);miaobiaods();delay(10000);init();}}
}
void Timer0() interrupt 1                  //定义中断函数,923为12M晶振的精度,如果是11.05M晶振请根据仿真或实测自行改变这个值
{    static u16 i;  TH0=(65535-901)/256;   TL0=(65535-901)%256;   i++;                                   //i为秒,不断累加beiguangpd();                              //进行背光判断,确保背光第一时间响应if(mbflag==1){                                         //如果检测到打开秒表了,就开始秒表位累加mbw++;if(mbw==10){mbw=0;MB1++;}}if(i==1000)                           //如果检测到1000,秒+1{k++; i=0;if(beiguang<60)                       //如果背光变量小于60,此时背光打开beiguang++;buchang++;  DHT11_receive();temper=ReadTemperature();               //检测温度,检测周期是1S}    if(k==60)                                  //判断各个变量,也可将这些放到其他模块里,但是精度未必会提高{k=0;e++;}if(buchang==4955)                                     //精度补偿部分,不一定适合你的晶振{buchang=0;k+=1;}if(e==60){e=0;d++;}if(d==24){ d=0;o++;if(wk<6)wk++;elsewk=0;}if(o==tianmax+1){o=1;p++;}if(p==13){p=1;y++;}
}
void bijiao()                                 //比较模块,也是报警触发模块
{static u8 gbflag;if(m==e&&n==d)                                  //如果闹钟时间相同,开始响铃,时长1分钟{if(gbflag==0)                                   //如果不是在响铃并按键关闭后,才会响铃
{if(nxflag==1)                                 //如果闹钟为开启状态响铃,否则不响beepon();if(k2==0||k3==0||k4==0)                        //如果有K2,K3,K4任何一个按键触发,就会将gbflag设置为1,停止响铃gbflag=1;                                       //因为K1键快速按下还有快捷粗调暂停1秒的功能,所以没有K1键}}elsegbflag=0;                              //响铃完毕后给gbflag赋值为0;if(e==0&&k==0)                                      //整点报时模块,设置为7到24点整点报时,可改范围,不会影响休息也比较合适{if((d>6&&d<24)||d==0)beepon();}         if((tempwarn!=(0X4e-0x30)*100)){if(wendufu==1)beepon();}if((tempwarn!=(0X4e-0x30)*100)||(tempwarn1!=(0X4e-0x30)*100))          //判断温度阀门打开了上限还是下线还是关闭还是上下限同时打开{ if((tempwarn==(0x4e-0x30)*100)&&(tempwarn1!=(0X4e-0x30)*100))               //判断完毕后只要触发就会报警{if(tempwarn1<temper){beepon();}}if((tempwarn!=(0x4e-0x30)*100)&&(tempwarn1==(0X4e-0x30)*100)){if(tempwarn>temper)beepon();}if((tempwarn!=(0X4e-0x30)*100)&&(tempwarn1!=(0X4e-0x30)*100)){ if((tempwarn>temper)||(tempwarn1<temper)){beepon();       }}}
}
void zhuanhuan()                                   //转换模块,将时间变量转换为1602的16位显示数值
{ nian1=(y/1000)+0x30;nian2=(y%1000/100)+0x30;nian3=(y%1000%100/10)+0x30;nian4=(y%1000%100%10)+0x30; yue1=(p/10)+0x30;yue2=(p%10)+0x30;tian1=(o/10)+0x30;tian2=(o%10)+0x30;shi1=(d/10)+0x30;shi2  =(d%10)+0x30;fen1=(e/10)+0x30;fen2=(e%10)+0x30;miao1=(k/10)+0x30;miao2=(k%10)+0x30;tem1=(temper/100)+0x30;tem2=(temper%100/10)+0x30;tem3=(temper%100%10)+0x30;
}
void tiaojie()                                         //光标调节时间模块
{ static u8 flag=0;       if(k1==0)                                           //检测到K1按下一段时间后,开始调节光标{   delay(30000);if(k1==0){beepon();                                                 //因为会关闭中断并且停秒,所以给软件补偿buchang值清0buchang=0;  while(1){ ET0=0; pdtian1();                                       //此时中断已关闭,开始循环判断pdxingqi1();                                       //判断天数与星期,比如在将时间调到3月31号后再调到2月zhuanhuan();                                    if(o>tianmax)o=tianmax;write_week();                                     //天数就会自动调节到28日,确保不会超出范围,并自动调出星期write_tian();if(k4==0)                                                           //如果按下K4,就停止时间光标调节并跳出循环{beepon(); break;}if(flag==0)                                //flag调节位置判断位{ write_miao();delay(5000);write_com(0x87+0x40);write_data(0xff);delay(5000);if(k2==0){                                    //此时调秒beepon();if(k<59)  k+=1;else  k=0;}if(k3==0){beepon(); if(k>0) k-=1;else k=59;} if(k1==0){beepon();flag+=1; }write_miao();}if(flag==1)                                      //此时调分{  write_fen();delay(5000);write_com(0x84+0x40);write_data(0xff);delay(5000);if(k2==0){beepon(); if(e<59) e+=1;else e=0;    }if(k3==0){beepon();if(e>0)  e-=1;else    e=59;}if(k1==0){ beepon();flag+=1;     }write_fen();} if(flag==2)                                          //此时调时{  write_shi();delay(5000);write_com(0x81+0x40);write_data(0xff);delay(5000);if(k2==0){beepon(); if(d<23) d+=1;else  d=0; }if(k3==0){beepon();if(d>0) d-=1;else   d=23;}if(k1==0){beepon();flag+=1;}write_shi();}if(flag==3)                                      //此时调天   天、月、年会影响星期,所以在这里加入判断星期模块{ write_tian();delay(5000);write_com(0x89);write_data(0xff);delay(5000);if(k2==0){beepon(); if(o<tianmax)o+=1;else o=1;    }if(k3==0){beepon();pdtian1();if(o>1)o-=1;else    o=tianmax;}if(k1==0){ beepon();flag+=1;}write_tian();}if(flag==4){   write_yue();                                                //此时调月delay(5000);write_com(0x86);write_data(0xff);                                //循环闪烁光标delay(5000);if(k2==0){beepon();if(p<12)p+=1;else p=1;     }if(k3==0){beepon();if(p>1)p-=1; elsep=12;if(o>tianmax)o=tianmax;}if(k1==0){beepon(); flag+=1; }write_yue();}if(flag==5){     write_nian();                               //此时调年delay(5000);write_com(0x83);write_data(0xff);delay(5000);if(k2==0){ beepon();if(y<9999)y+=1;elsey=1; }if(k3==0){beepon(); if(y>0)y-=1;else y=9999;}if(k1==0){beepon();flag=0;}write_nian(); }//调节完毕并且K4确认后打开中断允许,开始走时}}   }ET0=1;}
void beiguangpd()                                         //背光判断模块
{if(k1==0||k2==0||k3==0|k4==0){ if(bg==1)                                        //如果再背光熄灭的情况下 ,按下任何键都会打开背光并响铃beepon();beiguang=0;                                    //无论是否熄灭,按下都会清零}if(beiguang==60)                      //如果检测到没有按键60S,背光自动熄灭bg=1;else bg=0;
}
void main()                                   //主函数
{     bg=0;y=2017;p=5;o=25;DHT11_receive(); temper=ReadTemperature();welcome();                                    //欢迎NZdisplay();                                   //断电后第一个调节闹钟init();   Timer0Init();                               //初始化定时器,但是没有打开ET0                             ET0=1;                             init();                                     //调节完毕后延时初始化并延时足够时间,确保不会乱码delay(50000);while(1)                                       //循环各个模块且不会冲突{ zhuanhuan();                                   bijiao();tiaojie();naozhongfamen();wendufamen();miaobiao();pdtian1();pdxingqi1();Display();}
}
void write_week()                                //1602写并显示星期模块
{  static u8 i; switch (wk){case(1):for(i=0;i<5;i++){ write_com(0x8b+i);write_data(week1[i]);}break;case(2):for(i=0;i<5;i++){ write_com(0x8b+i);write_data(week2[i]);}break;case(3):for(i=0;i<5;i++){ write_com(0x8b+i);write_data(week3[i]);}break;case(4):for(i=0;i<5;i++){ write_com(0x8b+i);write_data(week4[i]);}break;case(5):for(i=0;i<5;i++){ write_com(0x8b+i);write_data(week5[i]);}break;case(6):for(i=0;i<5;i++){ write_com(0x8b+i);write_data(week6[i]);}break;case(0):for(i=0;i<5;i++){ write_com(0x8b+i);write_data(week7[i]);}break;}
}
void write_nian()                        //1602写并显示年模块
{write_com(0x80);write_data(nian1);write_com(0x81);write_data(nian2);write_com(0x82);write_data(nian3);write_com(0x83);write_data(nian4);
}
void write_yue()                                  //1602写并显示月模块
{ write_com(0x85);write_data(yue1);write_com(0x86);write_data(yue2);
}
void write_tian()                         //1602写并显示天模块
{write_com(0x88);write_data(tian1);write_com(0x89);write_data(tian2);
}
void write_shi()                             //1602写并显示时模块
{write_com(0x80+0x40);write_data(shi1);write_com(0x81+0x40);write_data(shi2);
}
void write_fen()                              //1602写并显示分模块
{write_com(0x83+0x40);write_data(fen1);write_com(0x84+0x40);write_data(fen2);
}
void write_miao()                             //1602写并显示秒模块
{write_com(0x86+0x40);write_data(miao1);write_com(0x87+0x40);write_data(miao2);
}
void write_temp()                            //1602写并显示温度报警设置模块
{ static i;for(i=0;i<13;i++){write_com(0x82+i);write_data(tempwarng[i]);}for(i=0;i<3;i++){write_com(0x80+i+0x40);write_data(temmin[i]);}write_com(0x83+0x40);write_data(0x7e);for(i=0;i<3;i++){write_com(0x8d+i+0x40);write_data(temmax[i]);}write_com(0x8c+0x40);write_data(0x7f);write_com(0x85+0x40);write_data(tempwarn/100+0x30);write_com(0x86+0x40);write_data((tempwarn%100/10)+0x30);write_com(0x87+0x40);write_data('-');write_com(0x88+0x40);write_data(tempwarn1/100+0x30);write_com(0x89+0x40);write_data((tempwarn1%100/10)+0x30);
}
void nzON()                                           //1602写并显示闹钟设置打开及关闭模块
{ static u8 i;if(nxflag==0)
{    for(i=0;i<3;i++){write_com(0x8b+0x40+i);write_data(naozhongOFF[i]);}}if(nxflag==1)
{    for(i=0;i<3;i++){write_com(0x8b+0x40+i);write_data(naozhongON[i]);}}
}
void write_setsuccess()                                   //1602写并显示设置成功
{static u8 i;for(i=0;i<12;i++){write_com(0x82+i);write_data(setsucces[i]);}for(i=0;i<16;i++){write_com(0x80+i+0x40);write_data(thanksu[i]);}
}
void write_nz()                                           //1602写并显示闹钟设置模块
{     static u16 n1,n2,m1,m2,i;   n1=(n/10)+0x30;n2=(n%10)+0x30;m1=(m/10)+0x30;m2=(m%10)+0x30;for(i=0;i<16;i++){write_com(0x80+i);write_data(set[i]);}write_com(0x82+0x40);write_data(n1);write_com(0x83+0x40);write_data(n2);write_com(0x84+0x40);write_data(':');write_com(0x85+0x40);write_data(m1);write_com(0x86+0x40);write_data(m2);
}

基于LCD1602的多功能万年历,温湿度计,非RTC时钟芯片单片机技术相关推荐

  1. 基于单片机多功能万年历系统毕业设计(完整资料)

    基于单片机的多功能万年历的设计实现功能如下: 1.主控芯片STC15W408AS 单片机: 2.具有公历农历显示或转换: 3.温度测试: 4.整点报时: 5.可以遥控控制: 6.节假日提示. [资源下 ...

  2. 51单片机进阶案例(1)——基于MATLAB GUI的单片机串口与PC的通信实现实时时钟和双向可调时钟功能(利用DS1302时钟芯片和LCD1602液晶屏)

    目录 一.案例描述 二.实现功能 三.51单片机部分实现 3.1 实时时钟的实现 3.2 串口通信的实现 3.2.1 接收数据 3.2.2 发送数据 四.MATLAB部分实现 4.1 GUI界面 4. ...

  3. 基于STM32与3264点阵屏的多功能万年历

    基于STM32与3264点阵屏的多功能万年历 一.前因 一次偶然的机会,笔者得到了一块二手的3264双色点阵屏,一番把玩过后发现这个屏幕的显示效果还是很棒的,就萌生了一个用这块屏diy的想法,思来想去 ...

  4. 基于AT89C52单片机的多功能万年历设计

    点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87853675 源码获取 目 录 摘 ...

  5. 基于matlab的电子时钟,基于LCD1602电子时钟毕业设计报告.doc

    PAGE PAGE 32 PAGE \* MERGEFORMAT 0 信息与电子工程学院课程设计报告 课 程单片机技术应用设计题目基于LCD1602电子时钟专 业班 级成 员姓 名学 号分工成 绩指导 ...

  6. CASE_02 基于FPGA的数字钟万年历

             该系类博客序言和资源简介可浏览该博客:PREFACE FPGA经典案例序言 快速了解该系列博客的内容与可用 资源. 目录 1 简介 2 数字钟计数方案 2.1 计数方案一 2.2 计 ...

  7. 基于nginx实现缓存功能及uptream模块详细使用方法

    基于nginx实现缓存功能及uptream模块详细使用方法 一般情况下,前端使用nginx做代理或7层负载并向后实现varish/squid做cache server的效果要好的多 nginx与squ ...

  8. 本科项目——51单片机多功能万年历

    源程序下载地址:http://download.csdn.net/detail/cxp2205455256/8183217 设计报告下载地址:http://download.csdn.net/deta ...

  9. 基于AD9850的多功能信号发生器

    基于AD9850的多功能信号发生器设计与实现 课程名称:多功能信号发生器设计 专    业:电子信息工程 班    级: 姓    名: 学    号: 指导老师: 成    绩: 2022年春 摘要 ...

最新文章

  1. [置顶] 单例模式lua实现
  2. 如何将伪数组转换成数组
  3. android自带中文字体,Android更换系统默认显示的字体使用自定义字体
  4. 笔试小结---线程、进程
  5. php fpm 安装配置,php php+fpm安装配置
  6. 解决DatePicker中Appbar icon缺失
  7. [转载] python super详解
  8. 基于STM32F103ZET6 HC_SR501人体红外感应
  9. 计算机485通讯原理图,485通讯接线图.pdf
  10. java web程序设计郭_Java Web程序设计-(第2版)
  11. 使用Python编写获取QQ群成员昵称及号码的小工具
  12. 企业如何从CMMI3升级为CMMI5,有哪些优势?
  13. 美团外卖红包,商超生鲜红包,饿了么红包天天领,果蔬抢特价,大额满减券
  14. python进行数据处理——pandas的drop函数
  15. Spring Boot使用RabbitMQ出现诡异异常:Failed to send reply with payload 'OK',Cannot determine ReplyTo message
  16. 【FPGA】四、按键消抖
  17. 微信小程序wx.request封装
  18. Azkaban重新编译,解决:Could not connect to SMTP host: smtp.163.com, port: 465【2022年01月10日】
  19. Linux的网卡配置 vi /etc/sysconfig/network-scripts/ifcfg-ens33
  20. Node.js项目中动态加载环境变量配置

热门文章

  1. 大数据的特征(4V)
  2. 阿里云服务器ECS windows server已开放端口但连不上的问题
  3. Qt编写自定义控件37-发光按钮(会呼吸的痛)
  4. Excel中批量生成标签,批量打印标签。按指定模板批量打印标签
  5. omf多路径 oracle_Oracle OMF 功能详解
  6. 修复版动态视频壁纸微信小程序源码下载,支持多种类型流量主收益
  7. 【动手学MVG】ICP算法原理和代码实现
  8. 对敏捷管理模式核心价值的解读
  9. 如何取消U盘上的设备加密功能Bitlocker——win10家庭版磁盘上有个锁的解决办法——详细操作版本
  10. 1083 Windy数(数位dp)