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

📄 ds1302.c

📁 DS1302+89C52六位数码管电子时钟
💻 C
字号:
#include <reg51.h>

sbit CLK=  P1^0;					//DS1302相关控制信号
sbit DIO=  P1^1;
sbit CE=  P1^2;

sbit SET=  P3^0;					//设置键
sbit ADD=  P3^1;					//加键
sbit DEC=  P3^2;					//减键

sbit ALAM= P3^6;					//闹钟输出

sbit DQ =  P3^4;					//18B20 I2C通讯口

sbit xsdxs=  P0^7;
bit xsd;
bit run_OR_Set=0;					//正常走时/设置标志
bit see_Tempreture=0;				//查看温度标志位,=1时查看温度
bit see_Timer=0;					//查看闹钟

bit zd=0;							//整点报时位
bit sd=0;							//设置时闪动  =1时开启闪动
unsigned char sd_char=0xFF;			//闪动时置数
unsigned char ZDJS=0;				//整点计数
unsigned char countt0;				//t0中断计数器
unsigned char countt1;				//t1中断计数器
unsigned char set_Count=0;			//设置计数器,
unsigned char setNZn=0;				//设置闹钟计数器

unsigned char NZ_hour=0,NZ_minit=0;	//闹钟初值
unsigned char BCD_NZ_hour,BCD_NZ_minit; //
bit NZ=0;							//闹钟标志位
unsigned char hour,minit,second,lastsecond;
unsigned char temp_hour,temp_minit,temp_second;


unsigned char code LED_DATA[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // 共阴
						//{0x28,0xEE,0x32,0xA2,0xE4,0xA1,0x21,0xEA,0x20,0xA0}; //共阳



void delay(unsigned int time)
{				  
	while(--time);
}

//==============================================================================
//=============================DS18B20==========================================
//==============================================================================
unsigned char flag_Negative_number = 0;//负数标志

//晶振12MHz  
void delay_18B20(unsigned int i)
{
 	while(i--);
}

//初始化函数
void Init_DS18B20(void) 
{
	unsigned char x=0;
	DQ = 1;          //DQ复位
	delay_18B20(4);  //稍做延时
	DQ = 0;          //单片机将DQ拉低
	delay_18B20(80); //精确延时 大于 480us   //100
	DQ = 1;          //拉高总线
  	delay_18B20(14);
  	x = DQ;           //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
	delay_18B20(20);	 
}

//读一个字节  
unsigned char ReadOneChar(void)
{
	unsigned char i=0;
	unsigned char dat = 0;
	for (i=8;i>0;i--)
	 {
		  DQ = 0; // 给脉冲信号
		  dat>>=1;
		  DQ = 1; // 给脉冲信号
		  if(DQ)
		  dat|=0x80;
		  delay_18B20(10);
	 }
 	return(dat);
}

//写一个字节  
void WriteOneChar(unsigned char dat)
{
 unsigned char i=0;
 for (i=8; i>0; i--)
 {
  DQ = 0;
  DQ = dat&0x01;
  delay_18B20(10);
  DQ = 1;
  dat>>=1;
 }
}

//读取温度
unsigned int ReadTemperature(void)
{
	unsigned char a=0;
	unsigned char b=0;
	unsigned int t=0;
	float tt=0;		 
	Init_DS18B20();
	WriteOneChar(0xCC); //跳过读序号列号的操作
	WriteOneChar(0x44); //启动温度转换
	Init_DS18B20();
	WriteOneChar(0xCC); //跳过读序号列号的操作
	WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
	a=ReadOneChar();
	b=ReadOneChar();

	//启动下一次温度转换
	//Init_DS18B20();
	//WriteOneChar(0xCC); // 跳过读序号列号的操作
	//WriteOneChar(0x44); // 启动温度转换
		
	t=b;
	t<<=8;
	t=t|a;

	flag_Negative_number = 0;

	if(t>0x0fff) 
	{
		t=~t+1;
		flag_Negative_number = 0xff;
	}
	//18b20:t=d*0.0625	
	tt=t*0.0625;
	t=tt*10+0.5; //有效位到小数点后2位,适用Proteus6.9版本和实物版
	//t = t*5; //有效位到小数点后2位,适用Proteus7以上版本
	return(t);
}
//==============================================================================
//==============================================================================
//==============================================================================




//==============================================================================
//============================DS1302============================================
//==============================================================================
unsigned char du1302(unsigned char dizhi)
{
  	unsigned char i,jieguo;
  	CLK=0;
  	CE=1;
  	for(i=0;i<8;i++)
  	{
		DIO=dizhi&  0x01;
		CLK=1;CLK=0;
		dizhi=dizhi>>1;
	}
  	DIO=1;
  	jieguo=0;
  	if(DIO==1){jieguo=jieguo|0x80;}
  	for(i=0;i<7;i++)
    {
		CLK=1;CLK=0;
		jieguo=jieguo>>1;
		if(DIO==1){jieguo=jieguo|  0x80;}
	}
  	CE=0;
	return(jieguo);
}

void xie1302(unsigned char dizhi,shuju)
{
  	unsigned char i;
  	CE=1;
  	for(i=0;i<8;i++)
    {
		DIO=dizhi&  0x01;
		CLK=1;CLK=0;
		dizhi=dizhi>>1;
	}
  	for(i=0;i<8;i++)
    {
		DIO=shuju&  0x01;
		CLK=1;CLK=0;
		shuju=shuju>>1;
	}
  	CE=0;
}
//========================================================================
//========================================================================
//========================================================================


void display(void)
{
	unsigned int temp;
	if(see_Tempreture==1)								//---------------显示温度----------------------
	{
		temp = ReadTemperature();//*5;
	
		if(flag_Negative_number)
			P0 = 0x40;
		else 
	 		P0 = 0x00;
		P2 = 0xBF;
		delay(300);
		P2 = 0xFF;
		
		P0 = LED_DATA[temp/100%10];
		P2 = 0xDF;
		delay(300);
		P2=0xFF;
	
		//P0 = LED_DATA[temp/10%10+10];
		P0 = LED_DATA[temp/10%10];
		P2 = 0xEF;
		delay(300);
		P2=0xFF;
	
		P0 = LED_DATA[temp%10];
		P2 = 0xF7;
		delay(300);
		P2=0xFF;
	
		P0 = 0x58;
		P2 = 0xFB;
		delay(300);
		P2=0xFF;
	}
	else
	{
		if(see_Timer==1)					//------------显示闹钟--------------------
		{
			unsigned char D1,D2,D3,D4,D5,D6;
			D1=NZ_hour/10;  	D2=NZ_hour%10;
			D3=NZ_minit/10;  	D4=NZ_minit%10;
			D5=0; 				D6=0;
			if(setNZn==1)
		  		P0= (LED_DATA[D1]&sd_char);		//display hour
			else
				P0= LED_DATA[D1];
		  	P2= 0x7F;
		  	delay(300);
			P2= 0xFF;
			if(setNZn==1)
		  		P0= ((LED_DATA[D2]|0x80)&sd_char);
			else 
				P0= LED_DATA[D2]|0x80;
			//xsdxs=xsd;
		  	P2=  0xBF;
		  	delay(300);
			P2= 0xff;
			
			if(setNZn==2)
		  		P0= (LED_DATA[D3]&sd_char);		//display minit
			else
				P0= LED_DATA[D3];
		  	P2=  0xDF;
		  	delay(300);
			P2=0xff;
			if(setNZn==2)
		  		P0= (LED_DATA[D4]&sd_char);
			else
				P0= LED_DATA[D4];
		  	P2=  0xEF;
		  	delay(300);
			P2=0xff;
		
		  	P0= LED_DATA[D5];		//display second
		  	P2=  0xF7;
		  	delay(300);
			P2=0xff;
		  	P0= LED_DATA[D6];
		  	P2=  0xFB;
		  	delay(300);
			P2=0xff;
		}

		else									//--------------------显示时间-----------------
		{
			unsigned char D1,D2,D3,D4,D5,D6;
			if(run_OR_Set==1)
				second=0x00;
			else
				second= du1302(0x81);
			minit= du1302(0x83);
			hour= du1302(0x85);
			if(second!=lastsecond){xsd=!xsd;}
			lastsecond=second;
			D1=hour>>4;  	D2=hour&0x0f;
			D3=minit>>4;  	D4=minit&0x0f;
			D5=second>>4; 		D6=second&0x0f;
			if(set_Count==1)
		  		P0= (LED_DATA[D1]&sd_char);		//display hour
			else
				P0= LED_DATA[D1];
		  	P2= 0x7F;
		  	delay(300);
			P2= 0xFF;
			if(set_Count==1)
		  		P0= ((LED_DATA[D2]|0x80)&sd_char);
			else 
				P0= LED_DATA[D2]|0x80;
			//xsdxs=xsd;
		  	P2=  0xBF;
		  	delay(300);
			P2= 0xff;
			
			if(set_Count==2)
		  		P0= (LED_DATA[D3]&sd_char);		//display minit
			else
				P0= LED_DATA[D3];
		  	P2=  0xDF;
		  	delay(300);
			P2=0xff;
			if(set_Count==2)
		  		P0= (LED_DATA[D4]&sd_char);
			else
				P0= LED_DATA[D4];
		  	P2=  0xEF;
		  	delay(300);
			P2=0xff;
		
		  	P0= LED_DATA[D5];		//display second
		  	P2=  0xF7;
		  	delay(300);
			P2=0xff;
		  	P0= LED_DATA[D6];
		  	P2=  0xFB;
		  	delay(300);
			P2=0xff;
		}
	}
}



void key_Scan(void)
{
	if(SET==0)								//SET键按下
	{
		display();					//调用显示,用于延时消抖
		if(SET==0)
		{
			TR1=0;					//停止闹钟
			NZ=0;
			if(see_Tempreture==0)
			{
				if(see_Timer==0)
				{
					setNZn=0;
					second=0x00;
					run_OR_Set=1;					//开启设置标志
					xie1302(  0x8E,  0x00);
					xie1302(  0x80,  0x80);			//时钟停止走时	
					xie1302(  0x8E,  0x80);
					set_Count++;
					TR0=1;							//开启定时器0
					if(set_Count==3)
					{
						run_OR_Set=0;				//关闭设置标志位
						set_Count=0;				//设置计数器清零,
						TH0=0x3C;
						TL0=0xB0;
						TR0=0;						//关闭定时器0
						sd=0;						//关闭闪动
						sd_char=0xFF;
						xie1302(  0x8E,  0x00);
						xie1302(  0x80,  0x00);		//时钟启动
						xie1302(  0x8E,  0x80);
					}
				}
				else
				{
					set_Count=0;
					setNZn++;
					TR0=1;
					if(setNZn==3)
					{
						setNZn=0;
						NZ=1;							//开启闹钟
						BCD_NZ_hour=(((NZ_hour/10)<<4)+(NZ_hour%10));		//将闹钟时间转换为BCD数
						BCD_NZ_minit=(((NZ_minit/10)<<4)+(NZ_minit%10));
						TH0=0x3C;
						TL0=0xB0;
						TR0=0;
						sd=0;
						sd_char=0xFF;
					}
				}
			}
		}	
		do
			display();
		while(!SET);
	}

	if(ADD==0)
	{					
		display();								//调用显示,用于延时消抖
 		if(ADD==0)
		{
			if(TR1==1)
			{
				TR1=0;
				ALAM=1;
			}
			else
			{
				if(see_Tempreture==0)
				{
					if(set_Count==0)
					{
						if(setNZn==0)
						{
							see_Timer=~see_Timer;				//开启查看闹钟功能
							see_Tempreture=0;
						}
						if(setNZn==1)
						{
							NZ_hour++;
							if(NZ_hour==24)
								NZ_hour=0;
						}
						if(setNZn==2)
						{
							NZ_minit++;
							if(NZ_minit==60)
								NZ_minit=0;
						}
					}
		
					if(set_Count==1)						//调小时
					{
						hour++;
						if((hour&0x0f)>=10)				//控制十进制进位
						{
							hour=hour+0x10;
							hour=hour&0xf0;
						}
		
						if(hour>=0x24)					//1302内部以16进制保存数据
							hour=0;
		
						xie1302(  0x8E,  0x00);				//将转换后的小时数据写入1302
						xie1302(  0x80,  0x80);
						xie1302(  0x84,hour);
						xie1302(  0x8E,  0x80);
		
					}
					if(set_Count==2)						//调分钟
					{
						minit++;
						if((minit&0x0f)>=0x0A)				//十进制进位
						{
							minit=minit+0x10;
							minit=minit&0xf0;
						}
						if(minit>=0x60)
							minit=0;
						
						xie1302(  0x8E,  0x00);
						xie1302(  0x80,  0x80);
						xie1302(  0x82,minit);
						xie1302(  0x8E,  0x80);
					}
				}
			}
		}		
		do
			display();
		while(!ADD);
	}

	if(DEC==0)
	{				
		display();								//调用显示,用于延时消抖
		if(DEC==0)
		{
				if(set_Count==0)
				{
					if(setNZn==0)
					{
						see_Tempreture=~see_Tempreture;		//当在非设置状态下可以查看温度
						see_Timer=0;
					}
					if(setNZn==1)
					{	
						if(NZ_hour==0)
							NZ_hour=24;
						NZ_hour--;
					}
					if(setNZn==2)
					{		
						if(NZ_minit==0)
							NZ_minit=60;
						NZ_minit--;
					}
				}
	
				if(set_Count==1)						//调小时
				{
					if((hour&0x0f)>0x00)
						hour--;
					else
					{
						if((hour&0xf0)>0x00)
						{
							hour=hour-0x10;
							hour=hour+0x09;
						}
						else
							hour=0x23;
					}		
			
					xie1302(  0x8E,  0x00);
					xie1302(  0x80,  0x80);
					xie1302(  0x84,hour);
					xie1302(  0x8E,  0x80);
				}
				if(set_Count==2)						//调分钟
				{
					if((minit&0x0f)>0x00)
						minit--;
					else
					{
						if((minit&0xf0)>0x00)
						{
							minit=minit-0x10;
							minit=minit+0x09;
						}
						else
							minit=0x59;
					}
					
					xie1302(  0x8E,  0x00);
					xie1302(  0x80,  0x80);
					xie1302(  0x82,minit);
					xie1302(  0x8E,  0x80);
				}
				
		}
		do
			display();
		while(!DEC);
	}
}




main()
{	
	unsigned char temp_second;
	xie1302(  0x90,  0xa5);
	Init_DS18B20();
	delay(5000);	
	TMOD=0x11;
	TH0=0x3C;
	TL0=0xB0;
	TH1=0x3C;
	TL1=0xB0;
	EA=1;
	ET0=1;
	ET1=1;
	TR0=0;
	TR1=0;
	while(1)
	{	
		key_Scan();

		display();	

		if(NZ==1)
		{
			if((hour==BCD_NZ_hour)&&(minit==BCD_NZ_minit)&&(second==0))
				TR1=1;
			if(minit==(BCD_NZ_minit+1))
			{
				TR1=0;
				ALAM=1;
			}
		}
	
		if((minit==0x00)&&(second==0x00))			//整点
		{
			TR1=1;
			temp_second=second;
		}
	
		if((minit==0x00)&&(second==hour))
		{
			TR1=0;
			ALAM=1;
		}
	}
}

void Initime0(void) interrupt 1
{
	TH0=0x3C;
	TL0=0xB0;
	TR0=1;
	countt0++;
	if(countt0==5)
	{
		countt0=0;
		sd=!sd;
		if(sd==1)
			sd_char=0x00;
		else 
			sd_char=0xFF;
	}
}


void Initime1(void) interrupt 3
{
	TH1=0x3C;
	TL1=0xB0;
	countt1++;
	TR1=1;
	if(countt1==10)
	{
		countt1=0;
		ALAM=~ALAM;
	}
	key_Scan();
}

⌨️ 快捷键说明

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