带温度测试的万年历

合集下载

带温度显示的万年历_数码管显示(附电路图和源代码)

带温度显示的万年历_数码管显示(附电路图和源代码)

设计报告设计任务:设计一个智能化万年历时钟电路,LED数码管作为电路的显示部分,按钮开关作为调时部分,通过与单片机连接数码管动态显示年、月、日、时、分、秒、星期、温度。

并能准确计算闰年闰月的显示。

设计要求:通过与单片机连接数码管动态显示年、月、日、时、分、秒、星期等功能,并能准确计算闰年闰月的显示,三个个按钮连接P3.0、P3.1、P3.2可以精确调整每一个时间数值,通过对所设计的万年历时钟电路进行实验测试,达到了动态显示时间,随时调整时间等技术所连线路和单片机接口仿真图如图3所示:图3 仿真按键4)温度采集部分:DS18B20温度传感器,测温范围-55℃~+125℃,固有测温分辨率0.5℃。

独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。

DS18B20的采集数据通过DQ传入单片机,单片机读取数据后将数据输出!如图所示:程序如下:ReadOneChar(void){unsigned char i=0;// 定义i用于循环unsigned char dat = 0;// 读取的8位数据for (i=8;i>0;i--)//8次循环{DQ = 0;// 拉低DQ总线开始读时序dat>>=1;// dat左移一位DQ = 1; //释放DQ总线if(DQ)// 如果DQ=1,执dat|=0x80;(0x80即第7位为1,如果DQ为1,即读取的数据为1,将dat的第7为置1,然后dat>>=1,循环8次结束,dat 即为读取的数据)//DQ=0,就跳过dat|=0x80;Tdelay(4);// 延时以完成此次读时序,之后再读下一数据}return(dat); 返回读取的dat}//写一个字节WriteOneChar(unsigned char dat){unsigned char i=0;//for (i=8; i>0; i--)//{DQ = 0;//DQ = dat&0x01;//Tdelay(5);//延时以完成此次读时序,之后再读下一数据DQ = 1;//dat>>=1;//}}//读取温度ReadTemperature(void){unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;//Init_DS18B20();WriteOneChar(0xCC);// 写指令,跳过ROM,WriteOneChar(0x44);// 启动温度转换Init_DS18B20();WriteOneChar(0xCC);// 写指令,跳过ROM,WriteOneChar(0xBE);// 写指令,读暂存存储器a=ReadOneChar();//读低8位b=ReadOneChar();//读高8位t=b;//t<<=8;//t=t|a;//tt=t*0.0625;//t= tt*10+0.5;//return(t); //获得0.01°C 的精度并返回}LED数码管的选择LED数码管分为共阴和共阳两种,以利用STC89C51的P0口作为LED显示的数据部分,以P2口的七个口作为显示部分的位选,通过三八译码器和4-16译码器扩展为17位的位选分别接在一个四位数码管和13个数码管的位选部分。

单片机万年历温度检测C程序(1302+1820+1602+51)

单片机万年历温度检测C程序(1302+1820+1602+51)

1302+1820+1602+51万年历#include<reg51.H>#include<INTRINS.H>#define uchar unsigned char#define uint unsigned int#define TIME (0X10000-50000)#define FLAG 0XEF //闹钟标志//引脚连接图sbit rst=P3^5;sbit clk=P3^4;sbit io=P3^3;sbit rs=P1^5;sbit rw=P1^6;sbit e=P1^7;sbit DQ=P1^4; //温度输入口sbit beep=P3^2;sbit ACC_7=ACC^7;//全局变量及常量定义uchar i=20,j,time1[16];uchar alarm[2],time2[15],time[3];uchar code Day[]={31,28,31,30,31,30,31,31,30,31,30,31};//12个月的最大日期(非闰年)//音律表uint code table1[]={64260,64400,64524,64580,64684,64777,64820,64898,64968,65030,65058,65110,65157,65178,65217};//发声部分的延时时间uchar code table2[]={0x82,1,0x81,0xf4,0xd4,0xb4,0xa4,0x94,0xe2,1,0xe1,0xd4,0xb4,0xc4,0xb4,4,0};//LCD自建字uchar 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};//日//*******温度小数部分用查表法**********//uchar codeditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x0 7,0x08,0x08,0x09,0x09};//闹钟中用的全局变量uchar th1,tl1;uchar temp_ioa[2]={0x00,0x00}; // 读出温度暂放bit flag; //18b20存在标志位/***********11微秒延时函数**********/delay(uint t){for(;t>0;t--);}/***********18B20复位函数**********/ow_reset(void){uchar i;DQ=1;_nop_();_nop_();DQ=0; //delay(50); // 550usDQ=1; //delay(6); // 66usfor(i=0;i<0x30;i++){if(!DQ)goto d1;}flag=0; //清标志位,表示ds1820不存在DQ=1;return;d1: delay(45); //延时500usflag=1;DQ=1; //置标志位,表示ds1820存在}/**********18B20写命令函数*********///向 1-WIRE 总线上写一个字节void write_byte(uchar val){uchar i;for (i=8; i>0; i--) //{DQ=1;_nop_();_nop_();DQ=0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us DQ=val&0x01; //最低位移出delay(6); //66usval=val/2; //右移一位}DQ=1;delay(1);}/*********18B20读1个字节函数********///从总线上读取一个字节uchar read_byte(void){uchar i;uchar value=0;for (i=8;i>0;i--){DQ=1;_nop_();_nop_();value>>=1;DQ=0; //_nop_();_nop_();_nop_();_nop_(); //4usDQ=1;_nop_();_nop_();_nop_();_nop_(); //4usif(DQ)value|=0x80;delay(6); //66us}DQ=1;return(value);}/***********读出温度函数**********/read_temp(){ow_reset(); //总线复位if(!flag) //判断ds1820是否存在?若ds18b20不存在则返回 return;//write_byte(0xCC); // Skip ROM//write_byte(0x44); // 发转换命令//delay(70);write_byte(0xCC); //发Skip ROM命令write_byte(0xBE); //发读命令temp_ioa[0]=read_byte(); //温度低8位temp_ioa[1]=read_byte(); //温度高8位ow_reset();write_byte(0xCC); // Skip ROMwrite_byte(0x44); // 发转换命令}/***********温度数据处理函数**********/work_temp(){uchar n=0,m;if(temp_ioa[1]>127)//负温度求补码{temp_ioa[1]=(256-temp_ioa[1]);temp_ioa[0]=(256-temp_ioa[0]);n=1;}time2[13]=ditab[temp_ioa[0]&0x0f]+'0';time2[12]='.';m=((temp_ioa[0]&0xf0)>>4)|((temp_ioa[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;}elsetime2[10]=0x20;if(time2[11]=='0'&&time2[13]=='0')time2[11]=time2[12]=0x20;}}}delay1ms(uchar time) //延时1ms{uchar i,j;for(i=0;i<time;i++){for(j=0;j<250;j++);}}//LCD驱动部分enable(){rs=0;rw=0;e=0;delay1ms(3);e=1;}write2(uchar i){P0=i;rs=1;rw=0;e=0;delay1ms(2);e=1;}write1(uchar data *address,m) {uchar i,j;for(i=0;i<m;i++,address++) {j=*address;write2(j);}}//LCD显示lcdshow(){P0=0XC; //显示器开、光标关enable();P0=0x80; //写入显示起始地址enable();write1(time1,16);P0=0xc1; //写入显示起始地址enable();write1(time2,15);}//自建字zijianzi(){uchar i;P0=0x40;enable();for(i=0;i<32;i++){write2(tab[i]);delay1ms(2);}}//DS1302读写子程序write(uchar address){uchar i;clk=0;_nop_();rst=1;_nop_();for(i=0;i<8;i++){io=address&1;_nop_();clk=1;address>>=1;clk=0;}}uchar read(){uchar i,j=0;for(i=0;i<8;i++){j>>=1;_nop_();clk=0;_nop_();if(io)j|=0x80;_nop_();clk=1;}return(j);}//部分显示数据初始化timestart(){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]=':';write(0xc1);alarm[0]=read();rst=0;write(0xc3);alarm[1]=read();rst=0;write(0xc5);time1[0]=read();rst=0;}//读取时间readtime(){uchar i,m,n;write(0x8d); //读取年份m=read();rst=0;time1[4]=m/16+0x30;time1[5]=m%16+0x30;write(0x8b); //读取星期m=read();rst=0;time1[15]=m+0x30;for(i=7,n=0x89;i<11;i+=3,n-=2) //读取月份和日期{write(n);m=read();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++) //读取时,分,秒{write(n);time[m]=read();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;beep=!beep;}showalarm(){uchar 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;}//根据日期的变动自动调整星期uchar setweek(){uchar 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(){uchar i=0x85,year,month,day,n;time2[6]=time2[7]=0x30,time1[14]=time1[15]=0x20; lcdshow();while(1){P0=0xe; //显示器开、光标开enable();P0=i; //定光标enable();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){write(0x8c);write((time1[4]&0xf)*16+(time1[5]&0xf));rst=0;write(0x8a);write(setweek());rst=0;for(i=7,n=0x88;i<11;i+=3,n-=2){write(n);write((time1[i]&0xf)*16+(time1[i+1]&0xf)); rst=0;}for(i=0;i<7;i+=3,n-=2){write(n);write((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(){uchar 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; //显示器开、光标开enable();P0=i; //定光标enable();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){write(0xc0);write((time2[0]&0xf)*16+(time2[1]&0xf)); rst=0;write(0xc2);write((time2[3]&0xf)*16+(time2[4]&0xf)); rst=0;time1[0]=FLAG;write(0xc4);write(time1[0]);rst=0;TR0=0;timestart();return;}else{TR0=0;timestart();return;}}}if(j==0){TR0=0;timestart();return;}}}main(){IE=0X82;TMOD=0x11;write(0x8E); //禁止写保护write(0);rst=0;P0=1; //清屏并光标复位enable();P0=0X38; //设置显示模式:8位2行5x7点阵enable();P0=6; //文字不动,光标自动右移enable();zijianzi(); //自建字timestart();while(1){readtime(); //读取时间read_temp(); //读出18B20温度数据 work_temp(); //处理温度数据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;elsetime1[0]=FLAG;write(0xc4);write(time1[0]);rst=0;}}}delay1ms(100);}}单片机万年历——基于1302和1602(1篇)2009-12-06 21:191302和1602的接法在我相册里面使用1602液晶显示DS1302+c51时钟[注12M晶振]=============================================================*/#include <AT89x52.h>#include <string.h>#include < intrins.h >#define delayNOP() ; {_nop_() ;_nop_() ;_nop_() ;_nop_() ;} ;#define LCM_RW P3_1 //定义引脚#define LCM_RS P3_0#define LCM_E P3_2#define LCM_Data P0#define Busy 0x80 //用于检测LCM状态字中的Busy标识#define uchar unsigned charsbit T_CLK=P2^4;sbit T_IO =P2^5;sbit T_RST=P2^6;sbit ACC0=ACC^0;sbit ACC7=ACC^7;sbit system=P1^1; //模式sbit TimerUp=P1^2; //时间加sbit TimerDown=P1^0; //时间减sbit Speaker=P2^1; //蜂鸣器void Set(uchar,uchar); //根据选择调整相应项目void RTInputByte(uchar); //输入 1Byte */uchar RTOutputByte(void); //输出 1Byte */void W1302(uchar, uchar); //向DS1302写入一个字节uchar R1302(uchar); //从DS1302读出一个字节void Set1302(uchar * ); //设置时间void KeySound(); //按键音void ClockSound(); //闹铃蜂鸣声uchar id,msec,model,LedTime,d;bit a,b; //闪烁标志位uchar inittime[7]={0x00,0x10,0x19,0x29,0x03,0x04,0x06}; //初始化后设置为:06年3月29日星期3 19点10分0秒void Out_LCM(void); //显示屏幕void model0(void); //显示输出void model1(void);void model2(void);void model3(void);void model4(void);void model5(void);void model6(void);void id_case1_key(); //项目调整void Modset(); //模式键处理void WriteDataLCM(uchar WDLCM);void WriteCommandLCM(uchar WCLCM,BuysC);uchar ReadStatusLCM(void);void LCMInit(void);void OutputInformation(uchar X, uchar Y, uchar DData);void DisplayListChar(uchar X, uchar Y, uchar code *DData);void Delay5Ms(void);void Delay400Ms(void);void systemsetup(void); //进入系统设置uchar code systemp[]={"System.setup"}; //字符串输出(系统设定)uchar code TIMER[]={"Time"}; //字符串输出(时间)uchar code DATE[]={"Date"}; //字符串输出(日期)uchar code alarmclock[]={"Clock"}; //字符串输出(闹铃)uchar code lamp[]={"Lamp"}; //字符串输出(背光灯)uchar code reset[]={"Reset"}; //字符串输出(时间归零)uchar code exit[]={"Exit"}; //字符串输出(退出)uchar code set[]={"Set"}; //字符串输出(设置)uchar code sec[]={"sec"}; //字符串输出(秒)uchar code ClockSet[]={"ClockSet"}; //字符串输出(闹铃设置)uchar code ClockOn[]={"ON"}; //字符串输出(ON)uchar code ClockOff[]={"OFF"}; //字符串输出(OFF)void timesetup(void); //时间设置void datesetup(void); //日期设置void alarmclockset(void); //闹铃设置void lampsetup(void); //背光灯设置void timereset(void); //时间清零/*******************************************************************/ void delay1(int ms){unsigned char y ;while(ms--){for(y = 0 ; y<250 ; y++){_nop_() ;_nop_() ;_nop_() ;_nop_() ;}}}void main(void){Speaker=1; //关闭蜂鸣器LED=0; //打开LED ,低电平有效,外接9012驱动Delay400Ms(); //启动等待,等LCM讲入工作状态Delay400Ms();LCMInit(); //LCM初始化TMOD=0x01; //16位定时TH0=0x3c; //50msTL0=0xb0;EA=1;TR0=1;ET0=1;while(1){if(TimerDown==0) //左移键按下后把背光灯打开{Delay5Ms();if(TimerDown==0){KeySound(); //蜂鸣声LED=0; //打开背光灯LedTime=R1302(0xc1)/16*10+R1302(0xc1)%16;} //取出背光灯时间并转换为十进制数}b=1; //模式键是否动作标志。

带温度计的万年历

带温度计的万年历

设计课题题目: 带温度计的万年历一、设计任务与要求1. 显示准确的北京时间(时、分、秒)及公历日期显示功能(年、月、日);2. 可通过按键切换年、月、日及时、分、秒的显示状态;3. 可随时可以调校年、月、日或时、分、秒;4. 可每次增减一进行时间调节,也可快速增减进行时间调节;5.可显示环境温度。

二、系统设计方案方案一、用主芯片为AT89C51的单片机控制实现,使用单片机内部的定时计数器实现时间的设定,使用按键进行时间的调整和定时,按键有蜂鸣器提示,温度传感器使用DALLAS 公司生产的单总线式数字温度传感器,它具有微型化、低功耗、高性能、抗干扰能力强、易配处理器等优点。

显示时间和温度使用数码管显示。

方案二、用主芯片为STC89C52的单片机控制实现,为了满足单片机系统的实时控制的需求,采用实时钟芯片DS1302,使用按键进行时间的调整和定时,温度传感器使用 DS18B20。

显示时间和温度使用LCD1602显示。

方案一片内定时器会导致计时节拍的时间误差,当进行年、月、日的日历计时,定时中断误差扥积累就会很大。

使用片内定时器进行计时的时候,单片机始终要处于工作状态。

才能维持计时时间,一旦停机或进入待机状态,开机后,计时时间就需要重新设定。

为了满足单片机系统的实时钟需求,本设计采用的是方案二,系统框图如图2-1所示。

图2-1三、单元电路分析与设计1. 原理分析 1.1主控制器单片机STC89C52 具有低电压供电和体积小等特点,如图3-1所示。

1.2晶振电路AT89S52引脚XTAL1和XTAL2与晶体振荡器及电容C1、C2按图3-2所示方式连接。

晶振、电容C1/C2及片内与非门(作为反馈、放大元件)构成了电容三点式振荡器,振荡信号频率与晶振频率及电容C1、C2的容量有关,但主要由晶振频率决定,范围在0~33MHz 之间,电容C1、C2取值范围在5~30pF 之间。

根据实际情况,本设计晶振选择频率为12MHZ ,电容选择30pF 如图3-2。

万年历阴历星期温度

万年历阴历星期温度

#include <reg52.h>#include <string.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit CLK=P1^1; //DS1302时钟线sbit SDA=P1^0; // DS1302数据线sbit RST=P1^2; //DS1302复位线sbit RS=P2^0;//数据/指令选择端口sbit RW=P2^1;//读写端口sbit EN=P2^2;//使能端口sbit K1=P3^4; // 选择sbit K2=P3^5; // 加sbit K3=P3^6; // 减sbit K4=P3^7; // 确定uchar tCount=0;//一年中每个月的天数,2月的天数由年份决定uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};uchar *WEEK[]={"sun","mon","tus","wen","thu","fri","sat"};//周日,周一到周六uchar LCD_DSY_BUFFER1[]={"Date 00-00-00 "}; //LCD显示缓冲uchar LCD_DSY_BUFFER2[]={"Time 00-00-00 "};uchar DateTime[7]; //所读取的日期时间char Adjust_Index=-1; //当前调节的时间:秒,分,时,日,uchar Change_Flag[]="-MHDM-Y";uchar Read_LCD_State();//读LCD状态void LCD_Busy_Wait();//判忙void Write_LCD_Data(uchar dat);//写数据void Write_LCD_Command(uchar cmd);//写命令void Init_LCD();//LCD初始化void Set_LCD_POS(uchar p);//设置显示位置void Display_LCD_String(uchar p,uchar *s);//写字符串void DelayMS(uint x)//延时{uchar i;while(x--) for(i=0;i<120;i++);}uchar Read_LCD_State()//读LCD状态{uchar state;RS=0;RW=1;EN=1;DelayMS(1);state=P0;EN=0;DelayMS(1);return state;}void LCD_Busy_Wait()//判忙{while((Read_LCD_State()&0x08)==0x80);DelayMS(5);}void Write_LCD_Data(uchar dat) //写数据{LCD_Busy_Wait();RS=1;RW=0;EN=0;P0=dat;EN=1;DelayMS(1);EN=0;}void Write_LCD_Command(uchar cmd)//写命令{LCD_Busy_Wait();RS=0;RW=0;EN=0;P0=cmd;EN=1;DelayMS(1);EN=0;}void Init_LCD() //LCD初始化{Write_LCD_Command(0x38); DelayMS(1);Write_LCD_Command(0x01); DelayMS(1);Write_LCD_Command(0x06); DelayMS(1);Write_LCD_Command(0x0C); DelayMS(1);Display_LCD_String(0x00,"zhongzhoudaxue "); // DelayMS(1000);Display_LCD_String(0x40," dian zi ri li ");DelayMS(2000);}void Set_LCD_POS(uchar p){Write_LCD_Command(p|0x80);}void Display_LCD_String(uchar p,uchar *s) {uchar i;Set_LCD_POS(p);for(i=0;i<16;i++){Write_LCD_Data(s[i]);DelayMS(1);}}/*--------------------------向DS1302写入一字节---------------------------*/void DS1302_Write_Byte(uchar x){uchar i;for(i=0;i<8;i++){SDA=x&1;CLK=1;CLK=0;x>>=1;}}/*-------------------------------从DS1302读取一字节--------------------------------*/uchar DS1302_Read_Byte(){uchar i,b,t;for(i=0;i<8;i++){b>>=1;t=SDA;b|=t<<7;CLK=1;CLK=0;}return b/16*10+b%16;}/*-------------------------------从DS1302指定位置数据--------------------------------*/uchar Read_Data(uchar addr){uchar dat;RST=0;CLK=0;RST=1;DS1302_Write_Byte(addr);dat=DS1302_Read_Byte();CLK=1;RST=0;return dat;}/*-------------------------------向DS1302某地址写入数据--------------------------------*/void Write_DS1302(uchar addr,uchar dat){CLK=0;RST=1;DS1302_Write_Byte(addr);DS1302_Write_Byte(dat);CLK=0;RST=0;}/*------------------------------------设置时间------------------------------------*/void SET_DS1302(){uchar i;Write_DS1302(0x8e,0x00);for(i=0;i<7;i++){Write_DS1302(0x80+2*i,(DateTime[i]/10<<4|(DateTime[i]%10)));}Write_DS1302(0x8e,0x80);}/*------------------------------------读取当前时期时间------------------------------------*/void GetTime(){uchar i;for(i=0;i<7;i++){DateTime[i]=Read_Data(0x81+2*i);}}/*------------------------------------时间和日期转换成数字字符------------------------------------*/void Format_DateTime(uchar d,uchar *a){a[0]=d/10+'0';a[1]=d%10+'0';}/*------------------------------------判断是否为闰年------------------------------------*/uchar isLeapYear(uint y){return (y%4==0&&y%100!=0)||(y%400==0);}/*------------------------------------星期转换------------------------------------*/void RefreshWeekDay(){uint i,d,w=5;for(i=2000;i<2000+DateTime[6];i++){d=isLeapYear(i) ? 366 : 365;w=(w+d)%7;}d=0;for(i=1;i<DateTime[4];i++) d+=MonthsDays[i];d+=DateTime[3];DateTime[5]=(w+d)%7+1;}/*------------------------------------年月日时分秒++/--------------------------------------*/void DateTime_Adjust(char x){switch (Adjust_Index){case 6: //年if(x== 1&&DateTime[6]<99) DateTime[6]++;if(x==-1&&DateTime[6]>0) DateTime[6]--;MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29:28;if(DateTime[3]>MonthsDays[DateTime[4]])DateTime[3]=MonthsDays[DateTime[4]];RefreshWeekDay();break;case 4: //月if(x== 1&&DateTime[4]<12) DateTime[4]++;if(x==-1&&DateTime[4]>1) DateTime[4]--;MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29:28;if(DateTime[3]>MonthsDays[DateTime[4]])DateTime[3]=MonthsDays[DateTime[4]];RefreshWeekDay();break;case 3: //日MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29:28;if(x== 1&&DateTime[3]<MonthsDays[DateTime[4]]) DateTime[3]++;if(x==-1&&DateTime[3]>0) DateTime[3]--;RefreshWeekDay();break;case 2: //时if(x== 1&&DateTime[2]<23) DateTime[2]++;if(x==-1&&DateTime[2]>0) DateTime[2]--;break;case 1: //秒if(x== 1&&DateTime[1]<59) DateTime[1]++;if(x==-1&&DateTime[1]>0) DateTime[1]--;break;}}/*------------------------------------定时器每秒刷新LCD显示------------------------------------*/void T0_INT() interrupt 1{TH0=-50000/256;TL0=-50000%256;if(++tCount!=2) return;tCount=0;Format_DateTime(DateTime[6],LCD_DSY_BUFFER1+5);Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+8);Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+11);strcpy(LCD_DSY_BUFFER1+13,WEEK[DateTime[5]-1]);Format_DateTime(DateTime[2],LCD_DSY_BUFFER2+5);Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+8);Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+11);Display_LCD_String(0x00,LCD_DSY_BUFFER1);Display_LCD_String(0x40,LCD_DSY_BUFFER2);}/*------------------------------------键盘中断------------------------------------*/void EX_INT0() interrupt 0{if(K1==0) //选择调整对象:年,月,日,时,分,秒{while(K1==0);if(Adjust_Index==-1||Adjust_Index==1) Adjust_Index=7;Adjust_Index--;if(Adjust_Index==5) Adjust_Index=4;LCD_DSY_BUFFER2[13]='[';LCD_DSY_BUFFER2[14]=Change_Flag[Adjust_Index];LCD_DSY_BUFFER2[15]=']';}elseif(K2==0) // 加{while (K2==0); DateTime_Adjust(1);}elseif(K3==0) // 减{while (K3==0); DateTime_Adjust(-1);}elseif(K4==0) // 确定{while(K4==0);SET_DS1302(); //调整后的时间写入DS1302LCD_DSY_BUFFER2[13]=' ';LCD_DSY_BUFFER2[14]=' ';LCD_DSY_BUFFER2[15]=' ';Adjust_Index=-1;}}/*------------------------------------主程序------------------------------------*/void main(){Init_LCD(); //CLD初始化IE=0x83; // 允许INT0,T0中断IP=0x01;IT0=0x01;TMOD=0x01;TH0=-50000/256;TL0=-50000%256;TR0=1;while(1){if(Adjust_Index==-1) GetTime();}}。

实现日期时间温度的显示万年历

实现日期时间温度的显示万年历

; ――――――――――――――――――――――――――――――― ; 温度值存放单元TEMP_ZH EQU 24H ;实时温度值存放单元TEMPL EQU 25H ;低温度值存放单元TEMPH EQU 26H ;高温度值存放单元TEMP_TH EQU 27H ;高温报警值存放单元TEMP_TL EQU 28H ;低温报警值存放单元TEMPHC EQU 29H ;存十位数 BCD码TEMPLC EQU 2AH ;存个位数 BCD码 ;―――――――――――――;======按键输入引脚定义======K1 EQU P3.2K2 EQU P3.3K3 EQU P3.6K4 EQU P3.7;SPK EQU P3.5RELAY EQU 2FH;------------------------------------;=====DS1302通信引脚定义=====RST BIT p1.6SCLK BIT p1.4IO BIT p1.5;=====定义数据存储地址========DS1302_ADDR DATA 30H ;地址寄存器DS1302_DATA DATA 31H ;数据寄存器TIME_YEAR DATA 32H ;年寄存器TIME_MONT DATA 33H ;月寄存器TIME_DAY DATA 34H ;天寄存器WEEK_DATA DATA 35H ;星期寄存器HOUR DATA 36H ;小时寄存器MINTUE DATA 37H ;分钟寄存器SECOND DATA 38H ;秒钟寄存器;=========显示数据缓冲地址============YEAR_HBUF DATA 40HYEAR_LBUF DATA 41HMONT_HBUF DATA 42HMONT_LBUF DATA 43HDAY_HBUF DATA 44HDAY_LBUF DATA 45HWEEK_HBUF DATA 46HWEEK_LBUF DATA 47HHOUR_HBUF DATA 48HHOUR_LBUF DATA 49HMINTUE_HBUF DATA 4AHMINTUE_LBUF DATA 4BHSECOND_HBUF DATA 4CHSECOND_LBUF DATA 4DH;===============================================X EQU 2FH ;LCD 地址变量 ;―――――――――――――;LCD控制引脚RS EQU P2.4RW EQU P2.5E EQU P2.6 ;―――――――――――――FLAG EQU 20H.0KEY_UD EQU 20H.1DQ EQU p2.7;=============主程序============== MAIN:ACALL SET_LCD ;LCD初始化设置子程序ACALL SET_1302 ;1302初始化TOOP: ACALL RESET_1820 ;调用18B20复位子程序ACALL TEMP_BJ ;显示温度标记"℃"ACALL MEU_OK ;调用显示"OK"信息子程序TOOP2:ACALL RE_TEMP ;调用读取温度数据子程序ACALL SET_DATA ;调用处理显示温度数据子程序ACALL TEMP_BJ ;显示温度标记子程序LCALL RD_DS1302LCALL DATA_BUFLCALL DISPLAYSJMP TOOP2 ;循环;--------――读取温度数据子程序--------――RE_TEMP:ACALL RESET_1820 ;18B20复位子程序MOV A,#0CCH ;跳过ROM匹配ACALL WRITE_1820 ;写入子程序MOV A,#44H ;发出温度转换命令ACALL WRITE_1820 ;调写入子程序ACALL RESET_1820 ;调复位子程序MOV A,#0CCH ;跳过ROM匹配ACALL WRITE_1820 ;写入子程序MOV A,#0BEH ;发出读温度命令ACALL WRITE_1820 ;写入子程序ACALL READ_1820 ;调用读取子程序RET;--------温度数据处理显示子程序----------SET_DATA:ACALL CONV_TEMP ;处理温度 BCD 码子程序ACALL DISP_BCD ;显示区 BCD 码温度值刷新子程序ACALL CONV ;LCD显示子程序RET;―――――――――――――;----------处理温度 BCD 码子程序---------- CONV_TEMP:MOV A,TEMPH ;判温度是否零下ANL A,#80HJZ TC1 ;温度零转TC1处CLR C ;C=0MOV A,TEMPL ;二进制数求补(双字节)CPL A ;取反加1ADD A,#01HMOV TEMPL,AMOV A,TEMPHCPL AADDC A,#00HMOV TEMPH,AJMP TC2;―――――――――――――TC1: MOV TEMPHC,#0AHTC2: MOV A,TEMPHCSWAP A ;高、低位交换MOV TEMPHC,AMOV A,TEMPLANL A,#0FH ;乘0.0625MOV DPTR,#DOTTABMOVC A,@A+DPTRMOV TEMPLC,A ;TEMPLC LOW=小数部分 BCD ;―――――――――――――MOV A,TEMPL ;整数部分ANL A,#0F0H ;取出高四位SWAP A ;高、低位交换MOV TEMPL,AMOV A,TEMPHANL A,#0FH ;取出低四位SWAP A ;高、低位交换ORL A,TEMPL ;重新组合MOV TEMP_ZH,ALCALL HEX2BCD1MOV TEMPL,AANL A,#0F0H ;取出高四位SWAP A ;高、低位交换ORL A,TEMPHC ;TEMPHC LOW = 十位数 BCD MOV TEMPHC,AMOV A,TEMPLANL A,#0FH ;取出低四位SWAP A ;高、低位交换ORL A,TEMPLC ;TEMPLC HI = 个位数 BCD MOV TEMPLC,AMOV A,R4JZ TC3ANL A,#0FH ;取出低四位SWAP A ;高、低位交换MOV R4,AMOV A,TEMPHC ;TEMPHC HI = 百位数 BCDANL A,#0FH ;取出低四位ORL A,R4MOV TEMPHC,ATC3: RET;―――――――――――――HEX2BCD1:MOV B,#064H ;十六进制-> BCDDIV AB ;B= A % 100MOV R4,A ;R4 = 百位数MOV A,#0AHXCH A,BDIV AB ;B = A % BSWAP A ;高、低位交换ORL A,BRET;―――――――――――――; 小数部分码表DOTTAB:DB 00H,00H,01H,01H,02H,03H,03H,04HDB 05H,05H,06H,06H,07H,08H,08H,09H;--------显示区BCD 码温度值刷新子程序-------- DISP_BCD:MOV A,TEMPLC ;个位数BCD码送入AANL A,#0FH ;取低位码MOV 70H,A ;小数位MOV A,TEMPLCSWAP A ;高、低位交换ANL A,#0FH ;取结果数的高位MOV 71H,A ;个位MOV A,TEMPHCANL A,#0FH ;取低位码MOV 72H,A ;十位MOV A,TEMPHCSWAP A ;高、低位交换ANL A,#0FH ;取结果数的高位MOV 73H,A ;百位MOV A,TEMPHCANL A,#0F0H ;取低位码CJNE A,#010H,DI0JMP DI2;―――――――――――――DI0: MOV A,TEMPHCANL A,#0FH ;取低位码JNZ DI2 ;十位数是0MOV A,TEMPHCSWAP A ;高、低位交换ANL A,#0FH ;取结果数的高位MOV 73H,#0AH ;符号位不显示MOV 72H,A ;十位数显示符号DI2: RET;==================================================;==========读1302子程序=================RD_DS1302:MOV DS1302_ADDR,#8DH ;读DS1302中的年LCALL READ ;调用读DS1302子程序MOV TIME_YEAR, DS1302_DATA ;把读出的年数据存入年寄存器中MOV DS1302_ADDR,#8BH ;读DS1302中的星期LCALL READMOV WEEK_DATA, DS1302_DATA ;把读出的星期数据存入星期寄存器中MOV DS1302_ADDR,#89H ;读DS1302中的月LCALL READMOV TIME_MONT, DS1302_DATA ;把读出的月数据存入月寄存器中MOV DS1302_ADDR,#87H ;读DS1302中的天LCALL READMOV TIME_DAY, DS1302_DATA ;把读出的天数据存入天寄存器中MOV DS1302_ADDR,#85H ;读DS1302中的小时LCALL READMOV HOUR, DS1302_DATA ;把读出的天数据存入小时寄存器中MOV DS1302_ADDR,#83H ;读DS1302中的分钟LCALL READMOV MINTUE, DS1302_DATA ;把读出的天数据存入分钟寄存器中MOV DS1302_ADDR,#81H ;读DS1302中的秒钟LCALL READMOV SECOND, DS1302_DATA ;把读出的天数据存入秒钟寄存器中 RET;===========按键子程序=================;=========数据分离后送显示缓存==================DATA_BUF:MOV R0,TIME_YEAR ;年数据分离,送显示缓存LCALL DIVIDE ;调用数据分离子程序MOV YEAR_HBUF,R1MOV YEAR_LBUF,R2MOV R0,TIME_MONT ;月数据分离,送显示缓存LCALL DIVIDEMOV MONT_HBUF,R1MOV MONT_LBUF,R2MOV R0,TIME_DAY ;日数据分离,送显示缓存LCALL DIVIDEMOV DAY_HBUF,R1MOV DAY_LBUF,R2MOV R0,WEEK_DATA ;星期数据分离,送显示缓存LCALL DIVIDEMOV WEEK_HBUF,R1MOV WEEK_LBUF,R2MOV R0,HOUR ;小时数据分离,送显示缓存LCALL DIVIDEMOV HOUR_HBUF,R1MOV HOUR_LBUF,R2MOV R0,MINTUE ;分钟数据分离,送显示缓存LCALL DIVIDEMOV MINTUE_HBUF,R1MOV MINTUE_LBUF,R2MOV R0,SECOND ;秒钟数据分离,送显示缓存LCALL DIVIDEMOV SECOND_HBUF,R1MOV SECOND_LBUF,R2RET;=========日历显示子程序==========;===============年显示===============DISPLAY:MOV A,#10000001B ;设定年第1位的显示地址为第1行,第1列 LCALL WR_COMM ;调用写指令到液晶子程序MOV A, #32H ;数字2的ASCII码LCALL WR_DATA ;调用写数据到液晶子程序MOV A,#10000010B ;设定年第2位的显示地址为第1行,第2列 LCALL WR_COMMMOV A, #30H ;数字0的ASCII码LCALL WR_DATAMOV A,#10000011B ;设定年第3位的显示地址为第1行,第3列 LCALL WR_COMMMOV A, YEAR_LBUF ;年的低位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATAMOV A,#10000100B ;设定年第4位的显示地址为第1行,第4列 LCALL WR_COMMMOV A, YEAR_HBUF ;年的高位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATA; =====================斜线显示========================MOV A,#10000101B ;设定斜线的显示地址为第1行,第5列LCALL WR_COMMMOV A,#2FH ;斜线的ASCII码LCALL WR_DATA;================显示月============MOV A,#10000110B ;设定月第1位的显示地址为第1行,第6列 LCALL WR_COMMMOV A, MONT_LBUF ;月的低位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATAMOV A,#10000111B ;设定月第2位的显示地址为第1行,第7列 LCALL WR_COMMMOV A, MONT_HBUF ;月的高位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATA;=======================斜线显示============================MOV A,#10001000B ;设定斜线的显示地址为第1行,第8列LCALL WR_COMMMOV A,#2FH ;斜线的ASCII码LCALL WR_DATA;==============================天显示=======================MOV A,#10001001B ;设定天第1位的显示地址为第1行,第9列MOV A, DAY_LBUF ;天的低位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATAMOV A,#10001010B ;设定天第2位的显示地址为第1行,第10列 LCALL WR_COMMMOV A, DAY_HBUF ;天的高位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATA;========================星期显示======================MOV A,#10001111B ;设定星期第2位的显示地址为第1行,第13列 LCALL WR_COMMMOV A, WEEK_DATA ;星期的高位缓存数据SUBB A,#1ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATA;=======================小时显示============================MOV A,#11000000B ;设定小时第1位的显示地址为第2行,第0列LCALL WR_COMMMOV A, HOUR_LBUF ;小时的低位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATAMOV A,#11000001B ;设定小时第2位的显示地址为第2行,第1列 LCALL WR_COMMMOV A, HOUR_HBUF ;小时的高位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATA;====================== 冒号的显示==========================MOV A,#11000010B ;设定冒号的显示地址为第2行,第2列LCALL WR_COMMMOV A, #3AH ;冒号的ASCII码LCALL WR_DATA;==================== 分钟显示======================MOV A,#11000011B ;设定分钟第1位的显示地址为第2行,第3列 LCALL WR_COMMMOV A, MINTUE_LBUF ;分钟的低位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATAMOV A,#11000100B ;设定分钟第2位的显示地址为第2行,第4列LCALL WR_COMMMOV A, MINTUE_HBUF ;分钟的高位缓存数据ADD A,#30H ;加30H修正取ASCII码;====================== 冒号的显示===========================MOV A,#11000101B ;设定冒号的显示地址为第2行,第5列LCALL WR_COMMMOV A, #3AH ;冒号的ASCII码LCALL WR_DATA;===================== 秒钟显示=============================MOV A,#11000110B ;设定秒钟第1位的显示地址为第2行,第6列 LCALL WR_COMMMOV A, SECOND_LBUF ;秒钟的低位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATAMOV A,#11000111B ;设定秒钟第2位的显示地址为第2行,第7列 LCALL WR_COMMMOV A, SECOND_HBUF ;秒钟的高位缓存数据ADD A,#30H ;加30H修正取ASCII码LCALL WR_DATARET;―――――――― DS18B20复位初始化子程序――――――――――RESET_1820: ;复位(有具体的时序要求)SETB DQNOPCLR DQ;―――――――――――――;主机发出延时537微秒的复位低脉冲MOV R1,#3DLY: MOV R0,#107DJNZ R0,$DJNZ R1,DLY;―――――――――――――;然后拉高数据线SETB DQNOPNOPNOP;―――――――――――――;等待DS18B20回应MOV R0,#25HT2: JNB DQ ,T5DJNZ R0, T2;―――――――――――――;时序要求延时一段时间T5: MOV R0,#117T6: DJNZ R0,T6;――――――――――――――T7: SETB DQRET;=======================================================;========DS1302初始化===========SET_1302:MOV DS1302_ADDR, #8EH ;写DS1302控制指令MOV DS1302_DATA, #00H ;写数据到DS1302的8E控制寄存器中,允许对其进行写操作LCALL WRITE ;调用写DS1302子程序MOV DS1302_ADDR, #90H ;写DS1302控制指令MOV DS1302_DATA,#0A6H ;写数据到DS1302的90控制寄存器中,对电池涓流充电,充电电流为1.1mALCALL WRITE ;调用写DS1302子程序RET;=========查询忙碌标志============CHECK_BUSY:PUSH ACCBUSY_LOOP:CLR ESETB RWCLR RSSETB EMOV A, p0JB p0.7,BUSY_LOOPPOP ACCLCALL DELRET;----------------------------------------------------------------------------------------------;===========延时程序===================DEL:MOV R6,#5L1:MOV R7,#248DJNZ R7,$DJNZ R6,L1RET;――――――――――写入DS18B20子程序――――――――――― ;写入DS18B20(有具体的时序要求)WRITE_1820:MOV R2,#8 ;一共8位数据CLR C ;C=0WR1:CLR DQ ;总线低位,开始写入MOV R3,#6DJNZ R3,$ ;保持16微秒以上RRC A ;把字节DATA分成8个BIT环移给CMOV DQ, C ;写入一个BITMOV R3,#23DJNZ R3,$ ;等待SETB DQ ;重新释放总线NOPDJNZ R2,WR1 ;写入下一个BITSETB DQ ;释放总线RET ;――――――――――读出DS18B20子程序――――――――――― ;将温度值从DS18B20中读出(有具体的时序要求)READ_1820:MOV R4,#4MOV R1,#TEMPL ;存入25H、26H、27H、28HRE0:MOV R2,#8 ;数据一共有8位RE1:CLR CSETB DQNOPNOPCLR DQ ;读前总线保持为低位NOPNOPNOPSETB DQ ;总线释放 ;―――――――――――――MOV R3,#9DJNZ R3,$ ;延时18微妙MOV C, DQ ;从总线读到一个BIT ;―――――――――――――MOV R3,#23 ;DJNZ R3,$ ;等待50微秒RRC A ;把读得的位值环移给ADJNZ R2,RE1 ;读下一个BITMOV @R1,AINC R1 ; R1内数据递增DJNZ R4,RE0RET;=========== LCD 1602 显示程序=========== ;初始化设置SET_LCD:CLR ECALL INIT_LCD ;初始化 LCDCALL STORE_DATA ;将自定义字符存入LCD的CGRAMRET;----------- LCD 初始化子程序----------- INIT_LCD:MOV A,#38H ;设置8位、2行、5x7点阵ACALL WR_COMM ; 调用写指令子程序ACALL DELAY1 ;调用延时子程序MOV A,#0CH ;开显示,光标不闪烁ACALL WR_COMM ;调用写指令子程序 ;ACALL DELAY1 ;调用延时子程序MOV A,#01H ;清除 LCD 显示屏ACALL WR_COMM ;调用写指令子程序 ;ACALL DELAY1 ;调用延时子程序RET;----------显示温度标记子程序----------- TEMP_BJ:MOV A, #0CEH ;设定第二行起始地址ACALL WR_COMM ;调用写指令子程序MOV DPTR,#BJ ;存代码表MOV R1 ,#0 ;使指针指到表中第一个码MOV R0 ,#2 ;取码次数Tp0:MOV A,R1 ;A为0MOVC A,@A+DPTR ;取码ACALL WR_DATA ;调用写数据子程序INC R1 ;R1值加1DJNZ R0,Tp0 ;判断是否将代码读取完?RET;―――――――――――――BJ: ;代码表DB 00H,"C";-----------自定义字符子程序----------- ;将自定义字符写入LCD1602的CGRAM中STORE_DATA:MOV A,#40H ;指定CG RAM起始地址ACALL WR_COMM ;将指令写入LCDMOV R2,#08H ;图形数据长度8个字节MOV DPTR,#TAB ;存代码表MOV R3,#00H ;使指针指到表中第一个码S_D: MOV A,R3 ;A为0MOVC A,@A+DPTR ;读取表代码ACALL WR_DATA ;调用写入数据指令INC R3 ;R3值加1DJNZ R2, S_D ;判断是否将代码读取完?RET ;;―――――――――――――TAB: ;代码表DB 0CH,12H,12H,0CHDB 00H,00H,00H,00H;-----------显示"OK"信息子程序---------MEU_OK:MOV DPTR,#M_OK1 ;指针指到显示消息MOV A,#1 ;显示在第一行ACALL LCD_PRINT ;LCD显示MOV DPTR,#M_OK2 ;指针指到显示消息MOV A,#2 ;显示在第一行ACALL LCD_PRINT ;LCD显示RET;――――――――――――――M_OK1:DB " - - WK: " ,0M_OK2:DB " - - ",0;------―――――菜单显示子程序―――――――----- ;在LCD的第一行或第二行显示字符LCD_PRINT:CJNE A,#1,LINE2 ;判断是否为第一行LINE1:ACALL CLR_LINE ;清除该行字符数据MOV A,#80H ;设置 LCD 的第一行地址ACALL WR_COMM ;写入命令JMP FILLLINE2:ACALL CLR_LINE ;清除该行字符数据MOV A,#0C0H ;设置 LCD 的第二行地址ACALL WR_COMMFILL:CLR A ;填入字符MOVC A,@A+DPTR ;由消息区取出字符CJNE A,#0,LC1 ;判断是否为结束码RETLC1:ACALL WR_DATA ;写入数据INC DPTR ;指针加1JMP FILL ;继续填入字符RET;---------― LCD显示子程序---------- CONV:MOV A,73H ;加载百位数据MOV X,#9 ;设置位置CJNE A,#1,CO1JMP CO2CO1:MOV A,#" "MOV B,XACALL LCDP2JMP CO3CO2:ACALL SHOW_LINE2 ;显示数据CO3: INC X ;位加1MOV A,72H ;十位ACALL SHOW_LINE2 ;显示数据INC X ;位加1MOV A, 71H ;个位ACALL SHOW_LINE2 ;显示数据INC X ;位加1MOV A,#'.'MOV B,XACALL LCDP2 ;显示字符MOV A,70H ;加载小数点位INC X ;设置位置ACALL SHOW_LINE2 ;显示数据RET;-----――显示第二行-----―――;在 LCD 的第二行显示数字SHOW_LINE2:ADD A,#30HMOV B,XACALL LCDP2RETLCDP2: ;在LCD的第二行显示字符PUSH ACC ;放入堆栈MOV A,B ;设置显示地址ADD A,#0C0H ;设置LCD的第二行地址ACALL WR_COMM ;写入命令POP ACC ;由堆栈取出AACALL WR_DATA ;写入数据RET;-----――――――写指令子程序――――――――――-- WR_COMM:MOV p0,A ;写入指令CLR RS ;RS=0,选择指令寄存器CLR RW ;RW=0,选择写模式SETB E ;E=1,允许读/写LCMACALL DELAY1 ;延时5MSCLR E ;E=0,禁止读/写LCMRET;---------―――写数据子程序------------ WR_DATA:MOV p0,A ;写入数据SETB RS ;RS=1,选择数据寄存器CLR RW ;RW=0,选择写模式SETB E ;E=1,允许读/写LCMACALL DE ;延时0.5MSCLR E ;E=0,禁止读/写LCMACALL DE ;延时0.5MSRET;----------清除LCD 的字符------------- CLR_LINE:MOV R0,#24 ;设置计数值CL1: MOV A,#' ' ;载入空格符至LCDACALL WR_DATA ;输出字符至LCDDJNZ R0,CL1 ;判断RET;--------------CLR_LINE1: ;清除LCD的第一行字符MOV A,#80H ;设置 LCD 的第一行地址ACALL WR_COMM ;调用写指令子程序MOV R0,#24 ;设置计数值C1: MOV A,#' ' ;载入空格符至LCDACALL WR_DATA ;输出字符至LCDDJNZ R0,C1 ;计数结束RET;========================================================= ;***********写1302程序*************WRITE:CLR SCLKNOPSETB RSTNOPMOV A,DS1302_ADDRMOV R4,#8WRITE1:RRC A ;送地址给1302NOPNOPCLR SCLKNOPNOPNOPMOV IO,CSETB SCLK ;送入地址在时钟上升沿有效NOPNOPNOPNOPDJNZ R4,WRITE1CLR SCLKNOPMOV A,DS1302_DATAMOV R4,#8WRITE2:RRC ANOP ;送数据给1302,时钟上升沿,数据输入 CLR SCLKNOPNOPMOV IO,CNOPNOPNOPSETB SCLKNOPNOPDJNZ R4,WRITE2CLR RSTCLR ARET;**********读1302程序************READ:CLR SCLKNOPNOPSETB RSTNOPMOV A,DS1302_ADDRMOV R4,#8READ1:RRC ANOPMOV IO,CNOPNOPNOPSETB SCLK ;送入地址在时钟上升沿有效NOPNOPNOPCLR SCLKNOPNOPDJNZ R4,READ1 ;判断8位数据是否传送完?MOV R4,#8READ2:CLR SCLKNOPNOPNOPMOV C,IONOPNOPNOPNOPNOP ;从ds1302中读取数据,时钟下降沿有效 RRC ANOPNOPNOPNOPSETB SCLKNOPDJNZ R4,READ2 ;判断8位数据是否传送完?MOV DS1302_DATA,ACLR RSTRET;==========分离数据子程序=========DIVIDE:MOV A,R0ANL A,#0FH ;屏蔽掉低4位,留下高4位MOV R1,AMOV A,R0SWAP A ;A中数据高4位与低4位互换ANL A,#0FH ;实际上是屏蔽掉了高4位,留下低4位MOV R2,ARET;========延时2秒子程序=============DELAY2:MOV R5,#20D3:MOV R6,#200D2:MOV R7,#250DJNZ R7,$DJNZ R6,D2DJNZ R5,D3RET;-------------鸣响子程序------------SPK_BZ:MOV R6,#100BZ2: ACALL DEX1CPL SPKDJNZ R6,BZ2MOV R5,#10ACALL DELAYRETDEX1: MOV R7,#180DE2: NOPDJNZ R7,DE2RET;-------------延时子程序------------- DELAY: ;延时时间为:R5×10MSDL1: MOV R7,#100DJNZ R7,$DJNZ R6,DL1DJNZ R5,DELAYRET;―――――――――――――DELAY1: ;延时时间为5MSMOV R6,#25DL2: MOV R7,#100DJNZ R7,$DJNZ R6,DL2RET;―――――――――――――DE:MOV R7,#250 ;延时时间为0.5MSDJNZ R7,$RET;-----------――END。

综合设计实验报告模板

综合设计实验报告模板

综合设计实验报告设计题目:课程名称:学生姓名:学号:所在院系:专业:班级:指导教师:目录第一章、前言 (1)第二章、设计要求及实现的功能 (1)2.1 设计要求 (1)2.2 设计实现的功能 (1)第三章、整体设计 (2)第四章、系统详细设计 (2)4.1硬件详细设计. (2)4.1.1主控制系统 (2)4.1.2时钟振荡电路和复位电路 (4)4.1.3 DS1302模块设计 (5)4.1.4 DS18B20模块设计 (6)4.1.5 按键电路 (8)4.1.6 LCD显示电路 (8)4.2 软件详细设计 (9)4.2.1系统软件详细设计 (9)4.2.2 DS1302的时间处理 (9)4.2.3 环境温度采集 (12)4.2.4 系统软件按键检测流程图 (12)第五章、系统仿真及程序编写及调试 (13)5.1 仿真软件介绍 (13)5.2系统硬件PROTEUS仿真原理图 (13)5.3 系统硬件仿真运行情况图 (14)第六章、课程设计总结 (14)第七章、仪器仪表清单 (15)第八章、参考文献 (16)第九章、附录 (16)显示温度的万年历第一章、前言随着科技的快速发展,时间的流逝,至从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。

如今万年历已经在人们生活中广泛的使用,它不仅是记录日期和时间的工具,而且也成为了一种装饰品。

现在的万年历可以说是多种多样,外观精美。

放在家里既可以计时也可作为风景壁画,因此越来越受到大众消费者的喜爱。

美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS1302。

它可以对年、月、日、周日、时、分、秒进行计时,而且DS1302的使用寿命长,误差小。

对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。

在本次设计中,采用单片机STC89C52,辅助以必要的外围电路,用C语言编写程序,并进行模块化设计而成的电子万年历系统。

GC056A万年历操作说明书

GC056A万年历功能简介及操作说明书主要特点:1.IC驱动能力强,外围电路简单,不要74LS1642.整机功耗低,可采用小功率变压器。

2.超强抗干扰能力。

3.驱动效率高,相同的电流比同类IC数码管亮度增加一倍。

4.IC适应电压范围广,便于数码管选用。

一. 功能简介:1.50年同步显示公历年、月、日、上午、下午、时、分、秒、星期、农历月、日、摄氏温度。

2.12/24小时制转换(24小时制时,上/下午的LED指示灯都不亮)3.四种星期显示方式由硬件选择:越南星期(2~8);7个LED星期(外销用途);国内星期(1~6,8),俄罗斯星期(1~7)。

具有年隐含功能(年显示,表示按原理图的位置正常显示年份;年隐含,表示年的四位数平时不显示出来,只在调整年份时显示在时与分上).4.IC功能选择:由原理图中的C1、C2、C3、R1来决定。

特别注意:C1,C2,C3、R1的参数不要随意改动。

C1、C2、C3、R1都不装:年显示,中国星期;C1装,C2、C3、R1都不装:年显示,越南星期;C2装,C1、C3、R1都不装:年显示,星期1~7;C1,C2都装,C3、R1都不装:年显示,7个LED星期;C1、C2都不装,C3、R1都装:年隐含,中国星期;C2不装,C1、C3、R1都装:年隐含,越南星期;C1不装,C2、C3、R1都装: 年隐含,星期1~7;C1、C2、C3、R1都装:年隐含,7个LED星期;5.内置锂电池,市电停电,LED显示关闭,万年历内部能正常走时,功耗是uA级,一块锂电池,可以连续运行6年以上。

重新来电时万年历不需重新设置。

6.温度测量范围:-9到48度,精度为正负1度。

时间误差一天小于1秒。

7.三个按键 S1:快速退出/即时播报键, S2:设置/移动键,S3:修改/ 闹钟开关键。

另提供一个可以选用的硬件复位键。

8.共4组闹钟,共用1个闹钟指示LED,可以在闹钟设置时单独开启或关闭单个闹钟。

第四组闹钟是学生闹钟,设定开启时只有在周一到周五响闹,周六和周日不响。

基于51单片机的万年历与温度检测报警系统

基于51单片机的万年历与温度检测报警系统摘要随着社会发展需求的改变,电子万年历是一个应用非常广泛的实用日常计时工具,带有显示世纪,年,月,日,星期,时,分,秒和按键可调时间及其按键设置闹钟的功能,同时具有月末自动更新,闰年补偿功能等多种功能。

温度检测报警系统也是在日常生活和工业应用非常广泛的工具,能实时采集周围的温度信息进行显示,程序内部设定有报警上下限,根据应用环境不同可设定不同的报警上下限。

此系统是基于STC89C52单片机设计的,包含液晶显示模块,DS12C887实时时钟模块,DS18B20温度采集模块,键盘扫描模块,报警模块,HX1838红外接收头模块。

STC89C52作为控制核心,具有功耗低,功能强等特点,电压可选5VUSB 供电。

显示模块采用12864液晶动态显示,相对数码管而言经济实用,占用空间小,对于显示数字、字母最为合适,而且与单片机连线简单,占用IO口相对较少。

实时时钟芯片DS12C887是一款与DS12C885实时时钟兼容的替代产品,该器件提供RTC/日历、定时闹钟等功能,如果检测到主电源故障,该器件可自动切换到备用电源供电,DS12C887将石英晶体与电池集成在一起,在断电后仍可精确走10年。

温度检测报警模块采用数字式温度传感器DS18B20,该芯片具有精度高,测量范围广等优点,易与单片机连接,模块电路组成简单并同时具有温度报警功能。

关键词:STC89C52,DS12C887,DS18B20,12864液晶显示,电子万年历,采集周围设备温度、温度报警一、设计要求与方案论证1.1设计要求设计一个能够实现世纪,年,月,日,星期,小时,分,秒显示附带温度检测显示的实时时钟电子万年历,同时具有时间调节和闹钟设置功能,以及时间预设报警、温度报警、报警解除等功能。

该产品共设有四个按键,每个按键具有多种功能,充分利用各个按键。

也可利用红外遥控来进行实时调节,体现时尚方便的特性,并且通过编程还可以控制12864液晶显示,随心所欲。

带有温度显示的万年历

.
题目:带温度显示的万年历
物电系通信工程本班 组长: 组员: 组员: 组员: 组员:
.
一、选题目的和意义
二十一世纪的今天,最具代表性的计时产品就是电子万年历,它是近代世界钟表业 界的第三次革命。第三次革命就是单片机数码计时技术的应用(电子万年历),使 计时产品的走时日差从分级缩小到1/600万秒,从原有传统指针计时的方式发展为人 们日常更为熟悉的夜光数字显示方式,直观明了,并增加了全自动日期、星期、温 度以及其他日常附属信息的显示功能,它更符合消费者的生活需求!因此,电子万 年历的出现带来了钟表计时业界跨跃性的进步……
.
本设计所用主要芯片
三、设计的方法及 .
步骤
系统构成框图:整个系统由主控模块和显示模 块两大模块组成,主控模块包括主控芯片、温 度检测、实时时钟电路及键盘接口电路,系统 构成框图如下图所示。
LCD液晶显示 DS1302时钟模块
Stc89c52 控制
模块
键盘 温度采集
.
主程序流程图
开始 初始化
(Y)显示温度
.
演示完毕
感谢老师及团队的协调合作
谢谢!!!
.
DS18B20温度检测流程图
初始化ds18b20 读取温度 温度值转换 LCD显示
.
时间调整部分程序设计
开始
Gongneng是多少
1调秒
2调分
3调时
4调号
5调月
6调年
7调分
8调时
加减
加减加减
加减加减加减加减
加减
Gongneng为0 返回时间显示
.
液晶LCD1602显示部分程序设计流程图
由于程序过多,不能在此显示
我国生产的电子万年历有很多种,总体上来说以研究多功能电子万年历为主,使万 年历除了原有的显示时间,日期等基本功能外,还具有闹铃,报警等功能。商家生 产的电子万年历更从质量,价格,实用上考虑,不断的改进电子万年历的设计,使 其更加的具有市场。

北极星数码万年历使用说明书

北极星数码万年历北极星数码万年历使用说明书操作说明1、按键说明:设置键、上调键、下调键、流水开关键。

2、时间调整在正常走时状态下,按“设置”键进入时间设置状态,同时年份“闪烁”,可按“上调”或“下调”键修改年份,修改好后按“设置”键将闪烁位移到公历“月”,按“上调”或“下调”键修改月份;用同样的方法可对日、时、分进行设置;12个公历节日及倒计天数、24个农历节气及倒计天数、12生肖、12星座、星期、农历月、日将自动跟随公历的变化。

当分设定好后,再按“设置”键退出时间设置,回到正常时间状态。

3、节气灯花样转换在正常走时状态下,按住“设置”键3秒钟即可进入节气灯花样转换。

4、12/24小时制切换在正常走时状态下,按住“上调”键3秒钟,则可进行12小时制与24小时制的切换。

上电复位时,可默认为24小时制或12小时制,由选项决定。

5、开/关整点报时在正常走时状态下,按住“下调”键3秒钟听到“嘀”一声,则可以打开或关闭整点报时功能。

6、天数倒计时或顺计时(由选项决定)在正常时间状态下,按“模式”键进入“天数计时状态”,在温度位显示“d1”,计时天数位若显示“――――”,表示计时“无效”;若显示具体数字表示有效,按“上调”键可以切换“有效”/“无效”,按“设置”键进入天数设定,且左边第一位(千位)闪烁,按“上调”或“下调”键修改内容,按“设置”键移动闪烁位置到第二位(百位),按“上调”或“下调”键修改闪烁位的内容,同样方法可设置十位与个位7、闹钟 8组定闹(由按键选项决定),默认值无效,默认时间为――:――点,闹钟设定:在正常时间状态下(或天数计时状态),按“下调”键进入“定闹查询状态”,定闹指示灯点亮,在温度位显示“A1”,表示当前你看到的是“第1组定闹”的信息,在小时、分钟位显示“――∶――”,表示定闹“无效”;显示“XX∶XX”的具体时间,表示定闹“有效”,按“上调”键可以切换“有效”/“无效”,按“设置”键进入定闹时间设定,且小时位闪烁,按“上调”或“下调”键修改闪烁位的内容,按“设置”键移动闪烁位置到分钟位,按“上调”或“下调”键修改闪烁位的内容,再按“设置”键确认并退出定闹时间设定,再按“下调”键进入下一组闹铃状态,其设置与“第1组定闹”相同,依次类推即可设置所有定闹。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^1;sbit DS1302_IO = P1^2;sbit DS1302_RST = P1^3;sbit wireless_1 = P2^2;sbit wireless_2 = P2^1;sbit wireless_3 = P2^0;sbit wireless_4 = P2^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;sbit DQ = P1^4; //温度传送数据IO口uchar temp_value; //温度值uchar TempBuffer[5],week_value[2];char done,count,temp,flag,up_flag,down_flag;char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************/sbit LcdRs = P3^6;sbit LcdEn = P3^7;sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数********************************************************************* *****uchar LCD_Wait(void){LcdRs=0;LcdEn=1; _nop_();LcdEn=0;return DBPort;}//向LCD写入命令或数据************************************************************#define LCD_COMMAND 0 // 写命令#define LCD_DATA 1 //写数据#define LCD_CLEAR_SCREEN 0x01 // 清屏void LCD_Write(bit style, uchar input){LcdEn=0;LcdRs=style;DBPort=input; _nop_();//注意顺序LcdEn=1; _nop_();//注意顺序LcdEn=0; _nop_();LCD_Wait();}//设置显示模式************************************************************#define LCD_SHOW 0x04 //显示开#define LCD_HIDE 0x00 //显示关#define LCD_CURSOR 0x02 //显示光标#define LCD_NO_CURSOR 0x00 //无光标void LCD_SetDisplay(uchar DisplayMode){LCD_Write(LCD_COMMAND, 0x08|DisplayMode);}//设置输入模式************************************************************#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00void LCD_SetInput(uchar InputMode){LCD_Write(LCD_COMMAND, 0x04|InputMode);}//初始化LCD************************************************************ void LCD_Initial(){LcdEn=0;LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//液晶字符输入的位置************************void GotoXY(uchar x, uchar y) //数据写入位置{if(y==0)LCD_Write(LCD_COMMAND,0x80|x);if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));}//将字符输出到液晶显示void Print(uchar *str) //数据写入{while(*str!='\0'){LCD_Write(LCD_DATA,*str);str++;}}/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{uchar Second;uchar Minute;uchar Hour;uchar Week;uchar Day;uchar Month;uchar Year;uchar DateString[11];uchar TimeString[9];}SYSTEMTIME; //定义的时间类型SYSTEMTIME CurrentTime;#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8Cvoid DS1302InputByte(uchar d) //实时时钟写入一字节(内部函数){uchar i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的RRCDS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}uchar DS1302OutputByte(void) //实时时钟读取一字节(内部函数){unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(uchar ucAddr, uchar ucData) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucData); // 写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsigned char Read1302(uchar ucAddr) //读取DS1302某地址的数据{uchar ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组{uchar ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ////将读出数据转化ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);}void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为2007/07/22{Time->DateString[0] = '2';Time->DateString[1] = '0';Time->DateString[2] = Time->Year/10 + '0';Time->DateString[3] = Time->Year%10 + '0';}else{Time->DateString[0] = ' ';Time->DateString[1] = ' ';Time->DateString[2] = ' ';Time->DateString[3] = ' ';}Time->DateString[4] = '-';if(hide_month<2){Time->DateString[5] = Time->Month/10 + '0';Time->DateString[6] = Time->Month%10 + '0';}else{Time->DateString[5] = ' ';Time->DateString[6] = ' ';}Time->DateString[7] = '-';if(hide_day<2){Time->DateString[8] = Time->Day/10 + '0';Time->DateString[9] = Time->Day%10 + '0';}else{Time->DateString[8] = ' ';Time->DateString[9] = ' ';}if(hide_week<2){week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示}else{week_value[0] = ' ';}week_value[1] = '\0';Time->DateString[10] = '\0'; //字符串末尾加'\0' ,判断结束字符}void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组TimeString[];{ if(hide_hour<2){Time->TimeString[0] = Time->Hour/10 + '0';Time->TimeString[1] = Time->Hour%10 + '0';}else{Time->TimeString[0] = ' ';Time->TimeString[1] = ' ';}Time->TimeString[2] = ':';if(hide_min<2){Time->TimeString[3] = Time->Minute/10 + '0';Time->TimeString[4] = Time->Minute%10 + '0';}else{Time->TimeString[3] = ' ';Time->TimeString[4] = ' ';}Time->TimeString[5] = ':';if(hide_sec<2){Time->TimeString[6] = Time->Second/10 + '0';Time->TimeString[7] = Time->Second%10 + '0';}else{Time->TimeString[6] = ' ';Time->TimeString[7] = ' ';}Time->DateString[8] = '\0';}void Initial_DS1302(void) //时钟芯片初始化{unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80) //判断时钟芯片是否关闭{Write1302(0x8e,0x00); //写入允许Write1302(0x8c,0x00); //以下写入初始化时间日期:00/00/00.星期: 3. 时间: 00:00:00Write1302(0x88,0x00);Write1302(0x86,0x00);Write1302(0x8a,0x01);Write1302(0x84,0x00);Write1302(0x82,0x00);Write1302(0x80,0x00);Write1302(0x8e,0x80); //禁止写入}}/***********ds18b20子程序*************************//***********ds18b20延迟子函数(晶振12MHz )*******/void delay_18B20(unsigned int i){while(i--);}/**********ds18b20初始化函数**********************/void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay_18B20(8); //稍做延时DQ = 0; //单片机将DQ拉低delay_18B20(80); //精确延时大于480usDQ = 1; //拉高总线delay_18B20(14);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(uchar dat){unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay_18B20(5);DQ = 1;dat>>=1;}}/**************读取ds18b20当前温度************/void ReadTemp(void){unsigned char a=0;unsigned char b=0;unsigned char t=0;Init_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换delay_18B20(100);Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度delay_18B20(100);a=ReadOneChar(); //读取温度值低位b=ReadOneChar(); //读取温度值高位temp_value=b<<4; //左移四位,扩大16倍,变为一个字节的高四位temp_value+=(a&0xf0)>>4; //取温度值的地位的高四位,右移四位后与温度的高四位相加}void temp_to_str() //温度数据转换成液晶字符显示{TempBuffer[0]=temp_value/100%10+'0'; //十位TempBuffer[1]=temp_value%10+'0'; //个位TempBuffer[2]=0xdf; //温度符号TempBuffer[3]='C';TempBuffer[4]='\0';}void Delay1ms(uint count){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/void mdelay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}////////////////////////////////////////////////////////////////////////////////////////////////////////////void Upkey()//升序按键{if(wireless_2==0){mdelay(7);if(wireless_2==0){while(!wireless_2);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp+1; //秒数加1up_flag=1; //数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp+1; //分数加1up_flag=1;if(temp>0x59) //超过59分,清零temp=0;break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp+1; //小时数加1up_flag=1;if(temp>0x23) //超过23小时,清零temp=0;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp+1; //星期数加1up_flag=1;if(temp>0x7)temp=1;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp+1; //日数加1up_flag=1;if(temp>0x31)temp=1;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp+1; //月数加1up_flag=1;if(temp>0x12)temp=1;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp+1; //年数加1up_flag=1;if(temp>0x85)temp=0;break;default:break;}}}}////////////////////////////////////////////////////////////////////////////////////////////////////////////void Downkey()//降序按键{if(wireless_3==0){mdelay(7);if(wireless_3==0){switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp-1; //秒数减1down_flag=1; //数据调整后更新标志if(temp==0x7f) //小于0秒,返回59秒temp=0x59;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp-1; //分数减1down_flag=1;if(temp==-1)temp=0x59; //小于0秒,返回59秒break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp-1; //小时数减1down_flag=1;if(temp==-1)temp=0x23;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp-1; //星期数减1down_flag=1;if(temp==0)temp=0x7;;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp-1; //日数减1down_flag=1;if(temp==0)temp=31;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp-1; //月数减1down_flag=1;if(temp==0)temp=12;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp-1; //年数减1down_flag=1;if(temp==-1)temp=0x85;break;default:break;}}}}void Setkey()//模式选择按键{if(wireless_4==0){mdelay(7);if(wireless_4==0){while(!wireless_4);count=count+1; //Setkey按一次,count就加1done=1; //进入调整模式}}}void outkey() //跳出调整模式,返回默认显示{uchar Second;if(wireless_1==0){mdelay(5);if(wireless_1==0){while(!wireless_1);count=0;hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month= 0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8e,0x80); //禁止写入done=0;}}}void keydone()//按键功能执行{ uchar Second;if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入允许temp=Read1302(0x80);Write1302(0x80,temp|0x80);Write1302(0x8e,0x80); //禁止写入flag=1;}Setkey(); //扫描模式切换按键switch(count){case 1:do //count=1,调整秒{outkey(); //扫描跳出按钮Upkey(); //扫描加按钮Downkey(); //扫描减按钮if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{Write1302(0x8e,0x00); //写入允许Write1302(0x80,temp|0x80); //写入新的秒数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_sec++; //位闪计数if(hide_sec>3)hide_sec=0;show_time(); //液晶显示数据}while(count==2);break;case 2:do //count=2,调整分{hide_sec=0;outkey();Upkey();Downkey();if(temp>0x60)temp=0;if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x82,temp); //写入新的分数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_min++;if(hide_min>3)hide_min=0;show_time();}while(count==3);break;case 3:do //count=3,调整小时{hide_min=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x84,temp); //写入新的小时数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_hour++;if(hide_hour>3)hide_hour=0;show_time();}while(count==4);break;case 4:do //count=4,调整星期{hide_hour=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x8a,temp); //写入新的星期数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_week++;if(hide_week>3)hide_week=0;show_time();}while(count==5);break;case 5:do //count=5,调整日{hide_week=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x86,temp); //写入新的日数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_day++;if(hide_day>3)hide_day=0;show_time();}while(count==6);break;case 6:do //count=6,调整月{hide_day=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x88,temp); //写入新的月数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_month++;if(hide_month>3)hide_month=0;show_time();}while(count==7);break;case 7:do //count=7,调整年{hide_month=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_year++;if(hide_year>3)hide_year=0;show_time();}while(count==8);break;case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;break; //count=7,开启中断,标志位置0并退出default:break;}}void show_time() //液晶显示程序{DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据TimeToStr(&CurrentTime); //时间数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符ReadTemp(); //开启温度采集程序temp_to_str(); //温度数据转换成液晶字符GotoXY(12,1); //液晶字符显示位置Print(TempBuffer); //显示温度GotoXY(0,1);Print(CurrentTime.TimeString); //显示时间GotoXY(0,0);Print(CurrentTime.DateString); //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week"); //在液晶上显示字母weekDelay1ms(400); //扫描延时}main(){flag=1; //时钟停止标志LCD_Initial(); //液晶初始化Init_DS18B20( ) ; //DS18B20初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;done=0; //进入默认液晶显示while(1){while(done==1)keydone(); //进入调整模式while(done==0){show_time(); //液晶显示数据flag=0;Setkey(); //扫描各功能键}}}。

相关文档
最新文档