蓝桥杯单片机第八届初赛试题-电子钟

蓝桥杯单片机第八届初赛试题-电子钟_第1张图片
主要涉及温度传感器 DS18B20 实时时钟DS1302 官网驱动改写。需要注意时间越界问题,小时最多到23,分钟59,秒59,进行判断

#include 
#include "ds1302.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6};
uchar yi,er,san,si,wu,liu,qi,ba;
uchar tem=0;//温度
uchar timeset=4;//时间设置
uchar clockset=0;//闹钟设置
uchar alarm[3]={0,0,0};//闹钟时间 秒 分 时
uchar show_tem=0;//温度显示
uchar s4=0;
uchar tt=0;
uint  count=0;
uchar led=0;
uchar led_show=0;


void allinit();
void Delay1ms(uint ms);
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);
void keyscan();
void Timer0Init(void);

void main()
{
	
	allinit();
	Timer0Init();
	Ds1302_Init();
//	yi=1;er=2;san=3;si=4;wu=5;liu=1;qi=7;ba=8;
	while(1)
	{
		Ds1302_TimeGet();
		tem=temget();
		if(show_tem==0)
		{	
						if(timeset==4)//时钟显示
						{			
								yi=time[2]/10;er=time[2]%10;san=10;
								si=time[1]/10;wu=time[1]%10;liu=10;
								qi=time[0]/10;ba=time[0]%10;
						}
						else if(timeset==1)//小时设置
						{
							if(time[0]%2==1)//通过判断秒进行数码管闪烁 奇数秒亮 偶数灭
							{
								yi=time[2]/10;er=time[2]%10;san=10;
								si=time[1]/10;wu=time[1]%10;liu=10;
								qi=time[0]/10;ba=time[0]%10;
							}
							else
							{
								yi=11;er=11;san=10;
								si=time[1]/10;wu=time[1]%10;liu=10;
								qi=time[0]/10;ba=time[0]%10;
							}
						}
						
						else if(timeset==2)//分钟设置
						{
							if(time[0]%2==1)
							{
								yi=time[2]/10;er=time[2]%10;san=10;
								si=time[1]/10;wu=time[1]%10;liu=10;
								qi=time[0]/10;ba=time[0]%10;
							}
							else
							{
								yi=time[2]/10;er=time[2]%10;san=10;
								si=11;wu=11;liu=10;
								qi=time[0]/10;ba=time[0]%10;
							}
						}
						
						else if(timeset==3)//秒设置
						{
							if(time[0]%2==1)
							{
								yi=time[2]/10;er=time[2]%10;san=10;
								si=time[1]/10;wu=time[1]%10;liu=10;
								qi=time[0]/10;ba=time[0]%10;
							}
							else
							{
								yi=time[2]/10;er=time[2]%10;san=10;
								si=time[1]/10;wu=time[1]%10;liu=10;
								qi=11;ba=11;
							}
						}
						
						
						if(clockset==4)//闹钟显示
						{
								Ds1302_TimeGet();
								yi=alarm[2]/10;er=alarm[2]%10;san=10;
								si=alarm[1]/10;wu=alarm[1]%10;liu=10;
								qi=alarm[0]/10;ba=alarm[0]%10;
						}
						else if(clockset==1)//小时设置
						{
							if(time[0]%2==1)
							{
								yi=alarm[2]/10;er=alarm[2]%10;san=10;
								si=alarm[1]/10;wu=alarm[1]%10;liu=10;
								qi=alarm[0]/10;ba=alarm[0]%10;
							}
							else
							{
								yi=11;er=11;san=10;
								si=alarm[1]/10;wu=alarm[1]%10;liu=10;
								qi=alarm[0]/10;ba=alarm[0]%10;
							}
						}
						
						else if(clockset==2)//分钟设置
						{
							if(time[0]%2==1)
							{
								yi=alarm[2]/10;er=alarm[2]%10;san=10;
								si=alarm[1]/10;wu=alarm[1]%10;liu=10;
								qi=alarm[0]/10;ba=alarm[0]%10;
							}
							else
							{
								yi=alarm[2]/10;er=alarm[2]%10;san=10;
								si=11;wu=11;liu=10;
								qi=alarm[0]/10;ba=alarm[0]%10;
							}
						}
						
						else if(clockset==3)//秒设置
						{
							if(time[0]%2==1)
							{
								yi=alarm[2]/10;er=alarm[2]%10;san=10;
								si=alarm[1]/10;wu=alarm[1]%10;liu=10;
								qi=alarm[0]/10;ba=alarm[0]%10;
							}
							else
							{
								yi=alarm[2]/10;er=alarm[2]%10;san=10;
								si=alarm[1]/10;wu=alarm[1]%10;liu=10;
								qi=11;ba=11;
							}
						}
		}
		else if(show_tem==1)
		{
	
			yi=11;er=11;san=11;si=11;wu=11;liu=tem/10;qi=tem%10;ba=12;//长按S4进行温度显示
			
		}
		if((time[2]==alarm[2])&&(time[1]==alarm[1])&&(time[0]==alarm[0]))//闹钟
		{
			EA=1;ET0=1;//打开中断控制led闪烁
			led_show=1;		
		}				
		  keyscan();
			display1(yi,er);
			display2(san,si);
			display3(wu,liu);
			display4(qi,ba);
	}

}
void keyscan()
{
	if(P30==0)//s7
	{
			Delay1ms(5);
		  if(P30==0)
			{
				
				if(led_show==0)
				{
				//时间显示和闹钟界面只能显示一个
				if(timeset==0) {timeset=4;clockset=0;}//时间显示 闹钟不显示
				else if(timeset==4) timeset=1;//时间显示 timeset初始化为4
				else if(timeset==1) timeset=2;
				else if(timeset==2) timeset=3;
				else if(timeset==3) timeset=4;
				
				}
				else if(led_show==1)
				{
				led_show=0;
				P2=0X80;
				P0=0XFF;
				}
				
		
			}
	while(!P30);
	}
	
	else if(P31==0)//s6
	{
			Delay1ms(5);
		  if(P31==0)
			{
		
			if(led_show==0)
			{	
		  	if(clockset==0) {clockset=4;timeset=0;}// 闹钟显示  时间不显示
				else if(clockset==4) clockset=1;//时间显示 timeset初始化为4
				else if(clockset==1) clockset=2;
				else if(clockset==2) clockset=3;
				else if(clockset==3) clockset=4;	
			}
			else if(led_show==1)
			{	
			led_show=0;
			P2=0X80;
			P0=0XFF;
			}
			
				
			}
	while(!P31);
	}
	
	else if(P32==0)//s5
	{
		  Delay1ms(5);
		 if(P32==0)
		{
				if(led_show==0)
				{
					      //时间调整 时 分 秒
								if(timeset==1)
								{
									if(time[2]==23)	
										time[2]=0;
									else time[2]++;Ds1302_Init();
								}
								else if(timeset==2)
								{
										if(time[1]==59)
													time[1]=0;
										else time[1]++;Ds1302_Init();
								}

								else if(timeset==3)
								{
										if(time[0]==59)
												time[0]=0;
										else time[0]++;Ds1302_Init();
								}

						  	 //调整闹钟 时 分 秒			
								else if(clockset==1)
										{
										if(alarm[2]==23)
											alarm[2]=0;
										else{alarm[2]++;}
										}
								else if(clockset==2)
								{
									if(alarm[1]==59)
											alarm[1]=0;
									else{alarm[1]++;}
								
								}
								else if(clockset==3)
								{
									if(alarm[0]==59)
											alarm[0]=0;
									else{alarm[0]++;}
								
								}		

						}
							else if(led_show==1)
							{	
							led_show=0;
							P2=0X80;
							P0=0XFF;
							}
		while(!P32);
	}
}			
					else if(P33==0)//s4
					{
								Delay1ms(5);
								if(P33==0)
								{
									s4=1;//判断按键是否按下的标志位
									if(timeset==4) show_tem=1;							
								}
					}
					//====写在按键检测之后======//
							if((s4==1)&&(P33==1))
							{
										s4=0;show_tem=0;
										if(led_show==0)
												{
													//时间调整 时 分 秒
														if(timeset==1)
														{
															if(time[2]==0)
															time[2]=23;
															else {time[2]--;}
															
															Ds1302_Init();
														}

														else if(timeset==2)
														{
														if(time[1]==0)
															time[1]=59;
														else {time[1]--;}
														
														 Ds1302_Init();//if else 之后的语句都进行初始化
														}

														else if(timeset==3)
														{
															if(time[0]==0)
															time[0]=59;
														  else {time[0]--;}
															
															Ds1302_Init();
														
														}
                     //调整闹钟 时 分 秒 
														else if(clockset==1)
														{
															if(alarm[2]==0)
															alarm[2]=23;														
                              else {alarm[2]--;}
														}

														else if(clockset==2)
														{
														 if(alarm[1]==0)
															alarm[1]=59;	
														else {alarm[1]--;}
                            }
														else if(clockset==3)
	                         {
														 if(alarm[0]==0)
															alarm[0]=59;	
														 else{alarm[0]--;}		
                            }

												}
												else if(led_show==1)
												{	
												led_show=0;
												P2=0X80;
												P0=0XFF;
												}
							
							}
			}
		

void Timer0Init(void)		//5毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xA0;		//设置定时初值
	TH0 = 0x15;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
}
void Timer0(void) interrupt 1
{
	tt++;
	count++;
	if(count==1000)
	{
	count=0;
	EA=0;
	ET0=0;//5s后关闭中断
	led_show=0;//标志位置0	
	P2=0X80;
	P0=0XFF;//关闭led 避免及时到最后是点亮的情况		
	}
	
	if((tt==40)&&(led_show==1))//led闪烁
	{
		tt=0;
		if(led==0)
		{
			P2=0X80;
			P0=0XFF;
			led=1;
		}
		else if(led==1)
		{
		P2=0X80;
		P0=0XFE;
		led=0;
		}
			
	}
	
}



void allinit()
{
	P2=0X80;
	P0=0XFF;
	
	P2=0XC0;
	P0=0XFF;
	P2=0XE0;
	P0=0XFF;
	
	P2=0XA0;
	P0=0X00;
}
void Delay1ms(uint ms)		//@12.000MHz
{
	uint k;
	unsigned char i, j;
	for(k=ms;k>0;k--)
	{
				i = 12;
				j = 169;
				do
				{
					while (--j);
				} while (--i);
				
	}
}


void display1(uchar yi,uchar er)
{
	P2=0XC0;
	P0=0X01;
	P2=0XE0;
	P0=tab[yi];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X02;
	P2=0XE0;
	P0=tab[er];
	Delay1ms(1);

}

void display2(uchar san,uchar si)
{
	P2=0XC0;
	P0=0X04;
	P2=0XE0;
	P0=tab[san];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X08;
	P2=0XE0;
	P0=tab[si];
	Delay1ms(1);
}
void display3(uchar wu,uchar liu)
{
	P2=0XC0;
	P0=0X10;
	P2=0XE0;
	P0=tab[wu];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X20;
	P2=0XE0;
	P0=tab[liu];
	Delay1ms(1);

}

void display4(uchar qi,uchar ba)
{
	P2=0XC0;
	P0=0X40;
	P2=0XE0;
	P0=tab[qi];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X80;
	P2=0XE0;
	P0=tab[ba];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0XFF;
	P2=0XE0;
	P0=0XFF;//关闭所有数码管使其亮度一致
}


onewire

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台
  日    期: 2011-8-9
*/

#include "onewire.h"

//单总线延时函数
void Delay_OneWire(unsigned int t)
{
	t=12*t;
  while(t--);
}

//DS18B20芯片初始化
bit Init_DS18B20(void)
{
	bit initflag = 0;
	DQ = 1;
	Delay_OneWire(12);
	DQ = 0;
	Delay_OneWire(80); 
	DQ = 1;
	Delay_OneWire(10); 
	initflag = DQ;    
	Delay_OneWire(5);
  
	return initflag;
}

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

//温度获取函数
unsigned char temget(void)
{
	unsigned char low,high;
	unsigned char temp;
  Init_DS18B20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay_OneWire(200);
	
  Init_DS18B20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
  low=Read_DS18B20();
	high=Read_DS18B20();
	temp=(low>>4)|(high<<4);
	return temp;
	
}


#ifndef _ONEWIRE_H
#define _ONEWIRE_H

#include 

#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe

//IC引脚定义
sbit DQ = P1^4;

//函数声明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);

unsigned char temget(void);

#endif

ds1302

#include "ds1302.h"
unsigned char time[]={50,59,23,0,0,0,0};
/********************************************************************/ 
/*单字节写入一字节数据*/
void Write_Ds1302_Byte(unsigned char dat) 
{
	unsigned char i;
	SCK = 0;
	for (i=0;i<8;i++) 
	{ 
		if (dat & 0x01) 	// 等价于if((addr & 0x01) ==1) 
		{
			SDA_SET;		//#define SDA_SET SDA=1 /*电平置高*/
		}
		else 
		{
			SDA_CLR;		//#define SDA_CLR SDA=0 /*电平置低*/
		}		 
		SCK_SET;
		SCK_CLR;		
		dat = dat >> 1; 
	} 
}
/********************************************************************/ 
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void) 
{
	unsigned char i, dat=0;	
	for (i=0;i<8;i++)
	{	
		dat = dat >> 1;
		if (SDA_R) 	  //等价于if(SDA_R==1)    #define SDA_R SDA /*电平读取*/	
		{
			dat |= 0x80;
		}
		else 
		{
			dat &= 0x7F;
		}
		SCK_SET;
		SCK_CLR;
	}
	return dat;
}

/********************************************************************/ 
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{ 

	RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
	SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

	RST_SET;			/*启动DS1302总线,RST=1电平置高 */
	addr = addr & 0xFE;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/	
	
	Write_Ds1302_Byte((dat/10<<4)|(dat%10));	 /*写入数据:dat*/
	RST_CLR;				 /*停止DS1302总线*/

}

/********************************************************************/ 
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp;
	unsigned char dat1,dat2;
	RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
	SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

	RST_SET;	/*启动DS1302总线,RST=1电平置高 */	
	addr = addr | 0x01;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
	temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/		
	RST_CLR;	/*停止DS1302总线*/
	
	dat1=temp/16;
	dat2=temp%16;
	temp=temp=dat1*10+dat2;
	
	//	RST_CLR;	/*读取完一个字节必须停止DS1302总线,否则出错*/
	//	SDA_CLR;
	SD=0;	//(即 使IO口P2^3=0)
	return temp;
}



void Ds1302_Init(void)
{
	unsigned char i,add;
	add=0x80;
	Ds1302_Single_Byte_Write(0x8e,0x00);
	for(i=0;i<7;i++)
	{
	Ds1302_Single_Byte_Write(add,time[i]);
	add+=2;
	}
	Ds1302_Single_Byte_Write(0x8e,0x80);
	
}

void Ds1302_TimeGet(void)
{
	unsigned char i,add;
	add=0x81;
	Ds1302_Single_Byte_Write(0x8e,0x00);
	for(i=0;i<7;i++)
	{
	time[i]=Ds1302_Single_Byte_Read(add);
	add+=2;
	}
	Ds1302_Single_Byte_Write(0x8e,0x80);
}	




#ifndef  __DS1302_H__
#define  __DS1302_H__

#include
#include
/********************************************************************/ 
sbit SCK=P1^7;		
sbit SD=P2^3;		
sbit RST=P1^3;
/********************************************************************/ 
/*复位脚*/
#define RST_CLR	RST=0	/*电平置低*/
#define RST_SET	RST=1	/*电平置高*/
/*双向数据*/
#define SDA_CLR	SD=0	/*电平置低*/
#define SDA_SET	SD=1	/*电平置高*/
#define SDA_R	SD	/*电平读取*/	
/*时钟信号*/
#define SCK_CLR	SCK=0	/*时钟信号*/
#define SCK_SET	SCK=1	/*电平置高*/
/********************************************************************/ 
#define ds1302_sec_addr			0x80		//秒数据地址
#define ds1302_min_addr			0x82		//分数据地址
#define ds1302_hr_addr			0x84		//时数据地址
#define ds1302_date_addr		0x86		//日数据地址
#define ds1302_month_addr		0x88		//月数据地址
#define ds1302_day_addr			0x8A		//星期数据地址
#define ds1302_year_addr		0x8C		//年数据地址

#define ds1302_control_addr		0x8Ee		//写保护命令字单元地址
#define ds1302_charger_addr		0x90 		//涓电流充电命令字地址			 
#define ds1302_clkburst_addr	0xBE		//日历、时钟突发模式命令字地址
/********************************************************************/ 

/********************************************************************/ 
/*单字节写入一字节数据*/
extern void Write_Ds1302_Byte(unsigned char dat);
/********************************************************************/ 
/*单字节读出一字节数据*/
extern unsigned char Read_Ds1302_Byte(void);
  
/********************************************************************/ 
/********************************************************************/ 
/*向DS1302单字节写入一字节数据*/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/ 
/*从DS1302单字节读出一字节数据*/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);


extern unsigned char time[];
extern void Ds1302_Init(void);
extern void Ds1302_TimeGet(void);

#endif	 
/********************************************************************/
//		     	END FILE
/********************************************************************/

你可能感兴趣的:(蓝桥杯)