⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 万年历.c

📁 DS12887+1602(带温度)原理图和程序
💻 C
字号:
/********************************************/
/*****************万年历*********************/
//功能描述:采用时钟芯片DS12CR887计时,DS18B20
//			测量温度,LCD1602显示时间。可从2000
//          年至2099年随意调节,显示包括年、月、
//			日、时、分、秒、星期和温度。
//键盘说明:key_1键为设置键
//			key_2键为时间加一键
//			key_3键为时间减一键
//			key_4键位定时设置键
//调时方法:按下key_1键为设置时间
//			按键次数       功能
//			   1		   设置秒
//			   2           设置分
//			   3           设置时
//			   4    	   设置日
//			   5           设置月
//			   6           设置年
//			   7		   设置星期
//             8           调节结束
//			按键次数		功能
//		       1            设置秒
//			   2            设置分
//			   3     		设置时
//			   4            设置结束
/********************************************/
#include <REGX51.H>
#include "1602.h"
#include"ds12cr887.h"
/**************键盘引脚定义******************/
sbit key_1 = P3^0;	 //设置格式
sbit key_2 = P3^1;	 //+ 
sbit key_3 = P3^2;	 //-
sbit buzzer= P1^4; 	//蜂鸣器 
sbit DQ    = P1^3;	   //定义DS18B20
/******************全局变量********************/
uchar t0=0,second=0, min=0, hour=0,day=0,month=0,year=0,weekday=0,flag=0,temp=0,flag1=0;
/******************初始化时间******************/
uchar code table1[]=" 2013-06-01 SAT ";
uchar code table2[]="00:00:00 0000";
uchar code table3[]="Jin Yaxue";
uchar code table4[]="I Love You !";
/*******************字符表*********************/
uchar code word[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x20,0x2d};
uchar code week[][3]={"SUN","MON","TUE","WED","THU","FRI","SAT"};
/************数据缓冲与键盘计数变量************/
uchar databuffer[14],TempBuffer[4],count,t_value;
uint num=0;
/******************函数声明********************/
void init();
void lcd_write_com(uchar command);  //1602液晶写命令
void lcd_write_data(uchar date);    //1602液晶写数据
void delay(uint a);
void newbuf();		//数据转换
void keyboard();    //键盘子程序
void disp();	   //显示程序
void write_ds(uchar add,uchar date);
uchar read_ds(uchar add);
void Init_DS18B20( );
void delay_18B20(unsigned int i);
uchar ReadOneChar(void );
void WriteOneChar(uchar dat);
void ReadTemp(void);
void temp_to_str();
/***********************主函数**********************/
void main()
{		
    init();			 //初始化 
	Init_DS18B20( );      //DS18B20初始化
	lcd_write_com(0x80+3);
	for(num=0;num<9;num++)	   //将table字符串写入
	{
		lcd_write_data(table3[num]);
		delay(200);
     }

	lcd_write_com(0x80+0x40+2);
	for(num=0;num<12;num++)	   //将table字符串写入
	{
		lcd_write_data(table4[num]);
		delay(200);
     }
	 delay(2000);
	lcd_write_com(0x01);			  //清屏

	lcd_write_com(0x80+0x00);  //设置指针地址为首行
	for(num=0;num<15;num++)	   //将table字符串写入
	{
		lcd_write_data(table1[num]);
		delay(20);
     }
	 lcd_write_com(0x80+0x40);	 //设置指针地址为第二行
	 for(num=0;num<13;num++)	 //将table1字符串写入
	 {
	 	lcd_write_data(table2[num]);
		delay(20);
	 }		  
	 while(1)
	{
		uchar b;
		keyboard();	//调整时间
		 ReadTemp();                    //开启温度采集程序
		 temp_to_str();                 //温度数据转换成液晶字符
		 lcd_write_com(0x80+0x40+9);
		 delay(20);
		 for(b=0;b<4;b++)
		 {
		 	lcd_write_data(TempBuffer[b]);
			delay(20);
		 }	  	 
		 
		 if(flag==0)
		 {
			second=read_ds(0x00);
			min=read_ds(0x02);
			hour=read_ds(0x04);
			weekday=read_ds(0x06);
			day=read_ds(0x07);
			month=read_ds(0x08);
			year=read_ds(0x09);
		}

		newbuf();
	 	{  
			databuffer[2]=10;
			databuffer[5]=10;
	    }  

	    disp();
	}
}
/*************************初始化*************************/
void init()
{
	lcd_write_com(0x38);			  //设置显示模式
	lcd_write_com(0x0c);			  //光标闪烁
	lcd_write_com(0x06);
	lcd_write_com(0x01);			  //清屏
	write_ds(0x0a,0x20);
	write_ds(0x0b,0x26);
	read_ds(0x0c);
	buzzer=1;
	EA=1;
	EX1=1;;
	IT0=1;
}
/***********************LCD1602写命令************************/
void lcd_write_com(uchar command)
{								     //液晶1602写命令
	lcdrs=0;
	lcdrw=0;
	P0=command;
	delay(5);
	lcden=1;
	delay(5);
	lcden=0;
}
/*************************LCD1602写数据************************/
void lcd_write_data(uchar date)
{
	lcdrs=1;					 //液晶1602写数据
	lcdrw=0;
	P0=date;
	delay(5);
	lcden=1;
	delay(5);
	lcden=0;
}
/***************************延时函数****************************/
void delay(uint a)
{
	uint x,y;
	for(x=a;x>0;x--)
		for(y=110;y>0;y--);
}
/******************************缓冲数据处理*************************/
void newbuf()		 //更新缓冲区子程序
{
 databuffer[0]=second%10;
 databuffer[1]=second/10;
 databuffer[3]=min%10;
 databuffer[4]=min/10;
 databuffer[6]=hour%10;
 databuffer[7]=hour/10;
 databuffer[8]=day%10;
 databuffer[9]=day/10;
 databuffer[10]=month%10;
 databuffer[11]=month/10;
 databuffer[12]=year%10;
 databuffer[13]=year/10;
}
/**************************液晶数据显示**************************/
void disp()	   //显示程序
{	
	uchar j=0; 
	lcd_write_com(0x80+0x40);	 //设置指针地址为第二行
	lcd_write_data(word[databuffer[7]]);	//小时十位
	lcd_write_data(word[databuffer[6]]);   //小时个位
	lcd_write_data(word[databuffer[5]]);
	lcd_write_data(word[databuffer[4]]);  //分十位
	lcd_write_data(word[databuffer[3]]);  //分个位
	lcd_write_data(word[databuffer[2]]);
	lcd_write_data(word[databuffer[1]]);  //秒十位
	lcd_write_data(word[databuffer[0]]);  //秒个位
 	lcd_write_com(0x80+0x03);	   //设置指针地址为第一行
	lcd_write_data(word[databuffer[13]]); //年十位
	lcd_write_data(word[databuffer[12]]); //年个位
	lcd_write_data(word[12]);
	lcd_write_data(word[databuffer[11]]);  //月十位
	lcd_write_data(word[databuffer[10]]);  //月个位
	lcd_write_data(word[12]);
	lcd_write_data(word[databuffer[9]]);   //日十位
	lcd_write_data(word[databuffer[8]]);   //日个位	
	lcd_write_com(0x80+0x0c);
	for(j=0;j<3;j++)
	{
		 lcd_write_data( week[weekday-1][j]);
	}
}
/******************************键盘扫描*****************************/
void keyboard()
{
	if(key_1==0)	
		{
			delay(10);
			if(key_1==0)
			{	
				count++;   //按键计数,设置模式
				while(!key_1);
				flag=1;
				flag1=0;
				read_ds(0x0c);
				while(!key_1);
				if(count==1)	//key_1键摁一次
				{
					lcd_write_com(0xc0+7);	  //设置光标为秒位置
					lcd_write_com(0x0e);
				}
			
				if(count==2)	 //key_1键摁两次
				{
					lcd_write_com(0xc0+4);	 //设置光标为分位置  
				}
				if(count==3)	//key_1键摁三次
				{
					lcd_write_com(0xc0+1);	 //设置光标为时位置
				}
				if(count==4)	//key_1键摁三次
				{
					lcd_write_com(0x80+0x09);	 //设置光标为日位置
				}
				if(count==5)	//key_1键摁三次
				{
					lcd_write_com(0x80+0x06);	 //设置光标为月位置
				}
				if(count==6)	//key_1键摁三次
				{
					lcd_write_com(0x80+0x03);	 //设置光标为年位置
				}
				if(count==7)	//key_1键摁三次
				{
					lcd_write_com(0x80+0x01);	 //设置光标为年位置
				}
				if(count==8)	 //key_1键摁四次
				{
					count=0;	   //摁键次数清零
					lcd_write_com(0x0f);		//光标不显示
					write_ds(0x00,second);
					write_ds(0x02,min);
					write_ds(0x04,hour);
					write_ds(0x06,weekday);
					write_ds(0x07,day);
					write_ds(0x08,month);
					write_ds(0x09,year);
					flag=0;
					delay(200);
				}
			}
	 	}
			if(count!=0)			   //key_1键摁后处理
			{
				if(key_2==0)		  //key_2键摁下处理
				{
					delay(10);
					if(key_2==0)
					{
						while(!key_2);
						if(count==1)	   //key_1键摁一次
						{
							second++;	 //秒加一
							if(second==60)
								second=0;
							newbuf();
							disp();
							lcd_write_com(0xc0+7);
							
							
						}
						if(count==2)	  //key_1键摁两次
						{
							min++;		 //分加一
							if(min==60)
								min=0;
							newbuf();
							disp();
							lcd_write_com(0xc0+4);
						}
						if(count==3)	  //key_1键摁三次
						{
							hour++;		//时加一
							if(hour==24)
								hour=0;
							newbuf();
							disp();
							lcd_write_com(0xc0+1);
						}
						if(count==4)	  //key_1键摁四次
						{
							day++;		//日加一
							if(day==32)
								day=1;
							newbuf();
							disp();
							lcd_write_com(0x80+0x09);
						}
						if(count==5)	  //key_1键摁五次
						{
							month++;		//月加一
							if(month==13)
								month=1;
							newbuf();
							disp();
							lcd_write_com(0x80+0x06);
						}
						if(count==6)	  //key_1键摁六次
						{
							year++;		//年加一
							if(year==100)
								year=0;
							newbuf();
							disp();
							lcd_write_com(0x80+0x03);
						}
						if(count==7)	  //key_1键摁六次
						{
							weekday++;		//年加一
							if(weekday==8)
								weekday=1;
							disp();
							lcd_write_com(0x80+0x0c);
							  delay(200);
						}
					}
				}
				if(key_3==0)		 //key_3键摁下处理
				{
					delay(10);
					if(key_3==0)
					{
						while(!key_3);
						if(count==1)	   //key_1键摁一次
						{	
							second--;	  //秒减一
							if(second==-1)
								second=59;
							newbuf();
							disp();
							lcd_write_com(0xc0+7);
						}
						if(count==2)		 //key_1键摁两次
						{
							min--;			//分减一
							if(min==-1)
								min=59;
							newbuf();
							disp();
							lcd_write_com(0xc0+4);
						}
						if(count==3)	   //key_1键摁三次
						{
							hour--;		   //时减一
							if(hour==-1)
								hour=23;
							newbuf();
							disp();
							lcd_write_com(0xc0+1);
						}
						if(count==4)	   //key_1键摁四次
						{
							day--;		   //日减一
							if(day==-1)
								day=31;
							newbuf();
							disp();
							lcd_write_com(0x80+0x09);
						}
						if(count==5)	   //key_1键摁五次
						{
							month--;		   //月减一
							if(month==-1)
								month=12;
							newbuf();
							disp();
							lcd_write_com(0x80+0x06);
						}
						if(count==6)	   //key_1键摁六次
						{
							year--;		   //年减一
							if(year==-1)
								year=99;
							newbuf();
							disp();
							lcd_write_com(0x80+0x03);
						}
						if(count==7)	   //key_1键摁六次
						{
							weekday--;		   //年减一
							if(weekday==0)
								weekday=7;
							disp();
							lcd_write_com(0x80+0x0c);
						}
					}
				}
			}

}
/**********************DS12887写数据*****************/
void write_ds(uchar add,uchar date)	//ds12887写数据
{
	dscs=0;
	dsas=1;
	dsds=1;
	dsrw=1;
	P2=add;
	dsas=0;
	dsrw=0;
	P2=date;
	dsrw=1;
	dsas=1;
	dscs=1;				
}
/*************************DS12887读数据********************/
uchar read_ds(uchar add)		    //ds12887读数据
{
 	uchar ds_date;
	dsas=1;
	dsds=1;
	dsrw=1;
	dscs=0;
	P2=add;
	dsas=0;
	dsds=0;
	P2=0xff;
	ds_date=P2;
	dsds=1;
	dsas=1;
	dscs=1;
	return ds_date;	
}
/*****************定时中断********************/
void timealarm() interrupt 2
{	
	uchar   c;
	buzzer=0;
	c=read_ds(0x0c);
}  
/***********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); //精确延时 大于 480us
	 DQ = 1;          //拉高总线
	 delay_18B20(14);
	 x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
	 delay_18B20(20);
}
/***********ds18b20读一个字节**************/  
uchar ReadOneChar(void)
{
	uchar y=0;
	uchar dat = 0;
	for (y=8;y>0;y--)
	 {
		  DQ = 0; // 给脉冲信号
		  dat>>=1;
		  DQ = 1; // 给脉冲信号
		  if(DQ)
		  dat|=0x80;
		  delay_18B20(4);
	 }
 	return(dat);
}
/*************ds18b20写一个字节****************/  
void WriteOneChar(uchar dat)
{
 	unsigned char z=0;
 	for (z=8; z>0; z--)
 	{
  		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);       // this message is wery important

	Init_DS18B20();
	WriteOneChar(0xCC); 	//跳过读序号列号的操作
	WriteOneChar(0xBE); 	//读取温度寄存器等(共可读9个寄存器) 前两个就是温度

	delay_18B20(100);

	a=ReadOneChar();    	//读取温度值低位
	b=ReadOneChar();   		//读取温度值高位
	t_value=b<<4;
	t_value+=(a&0xf0)>>4;               
}
void temp_to_str()   //温度数据转换成液晶字符显示
{
  TempBuffer[0]=t_value/10+'0';  //十位
  TempBuffer[1]=t_value%10+'0';  //个位
  TempBuffer[2]=0xdf;   //温度符号
  TempBuffer[3]='C';
}






					

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -