锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

单片机电子钟程序完美版(带闹钟温度功能)

时间:2024-04-23 03:07:09

本电子钟已经全部测试OK,带闹钟功能,年月日时分秒星期温度,四个按键可设置闹钟调节时间,温度可以显示正125度到负的55度之间,时间走时的话,我测试了一个月,误差不到1分钟。本人已经录制成视频,视频里面有详细的介绍,感兴趣的可以看看 。视频及多图还有源代码的地址:http://www.51hei.com/bbs/dpj-26057-1.html

程序:

#include #include #define uchar unsigned char#define uint unsigned intsbit 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的值分别为1235647int 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){						get
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章