<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        單片機電子鐘程序完美版(帶鬧鐘溫度功能)

        作者:未知   來源:本站原創   點擊數:  更新時間:2014年07月07日   【字體:

        本電子鐘已經全部測試OK,帶鬧鐘功能,年月日時分秒星期溫度,四個按鍵可設置鬧鐘調節時間,溫度可以顯示正125度到負的55度之間,時間走時的話,我測試了一個月,誤差不到1分鐘。本人已經錄制成視頻,視頻里面有詳細的介紹,感興趣的可以看看 。視頻及多圖還有源代碼的地址: http://www.thefapper.com/bbs/dpj-26057-1.html

        程序:

        #include <reg52.h>
        #include <intrins.h>
        #define uchar unsigned char
        #define uint unsigned int
        sbit rs=P1^0;//寄存器選擇
        sbit rw=P1^1;//讀寫信號線
        sbit lcden=P1^2;//led使能端
        
        sbit scl=P1^3;//時鐘線
        sbit rst=P1^5;//復位線
        sbit io=P1^4;//數據口
        
        sbit key_set_time=P3^4;//設置時間鍵
        sbit key_add=P3^5;//加鍵
        sbit key_minus=P3^6;//減鍵
        sbit key_set_alarm=P3^7;//設置鬧鐘鍵
        sbit bee=P1^6;//蜂鳴器接口
        sbit dq=P1^7;//ds18b20測溫
        
        uchar getTimebuf[7];//存放時間數據
        uchar time[]={"  :  :  "};//時間格式字符串
        uchar date[]={"20  -  -  "};//日期格式字符串
        uchar weeklist[]={"SunMonTueWedThuFriSat"};//星期字符列表
        uchar week[]={"   "};//星期格式字符串
        
        int count;//設定秒分時日月星期年的時候count的值分別為1235647
        int alarm;//是否進入鬧鐘設置界面 123分別代表開關 分 小時的設置
        int isOpen;//鬧鐘是否開啟  默認不開啟
        int fen,shi;//鬧鐘的分鐘小時
        int isRing;//鬧鐘是否在響
        
        uchar isInit_1302;//是否初始化時鐘完畢
        
        int num;
        int temperature;//溫度
        int temp_flag;//溫度正負標志
        
        void delay(uint x){
        	int y;
        	while(x--){
        		for(y=100;y>0;y--);
        	}
        }
        void write_1602com(uchar com){
        	//1602寫指令
        	rs=0;
        	lcden=0;
        	P2=com;
        	delay(5);
        	lcden=1;
        	delay(5);
        	lcden=0;
        }
        void write_1602data(uchar dat){
        	//1602寫數據
        	rs=1;
        	lcden=0;
        	P2=dat;
        	delay(5);
        	lcden=1;
        	delay(5);
        	lcden=0;
        }
        void init_1602(){
        	//初始化1602液晶
        	rw=0;
        	lcden=0;
        	write_1602com(0x38);//設置顯示模式
        	write_1602com(0x0c);//顯示開關及光標是否顯示和閃動
        	write_1602com(0x06);//光標移動方向
        	write_1602com(0x01);//清屏
        }
        void write_ds1302_byte(uchar temp){
        	//ds1302寫一個字節數據
        	uchar i;
        	for(i=0;i<8;i++){
        		io=temp&0x01;//將數據放到IO口上
        		scl=0;//scl為低時準備數據
        		scl=1;//上升沿寫入
        		temp>>=1;
        	}
        }
        void write_ds1302(uchar add,uchar dat){
        	//向地址add寫入數據dat
        	rst=0;
        	scl=0;
        	rst=1;
        	write_ds1302_byte(add);
        	write_ds1302_byte(dat);
        	scl=1;
        	rst=0;
        }
        uchar read_ds1302(uchar add){
        	//ds1302讀數據
        	uchar i,dat;
        	rst=0;
        	scl=0;
        	rst=1;
        	write_ds1302_byte(add);//首先寫入要讀的數據處的地址
        	for(i=0;i<8;i++){
        		if(io==1){
        			dat|=0x80;
        		}
        		scl=1;
        		scl=0;//下降沿讀取數據
        		dat>>=1;
        	}
        	scl=1;
        	rst=0;
        	return dat;
        }
        void read_time(uchar curr_time[]){
        	  uchar i;
        	  uchar ucAddr = 0x81;
        	  for (i=0;i<7;i++){
        		curr_time[i] = read_ds1302(ucAddr);//格式為: 秒 分 時 日 月 星期 年 
        		ucAddr += 2;
        	  }
        }
        void set_time(uchar *pSecDa){
        	//設定時間
        	uchar i;
        	uchar ucAddr = 0x80;
        	write_ds1302(0x8e,0x00);	
        	for(i =7;i>0;i--){ 
        		write_ds1302(ucAddr,*pSecDa); //秒 分 時 日 月 星期 年
        		pSecDa++;
        		ucAddr+=2;
        	}
        	write_ds1302(0x8e,0x80);
        }
        void init_ds1302(){
        	//ds1302初始化
        	isInit_1302=read_ds1302(0x81);//讀出時鐘狀態
        	if(isInit_1302&0x80){//說明沒有初始化
        		write_ds1302(0x8e,0x00);//關閉寫保護  以后一直開著
        		write_ds1302(0x90,0xa5); //輔助電源充電命令 一個二極管  一個2K電阻
        		write_ds1302(0x80,0x00);//秒 CH置0 開啟時鐘
        		write_ds1302(0x82,0x59);//分
        		write_ds1302(0x84,0x10);//時
        		write_ds1302(0x86,0x07);//日
        		write_ds1302(0x88,0x05);//月
        		write_ds1302(0x8a,0x04);//星期
        		write_ds1302(0x8c,0x14);//年
        		write_ds1302(0x8e,0x80);
        	}
        }
        char int_to_char(int temp){
        	//把0到9對應的數字轉為字符
        	char x='0';
        	switch(temp){
        		case 0:x='0';break;
        		case 1:x='1';break;
        		case 2:x='2';break;
        		case 3:x='3';break;
        		case 4:x='4';break;
        		case 5:x='5';break;
        		case 6:x='6';break;
        		case 7:x='7';break;
        		case 8:x='8';break;
        		case 9:x='9';break;
        	}
        	return x;
        }
        int ds18b20_read_temp();
        void display(){
        	uchar bai,shi,ge,point,fuhao;
        	read_time(getTimebuf);//時時讀取時間
            time[6]=(getTimebuf[0])/16+48;//格式化時間秒
            time[7]=(getTimebuf[0])%16+48;
        
            time[3]=(getTimebuf[1])/16+48;//格式化時間分
            time[4]=(getTimebuf[1])%16+48;
        
            time[0]=(getTimebuf[2])/16+48;//格式化時間小時
            time[1]=(getTimebuf[2])%16+48;
        
            date[8]=getTimebuf[3]/16+48;//格式化日期日
            date[9]=getTimebuf[3]%16+48;
        
            date[5]=getTimebuf[4]/16+48;//格式化日期月
            date[6]=getTimebuf[4]%16+48;
        
            date[2]=getTimebuf[6]/16+48;//格式化日期年
            date[3]=getTimebuf[6]%16+48;
        
            week[0]=weeklist[(getTimebuf[5]%10)*3];//格式化星期
            week[1]=weeklist[(getTimebuf[5]%10)*3+1];
            week[2]=weeklist[(getTimebuf[5]%10)*3+2];
        	
        	write_1602com(0x80+1);
        	for(num=0;num<10;num++){
        		write_1602data(date[num]);
        	}
        
        	write_1602data(' ');
        	for(num=0;num<3;num++){
        		write_1602data(week[num]);
        	}
        
        	write_1602com(0x80+0x40);
        	for(num=0;num<8;num++){
        		write_1602data(time[num]);
        	}
        	
        	//顯示溫度值
        	write_1602com(0x80+0x40+8);//設置數據指針
        	temperature=ds18b20_read_temp();
        	bai=temperature/1000+0x30;
        	shi=temperature%1000/100+0x30;
        	ge=temperature%100/10+0x30;
        	point=temperature%100%10+0x30;
        	if(temp_flag==1){//說明為正數  不顯示符號位 125.6 25.7兩種
        		fuhao=0x20;//顯示空白
        		if(bai==0x30){
        			bai=0x20;//如果百位為0  不顯示
        			if(shi==0x30){
        				shi=0x20;//如果百位為0  十位也為0  都不顯示
        			}
        		}
        		write_1602data(fuhao);
        		write_1602data(bai);
        		write_1602data(shi);
        	}else{
        		fuhao=0x2d;//顯示負號  -2.5  -25.8兩種
        		write_1602data(0x20);//因為負數最低到55,所以不顯示百位
        		if(shi==0x30){	
        			write_1602data(0x20);
        			write_1602data(fuhao);
        		}else{
        			write_1602data(fuhao);
        			write_1602data(shi);
        		}
        	}
        	write_1602data(ge);
        	write_1602data('.');
        	write_1602data(point);
        	write_1602data(0xdf);
        	write_1602data('C');
        }
        void display_alarm(uchar add,int dat){
        	//把設定的時分顯示出來
        	int x,y;
        	x=dat/10;
        	y=dat%10;
        	write_1602com(add);
        	write_1602data(int_to_char(x));
        	write_1602com(add+1);//防止寫后地址自動向后加一  光標閃爍看不到
        	write_1602data(int_to_char(y));
        	write_1602com(add+1);
        }
        void init_alarm(){
        	//鬧鐘設置界面  只有首次進入才執行
        	uchar code x[]="SET ALARM";
        	uchar i;
        	if(alarm==0){
        		write_1602com(0x01);//清屏
        		write_1602com(0x80+3);//設置數據指針
        		for(i=0;i<9;i++){
        			write_1602data(x[i]);
        		}
        		display_alarm(0x80+0x40+5,shi);//載入鬧鐘的時分
        		write_1602com(0x80+0x40+7);
        		write_1602data(':');
        		display_alarm(0x80+0x40+8,fen);
        		if(isOpen){//初始化的時候如果已經設定鬧鐘則顯示ON
        			write_1602com(0x80+0x40+13);
        			write_1602data(' ');
        			write_1602data('O');
        			write_1602data('N');
        		}else{
        			write_1602com(0x80+0x40+13);
        			write_1602data('O');
        			write_1602data('F');
        			write_1602data('F');
        		}
        	}
        }
        void key_scan(){
        	int i;
        	uchar code tips1[]="SET SUCCESS";//鬧鐘設置成功的提示
        	uchar code tips2[]="CANCEL SUCCESS";//取消鬧鐘的提示
        	if(key_set_time==0){//檢測是否按下
        		delay(10);//消抖
        		if(key_set_time==0){//再次檢測是否按下
        			while(!key_set_time);//檢測是否松開
        			delay(10);//延時消抖
        			while(!key_set_time);//再次檢測是否松開
        			if(alarm==0){//當沒有顯示鬧鐘界面時才顯示時間設定
        				count++;
        				write_ds1302(0x80,0x80);//讓時鐘停止
        				if(count==8){
        					//繼續走時,說明時間已經設定好了
        					write_1602com(0x0c);//讓光標消失
        					write_ds1302(0x80,0);//讓時鐘繼續
        					set_time(getTimebuf);//寫入新的時間
        					count=0;
        					return;
        				}
        				switch(count){
        					case 1:
        						write_1602com(0x80+0x40+7);//在秒的位置
        						break;
        					case 2:
        						write_1602com(0x80+0x40+4);//在分的位置
        						break;
        					case 3:
        						write_1602com(0x80+0x40+1);//在時的位置
        						break;
        					case 4:
        						write_1602com(0x80+14);//在星期的位置
        						break;
        					case 5:
        						write_1602com(0x80+10);//在日的位置
        						break;
        					case 6:
        						write_1602com(0x80+7);//在月的位置
        						break;
        					case 7:
        						write_1602com(0x80+4);//在年的位置
        						break;
        				}
        				write_1602com(0x0f);//讓光標閃爍
        			}
        		}
        	}
        	if(key_add==0){//檢測是否按下
        		delay(10);//消抖
        		if(key_add==0){//再次檢測是否按下
        			while(!key_add);//檢測是否松開
        			delay(10);//延時消抖
        			while(!key_add);//再次檢測是否松開
        			if(count!=0){
        				switch(count){
        				case 1:
        					//在秒的位置
        					getTimebuf[0]++;
        					if(getTimebuf[0]==0x5a){
        						getTimebuf[0]=0;
        					}
        					if(getTimebuf[0]==0x4a){
        						getTimebuf[0]=0x50;
        					}
        					if(getTimebuf[0]==0x3a){
        						getTimebuf[0]=0x40;
        					}
        					if(getTimebuf[0]==0x2a){
        						getTimebuf[0]=0x30;
        					}
        					if(getTimebuf[0]==0x1a){
        						getTimebuf[0]=0x20;
        					}
        					if(getTimebuf[0]==0x0a){
        						getTimebuf[0]=0x10;
        					}
        					time[6]=(getTimebuf[0])/16+48;//格式化時間秒
        					time[7]=(getTimebuf[0])%16+48;
        					write_1602com(0x80+0x40+6);//在秒的位置
        					write_1602data(time[6]);
        					write_1602com(0x80+0x40+7);//在秒的位置
        					write_1602data(time[7]);
        					write_1602com(0x80+0x40+7);//讓光標在秒的位置閃爍
        					break;
        				case 2:
        					//在分的位置
        					getTimebuf[1]++;
        					if(getTimebuf[1]==0x5a){
        						getTimebuf[1]=0;
        					}
        					if(getTimebuf[1]==0x4a){
        						getTimebuf[1]=0x50;
        					}
        					if(getTimebuf[1]==0x3a){
        						getTimebuf[1]=0x40;
        					}
        					if(getTimebuf[1]==0x2a){
        						getTimebuf[1]=0x30;
        					}
        					if(getTimebuf[1]==0x1a){
        						getTimebuf[1]=0x20;
        					}
        					if(getTimebuf[1]==0x0a){
        						getTimebuf[1]=0x10;
        					}
        					time[3]=(getTimebuf[1])/16+48;//格式化時間分
        					time[4]=(getTimebuf[1])%16+48;
        					write_1602com(0x80+0x40+3);//在分的位置
        					write_1602data(time[3]);
        					write_1602com(0x80+0x40+4);//在分的位置
        					write_1602data(time[4]);
        					write_1602com(0x80+0x40+4);//讓光標在分的位置閃爍
        					break;
        				case 3:
        					//在時的位置
        					getTimebuf[2]++;
        					if(getTimebuf[2]==0x24){
        						getTimebuf[2]=0;
        					}
        					if(getTimebuf[2]==0x1a){
        						getTimebuf[2]=0x20;
        					}
        					if(getTimebuf[2]==0x0a){
        						getTimebuf[2]=0x10;
        					}
        					time[0]=(getTimebuf[2])/16+48;//格式化時間小時
        					time[1]=(getTimebuf[2])%16+48;
        					write_1602com(0x80+0x40+0);//在小時的位置
        					write_1602data(time[0]);
        					write_1602com(0x80+0x40+1);
        					write_1602data(time[1]);
        					write_1602com(0x80+0x40+1);
        					break;
        				case 4:
        					//在星期的位置
        					getTimebuf[5]++;
        					if(getTimebuf[5]==0x08){
        						getTimebuf[5]=0x01;
        					}
        					if((getTimebuf[5]%10)*3==21){//輪完了  重新開始
        						week[0]=weeklist[0];
        						week[1]=weeklist[1];
        						week[2]=weeklist[2];
        					}else{
        						week[0]=weeklist[(getTimebuf[5]%10)*3];//格式化星期
        						week[1]=weeklist[(getTimebuf[5]%10)*3+1];
        						week[2]=weeklist[(getTimebuf[5]%10)*3+2];
        					}
        					write_1602com(0x80+12);
        					write_1602data(week[0]);
        					write_1602com(0x80+13);
        					write_1602data(week[1]);
        					write_1602com(0x80+14);
        					write_1602data(week[2]);
        					write_1602com(0x80+14);
        					break;
        				case 5:
        					//在日的位置
        					getTimebuf[3]++;
        					if(getTimebuf[3]==0x32){
        						getTimebuf[3]=0x01;
        					}
        					if(getTimebuf[3]==0x2a){
        						getTimebuf[3]=0x30;
        					}
        					if(getTimebuf[3]==0x1a){
        						getTimebuf[3]=0x20;
        					}
        					if(getTimebuf[3]==0x0a){
        						getTimebuf[3]=0x10;
        					}
        					date[8]=(getTimebuf[3])/16+48;
        					date[9]=(getTimebuf[3])%16+48;
        					write_1602com(0x80+9);
        					write_1602data(date[8]);
        					write_1602com(0x80+10);
        					write_1602data(date[9]);
        					write_1602com(0x80+10);
        					break;
        				case 6:
        					//在月的位置
        					getTimebuf[4]++;
        					if(getTimebuf[4]==0x13){
        						getTimebuf[4]=0x01;
        					}
        					if(getTimebuf[4]==0x0a){
        						getTimebuf[4]=0x10;
        					}
        					date[5]=(getTimebuf[4])/16+48;
        					date[6]=(getTimebuf[4])%16+48;
        					write_1602com(0x80+6);
        					write_1602data(date[5]);
        					write_1602com(0x80+7);
        					write_1602data(date[6]);
        					write_1602com(0x80+7);
        					break;
        				case 7:
        					//在年的位置
        					getTimebuf[6]++;
        					if(getTimebuf[6]==0x9a){
        						getTimebuf[6]=0x00;
        					}
        					if(getTimebuf[6]==0x8a){
        						getTimebuf[6]=0x90;
        					}
        					if(getTimebuf[6]==0x7a){
        						getTimebuf[6]=0x80;
        					}
        					if(getTimebuf[6]==0x6a){
        						getTimebuf[6]=0x70;
        					}
        					if(getTimebuf[6]==0x5a){
        						getTimebuf[6]=0x60;
        					}
        					if(getTimebuf[6]==0x4a){
        						getTimebuf[6]=0x50;
        					}
        					if(getTimebuf[6]==0x3a){
        						getTimebuf[6]=0x40;
        					}
        					if(getTimebuf[6]==0x2a){
        						getTimebuf[6]=0x30;
        					}
        					if(getTimebuf[6]==0x1a){
        						getTimebuf[6]=0x20;
        					}
        					if(getTimebuf[6]==0x0a){
        						getTimebuf[6]=0x10;
        					}
        					date[2]=(getTimebuf[6])/16+48;
        					date[3]=(getTimebuf[6])%16+48;
        					write_1602com(0x80+3);
        					write_1602data(date[2]);
        					write_1602com(0x80+4);
        					write_1602data(date[3]);
        					write_1602com(0x80+4);
        					break;
        				}
        			}
        			if(alarm!=0){
        				switch(alarm){
        					case 1:
        						//調節鬧鐘的開與關
        						if(isOpen==0){
        							isOpen=1;
        							write_1602com(0x80+0x40+13);
        							write_1602data(' ');
        							write_1602data('O');
        							write_1602data('N');
        						}else{
        							isOpen=0;
        							write_1602com(0x80+0x40+13);
        							write_1602data('O');
        							write_1602data('F');
        							write_1602data('F');
        						}
        						//防止寫后地址自動向后加一  光標閃爍看不到
        						write_1602com(0x80+0x40+15);
        						break;
        					case 2:
        						//調節鬧鐘的分
        						fen++;
        						if(fen==60){
        							fen=0;
        						}
        						display_alarm(0x80+0x40+8,fen);
        						break;
        					case 3:
        						//調節鬧鐘的小時
        						shi++;
        						if(shi==24){
        							shi=0;
        						}
        						display_alarm(0x80+0x40+5,shi);
        						break;
        				}
        			}
        		}
        	}
        	if(key_minus==0){//檢測是否按下
        		delay(10);//消抖
        		if(key_minus==0){//再次檢測是否按下
        			while(!key_minus);//檢測是否松開
        			delay(10);//延時消抖
        			while(!key_minus);//再次檢測是否松開
        			if(count!=0){
        				switch(count){
        				case 1:
        					//在秒的位置
        					getTimebuf[0]--;
        					if(getTimebuf[0]==0xff){
        						getTimebuf[0]=0x59;
        					}
        					if(getTimebuf[0]==0x4f){
        						getTimebuf[0]=0x49;
        					}
        					if(getTimebuf[0]==0x3f){
        						getTimebuf[0]=0x39;
        					}
        					if(getTimebuf[0]==0x2f){
        						getTimebuf[0]=0x29;
        					}
        					if(getTimebuf[0]==0x1f){
        						getTimebuf[0]=0x19;
        					}
        					if(getTimebuf[0]==0x0f){
        						getTimebuf[0]=0x09;
        					}
        					time[6]=(getTimebuf[0])/16+48;//格式化時間秒
        					time[7]=(getTimebuf[0])%16+48;
        					write_1602com(0x80+0x40+6);//在秒的位置
        					write_1602data(time[6]);
        					write_1602com(0x80+0x40+7);//在秒的位置
        					write_1602data(time[7]);
        					write_1602com(0x80+0x40+7);//讓光標在秒的位置閃爍
        					break;
        				case 2:
        					//在分的位置
        					getTimebuf[1]--;
        					if(getTimebuf[1]==0xff){
        						getTimebuf[1]=0x59;
        					}
        					if(getTimebuf[1]==0x4f){
        						getTimebuf[1]=0x49;
        					}
        					if(getTimebuf[1]==0x3f){
        						getTimebuf[1]=0x39;
        					}
        					if(getTimebuf[1]==0x2f){
        						getTimebuf[1]=0x29;
        					}
        					if(getTimebuf[1]==0x1f){
        						getTimebuf[1]=0x19;
        					}
        					if(getTimebuf[1]==0x0f){
        						getTimebuf[1]=0x09;
        					}
        					time[3]=(getTimebuf[1])/16+48;//格式化時間分
        					time[4]=(getTimebuf[1])%16+48;
        					write_1602com(0x80+0x40+3);//在分的位置
        					write_1602data(time[3]);
        					write_1602com(0x80+0x40+4);//在分的位置
        					write_1602data(time[4]);
        					write_1602com(0x80+0x40+4);//讓光標在分的位置閃爍
        					break;
        				case 3:
        					//在時的位置
        					getTimebuf[2]--;
        					if(getTimebuf[2]==0xff){
        						getTimebuf[2]=0x23;
        					}
        					if(getTimebuf[2]==0x1f){
        						getTimebuf[2]=0x19;
        					}
        					if(getTimebuf[2]==0x0f){
        						getTimebuf[2]=0x09;
        					}
        					time[0]=(getTimebuf[2])/16+48;//格式化時間小時
        					time[1]=(getTimebuf[2])%16+48;
        					write_1602com(0x80+0x40+0);//在小時的位置
        					write_1602data(time[0]);
        					write_1602com(0x80+0x40+1);
        					write_1602data(time[1]);
        					write_1602com(0x80+0x40+1);
        					break;
        				case 4:
        					//在星期的位置
        					getTimebuf[5]--;
        					if(getTimebuf[5]==0){
        						getTimebuf[5]=0x07;
        					}
        					if((getTimebuf[5]%10)*3==21){//輪完了  重新開始
        						week[0]=weeklist[0];
        						week[1]=weeklist[1];
        						week[2]=weeklist[2];
        					}else{
        						week[0]=weeklist[(getTimebuf[5]%10)*3];//格式化星期
        						week[1]=weeklist[(getTimebuf[5]%10)*3+1];
        						week[2]=weeklist[(getTimebuf[5]%10)*3+2];
        					}
        					write_1602com(0x80+12);
        					write_1602data(week[0]);
        					write_1602com(0x80+13);
        					write_1602data(week[1]);
        					write_1602com(0x80+14);
        					write_1602data(week[2]);
        					write_1602com(0x80+14);
        					break;
        				case 5:
        					//在日的位置
        					getTimebuf[3]--;
        					if(getTimebuf[3]==0){
        						getTimebuf[3]=0x31;
        					}
        					if(getTimebuf[3]==0x2f){
        						getTimebuf[3]=0x29;
        					}
        					if(getTimebuf[3]==0x1f){
        						getTimebuf[3]=0x19;
        					}
        					if(getTimebuf[3]==0x0f){
        						getTimebuf[3]=0x09;
        					}
        					date[8]=(getTimebuf[3])/16+48;
        					date[9]=(getTimebuf[3])%16+48;
        					write_1602com(0x80+9);
        					write_1602data(date[8]);
        					write_1602com(0x80+10);
        					write_1602data(date[9]);
        					write_1602com(0x80+10);
        					break;
        				case 6:
        					//在月的位置
        					getTimebuf[4]--;
        					if(getTimebuf[4]==0){
        						getTimebuf[4]=0x12;
        					}
        					if(getTimebuf[4]==0x0f){
        						getTimebuf[4]=0x09;
        					}
        					date[5]=(getTimebuf[4])/16+48;
        					date[6]=(getTimebuf[4])%16+48;
        					write_1602com(0x80+6);
        					write_1602data(date[5]);
        					write_1602com(0x80+7);
        					write_1602data(date[6]);
        					write_1602com(0x80+7);
        					break;
        				case 7:
        					//在年的位置
        					getTimebuf[6]--;
        					if(getTimebuf[6]==0xff){
        						getTimebuf[6]=0x99;
        					}
        					if(getTimebuf[6]==0x8f){
        						getTimebuf[6]=0x89;
        					}
        					if(getTimebuf[6]==0x7f){
        						getTimebuf[6]=0x79;
        					}
        					if(getTimebuf[6]==0x6f){
        						getTimebuf[6]=0x69;
        					}
        					if(getTimebuf[6]==0x5f){
        						getTimebuf[6]=0x59;
        					}
        					if(getTimebuf[6]==0x4f){
        						getTimebuf[6]=0x49;
        					}
        					if(getTimebuf[6]==0x3f){
        						getTimebuf[6]=0x39;
        					}
        					if(getTimebuf[6]==0x2f){
        						getTimebuf[6]=0x29;
        					}
        					if(getTimebuf[6]==0x1f){
        						getTimebuf[6]=0x19;
        					}
        					if(getTimebuf[6]==0x0f){
        						getTimebuf[6]=0x09;
        					}
        					date[2]=(getTimebuf[6])/16+48;
        					date[3]=(getTimebuf[6])%16+48;
        					write_1602com(0x80+3);
        					write_1602data(date[2]);
        					write_1602com(0x80+4);
        					write_1602data(date[3]);
        					write_1602com(0x80+4);
        					break;
        				}
        			}
        			if(alarm!=0){
        				switch(alarm){
        					case 1:
        						//調節鬧鐘的開與關
        						if(isOpen==0){
        							isOpen=1;
        							write_1602com(0x80+0x40+13);
        							write_1602data(' ');
        							write_1602data('O');
        							write_1602data('N');
        						}else{
        							isOpen=0;
        							write_1602com(0x80+0x40+13);
        							write_1602data('O');
        							write_1602data('F');
        							write_1602data('F');
        						}
        						//防止寫后地址自動向后加一  光標閃爍看不到
        						write_1602com(0x80+0x40+15);
        						break;
        					case 2:
        						//調節鬧鐘的分
        						fen--;
        						if(fen<0){
        							fen=59;
        						}
        						display_alarm(0x80+0x40+8,fen);
        						break;
        					case 3:
        						//調節鬧鐘的小時
        						shi--;
        						if(shi<0){
        							shi=23;
        						}
        						display_alarm(0x80+0x40+5,shi);
        						break;
        				}
        			}
        		}
        	}
        	if(key_set_alarm==0){//檢測是否按下
        		delay(10);//消抖
        		if(key_set_alarm==0){//再次檢測是否按下
        			while(!key_set_alarm);//檢測是否松開
        			delay(10);//延時消抖
        			while(!key_set_alarm);//再次檢測是否松開
        			if(count==0){//時間在正常走動的時候才能設置鬧鐘
        				init_alarm();
        				alarm++;//說明進入鬧鐘設置界面
        				if(alarm==4){
        					alarm=0;//說明鬧鐘設置完畢
        					write_1602com(0x01);//清屏以便顯示時間
        					write_1602com(0x0c);//關閉光標
        					//顯示設置成功或取消的提示
        					if(isOpen){
        						write_1602com(0x80+2);
        						for(i=0;i<11;i++){
        							write_1602data(tips1[i]);
        						}
        					}else{
        						write_1602com(0x80+1);
        						for(i=0;i<14;i++){
        							write_1602data(tips2[i]);
        						}
        					}
        					//延時2ms后清屏顯示時間
        					delay(2000);
        					write_1602com(0x01);
        				}else{
        					switch(alarm){
        						case 1:
        							write_1602com(0x80+0x40+15);
        							break;
        						case 2:
        							write_1602com(0x80+0x40+9);
        							break;
        						case 3:
        							write_1602com(0x80+0x40+6);
        							break;
        					}
        					write_1602com(0x0f);
        				}
        			}
        		}
        	}
        }
        void beep(){
        	//檢測鬧鐘  并且報警
        	if(time[0]==int_to_char(shi/10)&&time[1]==int_to_char(shi%10)&&time[3]==int_to_char(fen/10)&&time[4]==int_to_char(fen%10)){
        		isRing=1;//鬧鐘響起,此時如果進入鬧鐘設置界面 改變時分,鬧鐘就關閉了
        		bee=0;
        		delay(250);
        		bee=1;
        		delay(250);
        	}else{
        		isRing=0;//關閉鬧鐘或者一分鐘后鬧鐘自動關閉
        		bee=1;
        	}
        }
        void delay1(int i){
        	while(i--);
        }
        void ds18b20_init(){
        	uchar x=0;
        	dq = 1;    //DQ復位
        	delay1(8);  //稍做延時
        	dq = 0;    //單片機將DQ拉低
        	delay1(80); //精確延時 大于 480us
        	dq = 1;    //拉高總線
        	delay1(14);
        	x=dq;      //稍做延時后 如果x=0則初始化成功 x=1則初始化失敗
        	delay1(20);
        }
        uchar ds18b20_read(){
        	//讀一個字節
        	uchar i=0;
        	uchar dat = 0;
        	for (i=8;i>0;i--)
        	{
        		dq = 0; // 給脈沖信號
        		dat>>=1;
        		dq = 1; // 給脈沖信號
        		if(dq)
        			dat|=0x80;
        		delay1(4);
        	}
        	return(dat);
        }
        void ds18b20_write(char dat){
        	//寫一個字節
        	uchar i=0;
        	for (i=8; i>0; i--)
        	{
        		dq = 0;
        		dq = dat&0x01;
        		delay1(5);
        		dq = 1;
        		dat>>=1;
        	}
        }
        int ds18b20_read_temp(){
        	//讀取溫度
        	uchar low;
        	uchar high;
        	unsigned long tmp;
        	float value;
        	int t;//溫度
        	ds18b20_init();
        	ds18b20_write(0xCC); //跳過讀序列號的操作
        	ds18b20_write(0x44); //啟動溫度轉換
        	ds18b20_init();
        	ds18b20_write(0xCC); //跳過讀序列號的操作
        	ds18b20_write(0xBE); //讀取溫度寄存器  共九個  前兩個代表溫度
        	low=ds18b20_read();//低八位數據
        	high=ds18b20_read();//高八位數據
        
        	tmp=high;
        	tmp<<=8;
        	tmp=tmp|low;
        	//此處有正負之分
        	if(tmp>=63488){//ffff f000 0000 0000-->(f800)
        		temp_flag=0;
        		//8位全為1時,加1才進位
        		if((~low)==0xff){//判斷low取反加1之后是否進位
        			high=(~high)+1;
        			low=0;
        		}else{
        			high=~high;
        			low=(~low)+1;
        		}
        		tmp=high*256+low;
        	}else{
        		temp_flag=1;
        	}
        	value=tmp*0.0625;
        	t=value*10+((temp_flag==1)?+0.5:-0.5);//放大十倍輸出并四舍五入
        	return t;
        }
        void main(){
        	init_1602();
        	init_ds1302();
        	while(1){
        		if(isOpen){//只有開啟鬧鐘的時候才檢測
        			beep();//不斷檢測鬧鐘
        		}
        		key_scan();
        		if(count==0&&alarm==0){//沒有設定時間  也沒有在鬧鐘界面的時候時間才顯示
        			display();
        		}
        	}
        }
        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮