基于51单片机的数字温度计【开源】

1.1项目功能

(1)温度实时显示(LCD2864)

(2)温度上限下线调节

(3)万年历功能

(4)超温报警

(5)年月日时分秒可调节

(6)温度测量精度0.0625℃

(7)节日自动判定

1.2所需器材

STC89c52,DS18B20,DS1302,按键模块。LCD12864

 1.3程序架构

基于51单片机的数字温度计【开源】_第1张图片

1.4程序源码

main.c

#include 
#include "DS18B20.H"
#include "LCD12864.H"
#include "DS1302.h"
#include 


uchar table1[]="现温度        ";
uchar table2[]="上限值        度";
uchar table3[]="下限值        度";
uchar table4[]="  警告温度超出  ";
uchar table5[]="    温度稳定    ";
uchar table6[]="负温度-        ";
uchar table7[]="SpringFestival";
uchar table8[]="duanwuFestival";
uchar table10[]="    温度计";
 unsigned char Time_buf[7]={0x20,0x00,0x00,0x15,0x11,0x09,0x21};//年,秒,分,时,日,月,年;//时间缓冲数组
 unsigned char tempbuf;	//存储接收到的信息
 unsigned char tt;//传输数据
 unsigned char	receiveData;
sbit BUZZ = P2^6; //定义蜂鸣器引脚(起报警作用)

sbit key1 = P3^3; //独立按键右一切换到温度显示界面
sbit key2 = P3^0;  //上限加一--------bug原因(普中科技开发板与LCD12864液晶重合了)
sbit key3 = P3^1;   //左一切换到时间界面
sbit key4 = P3^2;//上限减一-----------bug原因(普中科技开发板与LCD12864液晶重合了)
sbit deng=P2^2;  //报警的光报警
/*================================================================================
按键调节时间↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
=================================================================================*/
void SetTime(void)
{
	
					uint i;
					switch(array())								//矩阵按键扫描
					{
						
						case 0:	Time_buf[6] = Time_buf[6] + 0x01;break;			//年+
						case 8: Time_buf[5] = Time_buf[5] + 0x01;break;     //月+
						case 1: Time_buf[4] = Time_buf[4] + 0x01;break;     //日+
						case 9:	Time_buf[3] = Time_buf[3] + 0x01;break;     //时+
						case 2: Time_buf[2] = Time_buf[2] + 0x01;break;     //分+
					
						case 4:	Time_buf[6] = Time_buf[6] - 0x01;break;			//年-
						case 12: Time_buf[5] = Time_buf[5] - 0x01;break;     //月-
						case 5: Time_buf[4] = Time_buf[4] - 0x01;break;     //日-
						case 13:Time_buf[3] = Time_buf[3] - 0x01;break;     //时-
						case 6:Time_buf[2] = Time_buf[2] - 0x01;break;     //分-

						default:;
				}
		
					for( i = 0; i < 7;i++)
			{
						if( (Time_buf[i] & 0x0F) > 9)
					{
						Time_buf[i] = ((Time_buf[i]+0x10)&0xF0);
					}
			}
		
				DS1302_Data_Input(DS1302_CONTROL_ADD,0x00);			//关闭写保护

				DS1302_Data_Input(DS1302_MIN_ADD,Time_buf[2]);		//分
				DS1302_Data_Input(DS1302_HR_ADD,Time_buf[3]);		//时
				DS1302_Data_Input(DS1302_DAY_ADD,Time_buf[4]);		//日
				DS1302_Data_Input(DS1302_MONTH_ADD,Time_buf[5]);	//月
				DS1302_Data_Input(DS1302_YEAR_ADD,Time_buf[6]);		//年
    
				DS1302_Data_Input(DS1302_CONTROL_ADD,0x80);			//打开写保护
		
}
//
//串口通信初始化
/*波特率为9600*/
void UART_init(void)
{
    SCON = 0x50;        //串口方式1
 
    TMOD = 0x20;        // 定时器使用方式2自动重载
    TH1 = 0xFD;    //9600波特率对应的预设数,定时器方式2下,TH1=TL1
    TL1 = 0xFD;
    ES=1 ;
	  EA=1 ;
    TR1 = 1;//开启定时器,开始产生波特率
}

/*void Usart() interrupt 4  //串行口中断
{

	SBUF=receiveData;//将接收到的数据放入到发送寄存器
	while(!TI);			 //等待发送数据完成
	TI=0;				 //清除发送完成标志位
}


unsigned char convert(int temp)
{
	unsigned char m;
	m=(char)(temp / 10+temp % 100+ temp % 10);
	return m;
}*/
//----------------------------------------------------------------------------------
void main()
{    
				unsigned char sec_buf = 0x00;	//用来保存上一次的秒数
				uint i;
				int hight=27,low=20;  //定义上限为27度,下限为20度。
				uchar L, H;
				init_12864();           		//12864初始化
				DS1302_Init();					//DS1302初始化
				DS1302_Write_Time();			//初始化数据
        UART_init();             //串口通信初始化函数
				
  get:  print(1,0,"    年  月  日");
	    	print(2,0,"    时  分  秒");
	      print(3,0,"    长江大学");
	    	
/*---------------------------------------------------------	
	时间显示↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
-----------------------------------------------------------*/
			while(1)
		{
					DS1302_Read_Time();

			
					SetTime(); //设定时间
			
			 if(Time_buf[1] != sec_buf)					//当前时间与原来时间不同
				{    
					  sec_buf = Time_buf[1];						//把当前的秒数赋值给临时变量
            display_int(1,0,ChangeTime(Time_buf[0]));	//年
            display_int(1,1,ChangeTime(Time_buf[6]));	//年
            display_int(1,3,ChangeTime(Time_buf[5]));   //月
			      display_int(1,5,ChangeTime(Time_buf[4]));   //日
            display_int(2,1,ChangeTime(Time_buf[3]));   //时
            display_int(2,3,ChangeTime(Time_buf[2]));   //分
			      display_int(2,5,ChangeTime(Time_buf[1]));	//秒
					
					
				}
				if((Time_buf[5]==1)&&(Time_buf[4]==1))  //春节
							display(4,0,&table7);
				 else if((Time_buf[5]==5)&&(Time_buf[4]==5))  //端午节
							display(4,0,&table8);
	   else  
			 	display(4,0,&table10);
					
				if(key1 == 0)//切换到温度显示界面
				{
						init_12864();
						break;//按下切换到温度显示界面
				}
		}

//-----------------------------------------------------------
//-----------------------------------------------------------
					//作用:	将三行汉子固定显示,不刷新
					display(1,0,&table1);  //在第1行显示
					display(2,0,&table2);
					display(3,0,&table3);
		   
		
		
		
//=========================================================
//温度显示↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			while(1)
		{

							Init_DS18B20();  //初始化DS18B20
							Write_Byte(0xcc);  //发送跳跃ROM指令
							Write_Byte(0x44);  //发送温度转换指令
			        Delay_8us(100);
							Init_DS18B20();  //初始化DS18B20
							Write_Byte(0xcc);  //发送跳跃ROM指令
							Write_Byte(0xbe);  //读取DS18B20暂存器值
							L = Read_Byte();  //读高速暂存器的byte0(低字节,二进制数)
							H = Read_Byte();  //读高速暂存器的byte1(高字节,二进制数)
							i = H;  //高8位赋值给i
					    i <<= 8;  // 低8位的数据整体左移8位
							i |= L;	  // 高8位的数据填充低8位移走的空位,组成16位的二进制赋值给i
			if(i>0xfff)//温度为负数时候取反+1
			{	i=~i+1;
				display(1,0,&table6);//超过范围在其前面显示“——”表示负温度
		   
			}
			
				i = i * 0.0625 * 10 + 0.5;  //读到的二进制数据转换温度的算法
			       // receiveData=	convert(i);	//转换为字符串 
			        LcdDisplay(i); //温度显示函数
							LcdDisplay_hight(hight);
							LcdDisplay_low(low);
			
			
				if((i>=hight*10)|(i<=low*10)) //温度高于上下限就报警
					{

								display(4,0,&table4);
						
							//这里还可以加入呼吸灯进行报警,或者其他的一些报警功能
											
											BUZZ = 0;    //拉低蜂鸣器响
									    deng=0;
					}
											
					
			else
					{
								BUZZ=1;
						deng=1;
								display(4,0,&table5);//在第四行显示,即显示温度稳定(没有超过范围)
					}
										
//---------------------------------------------------------------------
//按键调上限
								
					
					if(array()==3)    //当key2按下一次时,上限温度加一,一直按一直加
				{
				
					hight++;
				}
					if(array()==7)   //当key4按下一次时,上限温度减一,一直按一直减
				{  
					
						hight--;
				}
//-----------------------------------------------------------------------
//调下限
										
					if(array()==11)    //当key11按下一次时,下限限温度加一,一直按一直加
										{
												low++;
										}
					if(array()==15)   //当key15按下一次时,下限温度减一,一直按一直减
										{
												low--;
										}
//--------------------------------------------------------------------
										
			if(key3 == 0)
				{
		    Delay_8us(20);//软件延时
					if(key3==0)
					{init_12864 ();
						goto get;}
					break;//按下切换到时间显示界面,但不初始化时间,接着开机时计算(后台走时)
				}  
			}
		
		}

		

LCD12864.c 主要一些延时和LCD12864的驱动)

#include "lcd12864.h"
#include 
/******************************
功能:LCD12864驱动
*******************************/
void delay(uint x)//延时函数
{
	uint i;
	for(i=x;i>0;i--);
}


void Delay50ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
//i = 2;
	//j = 26;
//k = 223;
	i=1;
	j=1;
	k=120;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}



void writecommand(uchar command)//写指令函数,对应指令值为其参数command
{
	check_busy();
  E=0; //初始化使能端
	RS=0;//选择命令
	RW=0;//选择写入
	out=command;//放置数据
	E=1;//写时序
	_nop_();
	E=0;
}


void check_busy()//查忙(液晶查忙)
{
 uchar dt;
 do
 {
  dt=0xff;
	E=0;
	RS=0;//选择命令
	RW=1;//选择读取
	E=1;
	dt=out;
 }
  while(dt&0x80);
  E=0;
}

void writedate (uchar date )
{
    
    check_busy();           //检测忙标志
    E=0;                    //写数据时,E=1,所以先置E=0;
    RS=1;     
    RW=0;  
    out=date;               //将数据写入P0口,即写入LCD  
    E=1;
    _nop_();                //硬件反应时间
    E=0; 
    Delay50ms();
}


void init_12864 ()   //初始化12864
{
		PSB=1;//并行
    writecommand(0x30);              //设定为基本功能
	
    writecommand(0x0c);               //  命令0x0c:设置开显示,不显示光标(开启整体显示) 
    
    writecommand(0x06);               //  命令0x06:写一个字符后地址指针加1,整屏显示不移动
    
    writecommand(0x01);               //  显示清屏
}


/*******************************************
*函数名:指定位置函数
*功能:选择在12864显示的位置
*输入参数:X ,Y
*输出参数:无
********************************************/
void place(uchar x,uchar y)//指定位置
{
			uchar sum;
			if(x == 1)	//第一行
				x = 0x80;
			if(x == 2)	//第二行
				x = 0x90;
			if(x == 3)	//第三行
				x = 0x88;
			if(x == 4)	//第四行
				x = 0x98;
			sum = x + y;	//x为行 ,y 该行为第几位
			writecommand(sum);	//将行数与列数整合
}


/*****************************************
*函数名:12864显示函数 
*功能:将想要显示的数据在12864上显示出来
*输入参数:X , Y , *P
*输出参数:无
******************************************/
void display(uchar x, uchar y, uchar *p)
{
			place(x,y);				//调用位置函数
			while(*p != '\0')	//判断是否到最后一个字符
			{
				writedate(*p);		//读取数据
				p++;						//指向向下一个元素
			}
}



void LcdDisplay(int temp)   //温度显示函数  
{
			unsigned char  datas[] ={9,8,2}; //数组存温度数据
			unsigned char  charper [6]= "摄氏度";
			unsigned char i;
			datas[0] = temp / 100;	  //获取十位
			datas[1] = temp % 100 / 10;	   //获取个位
			datas[2] = temp % 10 ;		   //显示小数点后一位
			
			writecommand(0x84);
			writedate('0'+datas[0]);
			SBUF='0'+datas[0];
			while(!TI);
				TI=0;
			writecommand(0x85);
			writedate('0'+datas[1]);
				SBUF='0'+datas[1];
			 while(!TI);
				TI=0;
			
			writecommand(0x86);
			writedate('.');
			SBUF='.';
			while(!TI);
			TI=0;
			
			writecommand(0x87);
			writedate('0'+datas[2]);
				SBUF='0'+datas[2];
			while(!TI);
				TI=0;
			for(i=0;i<6;i++)
			{ 
				SBUF=charper[i];
					while(!TI);
			  TI=0;
			}
			

}



void LcdDisplay_hight(int temp)   //上限温度显示函数  
{
			unsigned char  datas[] ={0,0}; //数组上限存温度数据
			datas[0] = temp / 10;	  //获取十位
			datas[1] = temp % 10;	   //获取个位
			
			writecommand(0x94);
			writedate('0'+datas[0]);
			
			writecommand(0x95);
			writedate('0'+datas[1]);
			

}



void LcdDisplay_low(int temp)   //温度下限显示函数  
{
		unsigned char  datas[] ={0,0}; //数组下限存温度数据
		datas[0] = temp / 10;	  //获取十位
		datas[1] = temp % 10;	   //获取个位
		
		writecommand(0x8c);
		writedate('0'+datas[0]);
		
		writecommand(0x8d);
		writedate('0'+datas[1]);
		
	
}


//----------------------------------------------------------------
void ad_ope(uchar x,uchar y)//地址选择
{
			uchar num;
			switch(x)
			{
				case 1: x=0x80; break;
				case 2: x=0x90; break;
				case 3: x=0x88; break;
				case 4: x=0x98; break;
			}
			num=x+y;
			writecommand(num);
}




void print(uchar x,uchar y,uchar *s)//输出
{
			uint i = 0;
			ad_ope(x,y);
			while(*s>0)
			{
				writedate(*s++);
				i++;
				delay(10);
			}
			if(i == 1) writedate(' ');		//如果只有一位数就把这位数后面的一个空位覆盖为空格		
}



void display_int(uchar x,uchar y, int voltage)//整数输出
{	
			unsigned char value[8];
			
			sprintf(value, "%d", voltage);
			print(x,y,value);
			delay(1);
}


/*------------------------------------------------*/

uchar array(void)//矩阵键盘,判断按键是否被按下,那个按键被按下
{
	uchar x,y,z;
	uchar key = 16;
	
	P1=0x0f;    
	if(P1!=0x0f)
	{
		delay(2500);//软件延时
		if(P1!=0x0f)//是否有按键按下
		{
			x  = P1&0x0f;  //检测列
			P1 = 0xf0;
			delay(2500);//软件延时
			y  = P1&0xf0;//接着检测行
			z  = x|y;//按位相与后判断具体那一位被按下(普中科技开发板对应的按键值加1既可)
			switch(z)
			{
				case 0xee: key=0; break; 
				case 0xde: key=1; break; 
				case 0xbe: key=2; break; 
				case 0x7e: key=3; break; 
				case 0xed: key=4; break;
				case 0xdd: key=5; break;
				case 0xbd: key=6; break;
				case 0x7d: key=7; break;
				case 0xeb: key=8; break; 
				case 0xdb: key=9; break; 
				case 0xbb: key=10; break; 
				case 0x7b: key=11; break; 
				case 0xe7: key=12; break;
				case 0xd7: key=13; break;
				case 0xb7: key=14; break;
				case 0x77: key=15; break;
			}
		}
	}
	return key;
}

/*-----------------------------------------------*/

LCD12864.h (主要一些函数的声明)

#ifndef _lcd12864_H_
#define _lcd12864_H_

/******包含的头文件声明区***********/
#include 
#include 
#include 

/*********宏定义区域*********/
#define uchar unsigned char  
#define uint unsigned int    
#define out P0

/*********端口定义区********/
sbit E=P2^7;//使能
sbit RW=P2^5;//读写
sbit RS=P2^6;//寄存器选择输入
sbit PSB=P3^2;//串并行方式选择,1并,0串

/************函数声明区**********/
extern void Delay50ms();
extern void Delay100ms();
extern void condition();
extern void writecommand();
extern void check_busy();
extern void writedate ();
extern void init_12864();  

extern uchar array(void);//矩阵按键扫描

void place(uchar x,uchar y);//选择在12864显示位置
void display(uchar x, uchar y, uchar *p);
void LcdDisplay(int temp);
void LcdDisplay_hight(int temp);
void LcdDisplay_low(int temp);


extern void print(uchar,uchar,uchar*);//显示数据
//extern void display_float(uchar,uchar,float);
extern void display_int(uchar,uchar, int);


#endif

DS18B20.c(DS18B20驱动程序) 

#include "DS18B20.H"
bit flag;
/*这里时钟都是以11.0592M写的,*/
void Delay_8us(unsigned int us)//@11.0592MHz 粗略延时1ms
{
while(us--);
}
/*******************************************************************************
* 函数名   	: Init
* 描述	    : DS18B20复位初始化
* 输入参数  : 无
* 返回参数  : 返回值为0或者1,为0则复位初始化成功 为1则复位初始化失败.
********************************************************************************/

Init_DS18B20(void)
{ 		unsigned char x=0;
			DQ = 1;      //复位  先将数据线置高
			Delay_8us(10);    //延时一下
			DQ = 0;
			Delay_8us(80);
			DQ = 1;      //释放总线
		  Delay_8us(20); //延时120us  等待应答脉冲
			x = DQ;   //接受应答
		   Delay_8us(30); 
			return x;
}

/*******************************************************************************
* 函数名	  : Write Byte
* 描述	    : 写一个字节从低位到高位发送,写位分为写0,写1两者的时隙不同
* 输入参数  : 要写入的一个字节
* 返回参数  : 无
********************************************************************************/
void Write_Byte(unsigned char  byte)
{
   unsigned char i=0;
   for(i=8;i>0;i--)
   {
      DQ=0;
      DQ=byte&0x01;
      Delay_8us(5);
      DQ=1;
      byte>>=1;
   }
   //return(byte);
}

/*******************************************************************************
* 函数名	  : Read_Byte
* 描述	    : 读一个字节,从低位到高位读取,
              总线拉低读时隙开始,开始至15us内控制器采样完成
* 输入参数  : 无
* 返回参数  : 读取到的一个字节
********************************************************************************/
unsigned char  Read_Byte(void)
{
			int i;
			unsigned char  byte = 0;
			for(i=0;i<8;i++)
			{ 
				DQ = 0;             //主机输出低电平 
				byte>>=1;         //先读取低位,每次移一位直至读完一个字节
				DQ =1;
				if(DQ)           //判断读到位是否为1
				{
				byte|=0x80;	//若总线为1,即DQ为1,那就把byte的最高位置1;若为0,则不进行处理,保持为0
				}								            			
	      Delay_8us(4);
				
			}
			return  byte;
}

DS18B20.h(作用请参考上述.h文件) 

#ifndef _DS18B20_h_
#define _DS18B20_h_

#include "reg51.H"
#include 


sbit DQ = P2^0;   //DS18B20单总线,作为测温芯片输出口

extern void Delay_8us(unsigned int ms);
extern Init_DS18B20(void);
extern void Write_Byte(unsigned char  byte);
extern unsigned char  Read_Byte(void);


#endif

DS1302.c(时钟芯片的驱动程序)

/*******************************************************************************
* 文件名 : DS1302.c
* 实现功能:DS1302驱动程序
* 
*******************************************************************************/  

#include "DS1302.h"


/*******************************************************************************
* 功能描述 : DS1302初始化
* 函数属性 : 外部
* 输入参数 : 无
* 返回参数 : 无
* 函数详解 :上电运行时,在VCC大于或小于2.5V之前,RST必须
*						保持低电平,只有在SCLK为低电平时,RST才能被置高 。
*******************************************************************************/
void DS1302_Init()
{
		RST = 0;      //片选,RST其实质相当于片选CE
		SCLK = 0;     在sclk拉低的前提前才能拉高RST
}

/*******************************************************************************
* 功能描述 : 数据输入函数
* 函数属性 : 外部
* 输入参数 : 无
* 返回参数 : 无
* 函数详解 : 数据输入,一个字节的输入将在下8个时钟周期的上升沿完成,
*						 数据传输从字节最低位开始。
*******************************************************************************/
void DS1302_Data_Input(unsigned char Address,unsigned char Data)
{
			unsigned char i;
			RST = 1;//启动DS1302总线
			Address = Address & 0xFE;//最低位置0,寄存器0位时写,1时读,这时为写数据
			for(i=0;i<8;i++)
			{
				SCLK = 0;
				if(Address&0x01)    //数据从低位开始传送
				{
					DAT = 1;
				}
				else
				{
					DAT = 0;
				}	
				SCLK = 1;//上升沿写入指令
				Address = Address>>1;
			}
			for(i=0;i<8;i++)
			{
				SCLK = 0;
				if(Data&0x01)
				{
					DAT = 1;
				}
				else
				{
					DAT = 0;
				}
				SCLK = 1;//上升沿写入数据
				Data = Data>>1;
			}
			SCLK = 0;
			RST = 0;//关闭DS1302总线
}



/*******************************************************************************
* 功能描述 : 数据输出函数
* 函数属性 : 外部
* 输入参数 : 无
* 返回参数 : 无
* 函数详解 : 数据输出,一个字节的数据将在下个8个时钟周期的下降沿被输出。注意第一位输出
*			 是在最后一位控制指令所在的下降沿被输出,要求RST保持位高电平
*******************************************************************************/
unsigned char DS1302_Data_Output(unsigned char Address)
{
			unsigned char i;
			unsigned char temp;
			RST = 1;
			Address = Address | 0x01;
			for(i=0;i<8;i++)
			{
				SCLK = 0;
				if(Address&0x01)
				{
					DAT = 1;
				}
				else
				{
					DAT = 0;
				}
				SCLK = 1;
				Address = Address>>1;
			}

			for(i=0;i<8;i++)
			{
				SCLK=0;
				temp = temp >> 1;
				if (DAT)
				{
					temp |= 0x80;
				}
				else
				{
					temp &= 0x7F;
				}
				SCLK=1;
			}
			SCLK=0;
			RST = 0;
			return temp;

	
}

/*******************************************************************************
* 功能描述 : 初始化时间
* 函数属性 : 外部
* 输入参数 : 无
* 返回参数 : 无
* 函数详解 : 
*******************************************************************************/
void DS1302_Write_Time(void)
{
			DS1302_Data_Input(DS1302_CONTROL_ADD,0x00);		//关闭写保护,允许数据写入寄存器,数据内容为0(写入允许)
			DS1302_Data_Input(DS1302_SEC_ADD,0x80);			//CH位置高,振荡器停止,置低,振荡器工作允许	
			DS1302_Data_Input(DS1302_CHARGER_ADD,0xa9);

			 
			/*初始值*/
			DS1302_Data_Input(DS1302_SEC_ADD,Time_buf[1]);		//秒
			DS1302_Data_Input(DS1302_MIN_ADD,Time_buf[2]);		//分
			DS1302_Data_Input(DS1302_HR_ADD,Time_buf[3]);		//时
			DS1302_Data_Input(DS1302_DAY_ADD,Time_buf[4]);		//日
			DS1302_Data_Input(DS1302_MONTH_ADD,Time_buf[5]);	//月
			DS1302_Data_Input(DS1302_YEAR_ADD,Time_buf[6]);		//年
			
			DS1302_Data_Input(DS1302_CONTROL_ADD,0x80);			//打开写保护
}


/*******************************************************************************
* 功能描述 : 读取时间
* 函数属性 : 外部
* 输入参数 : 无
* 返回参数 : 无
* 函数详解 : 
*******************************************************************************/
void DS1302_Read_Time(void)  
{
			Time_buf[1]=(DS1302_Data_Output(DS1302_SEC_ADD))&0x7f;	//秒,屏蔽秒的第7位,避免超出59
			Time_buf[2]=DS1302_Data_Output(DS1302_MIN_ADD);			//分
			Time_buf[3]=DS1302_Data_Output(DS1302_HR_ADD)&0x3F;		//时  3f --	0011 1111
			Time_buf[4]=DS1302_Data_Output(DS1302_DAY_ADD);			//日
			Time_buf[5]=DS1302_Data_Output(DS1302_MONTH_ADD);		//月
			Time_buf[6]=DS1302_Data_Output(DS1302_YEAR_ADD);		//年	
}


/*8421码转换*/
unsigned char ChangeTime(unsigned char tim)
{
			unsigned char Time;
			if((tim&0x0F)>9)						//如果个位超过9,则十位加一后,个位清零
			{
				tim=((tim+0x10)&0xF0);				//0x4A+0x10=0x5A&0xF0=0x50
													
			}										//如果没有则跳过该部分
			
			Time = (tim>>4)*10+(tim&0x0f);			//把8421码转变成10进制的数
													//0x50>>4=0x05*10=50,0x50&0x0f=0x00=0 ;50
			return Time;							//返回这个数的值
}

DS1302.h 

/*******************************************************************************
* 文件名 : DS1302.h
* 实现功能:一些初始化

*******************************************************************************/  

#ifndef __DS1302_H__
#define __DS1302_H__ 


#include 
#include 
#include 
#include 
#include "lcd12864.h"


sbit SCLK =  P3^6;//串行时钟输入端口
sbit DAT  =  P3^4;//数据IO端口
sbit RST  =  P3^5;//复位输入端



#define		DS1302_SEC_ADD			 0x80//秒(写秒寄存器)
#define		DS1302_MIN_ADD			 0x82//分(写分寄存器)
#define		DS1302_HR_ADD			   0x84//时(写时寄存器)
#define		DS1302_DAY_ADD			 0x86//日(同理)
#define		DS1302_MONTH_ADD		 0x88//月
#define		DS1302_YEAR_ADD			 0x8C//年

#define		DS1302_CONTROL_ADD		0x8E//控制
#define		DS1302_CHARGER_ADD		0x90//涓流充电					 
#define		DS1302_CLKBURST_ADD		0xBE//时钟多字节


extern unsigned char Time_buf[7];//={0x20,0x20,0x13,0x15,0x17,0x05,0x20};//秒,分,时,日,月,年;//时间缓冲数组


extern void DS1302_Init();													//初始化DS1302

extern void DS1302_Data_Input(unsigned char Address,unsigned char Data);	//数据输入
extern unsigned char DS1302_Data_Output(unsigned char Address);				//数据输出

extern void DS1302_Write_Time(void);										//写入初始化时间
extern void DS1302_Read_Time(void);											//读取时间
extern unsigned char ChangeTime(unsigned char tim);  /*8421码转换*/


#endif

1.5成果展示

 基于51单片机的数字温度计【开源】_第2张图片

基于51单片机的数字温度计【开源】_第3张图片

需要工程文件可以留言 

资源已经上传到个人资源链接(免费,免积分)和大家共同学习。用完就点个关注吧

你可能感兴趣的:(嵌入式,51单片机,单片机,嵌入式硬件)