蓝桥杯第八届省赛试题--“电子时钟”

题目要求

一、 基本要求
1.1 使用 CT107D 单片机竞赛板,完成“电子钟”功能的程序设计与调试;
1.2 设计与调试过程中,可参考组委会提供的“资源数据包” ;
1.3 Keil 工程文件以准考证号命名,完成设计后,提交完整、可编译的 Keil
工程文件到服务器。
二、 硬件框图
蓝桥杯第八届省赛试题--“电子时钟”_第1张图片
三、 功能描述
3.1 初始化
1)关闭蜂鸣器、继电器等无关外设;
2)设备初始化时钟为 23 时 59 分 50 秒,闹钟提醒时间 0 时 0 分 0 秒。
3.2 显示功能
蓝桥杯第八届省赛试题--“电子时钟”_第2张图片
3.3 按键功能
1)按键 S7 定义为“时钟设置”按键,通过该按键可切换选择待调整的
时、分、秒,当前选择的显示单元以 1 秒为间隔亮灭,时、分、秒
的调整需注意数据边界属性。
蓝桥杯第八届省赛试题--“电子时钟”_第3张图片
2) 按键 S6 定义为“闹钟设置”按键,通过该按键可进入闹钟时间设置
功能,数码管显示当前设定的闹钟时间。
蓝桥杯第八届省赛试题--“电子时钟”_第4张图片
3) 按键 S5 定义为“加” 按键, 在“时钟设置” 或“闹钟设置” 状态下,每次按下该按键当前选择的单元(时、分或秒)增加 1 个单位。
4) 按键 S4 定义为“减” 按键, 在“时钟设置” 或“闹钟设置” 状态下,每次按下该按键当前选择的单元(时、分或秒)减少 1 个单位。
5) 按键功能说明:
按键 S4、 S5 的“加” 、 “减”功能只在“时钟设置”或“闹钟设置”状态下有效;
在 “时钟显示”状态下,按下 S4按键,显示温度数据,松开按键,返回“时钟显示”界面。
3.4 闹钟提示功能
1)指示灯 L1 以 0.2 秒为间隔闪烁,持续 5 秒钟;
2)闹钟提示状态下,按下任意按键,关闭闪烁提示功能。

程序代码

主函数

#include"stc15f2k60s2.h"
#include "ds1302.h"
#include "onewire.h"

typedef unsigned char uchar;
typedef unsigned int uint;

uchar code SMG_duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
uchar code SMG_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

uchar time_display[8];					 //时间显示
uchar temp_display[8];					 //温度显示
uchar set_display[8];					 //时间设置显示
uchar clock_display[8];					 //闹钟设置显示

uchar clock_shi=0,clock_fen=0,clock_miao=0;					 //闹钟时间
uchar shi,fen,miao;
uchar clock_mode=0;						 //闹钟调整模式
uchar mode=0;							//时间调整模式
uchar mode_display=0;		  // 0 时间显示,1  时间设置  2 温度显示   3  闹钟设置
bit clock_flag;

uchar set_blink;
uchar led_blink=0;


uchar temperature;

uchar Key_init();
void Timer0Init();		//1毫秒@11.0592MHz



void main()
{
   uchar key_val;
   P2=0XA0;P0=0X00;
   P2=0X80;P0=0XFF;

   Timer0Init();
   DS1302();		
   time_display[2]=0X40; time_display[5]=0X40;

   set_display[2]=0X40; set_display[5]=0X40;
   clock_display[2]=0x40; clock_display[5]=0x40;

   temp_display[0]=0x00; temp_display[1]=0x00; 
   temp_display[2]=0x00; temp_display[3]=0x00;
   temp_display[4]=0x00; temp_display[7]=0x39;
   while(1)
   {
      ET0=0;						//不关闭中断,时间显示会有种卡顿感
      Read_time();
	  ET0=1;
	  if(mode_display==0)				//时间
	  {
	    time_display[0]=SMG_duan[TIME[2]/16];	time_display[1]=SMG_duan[TIME[2]%16];
	    time_display[3]=SMG_duan[TIME[1]/16];	time_display[4]=SMG_duan[TIME[1]%16];	  
	    time_display[6]=SMG_duan[TIME[0]/16];   time_display[7]=SMG_duan[TIME[0]%16];
	  }

	  if(mode_display==3)					   //闹钟
	   {
	    if(set_blink)
		{
		  if(clock_mode==1)										//时
		  {		    			
	        clock_display[0]=SMG_duan[clock_shi/10];
		    clock_display[1]=SMG_duan[clock_shi%10];	  			   
		  }	
		  if(clock_mode==2)									 //分
		  {		    
	         clock_display[3]=SMG_duan[clock_fen/10];	
			 clock_display[4]=SMG_duan[clock_fen%10];		
		  }
		  if(clock_mode==3)								   //秒
		  {	 		     
	        clock_display[6]=SMG_duan[clock_miao/10];    
			clock_display[7]=SMG_duan[clock_miao%10];	 
		  }
		}
		else
		{
		  if(clock_mode==1)
		  {
			clock_display[0]=0x00;	
		    clock_display[1]=0x00;
		  }
		  else
		  {
			clock_display[0]=SMG_duan[clock_shi/10];
		    clock_display[1]=SMG_duan[clock_shi%10];
		  }

		  if(clock_mode==2)
		  {
			clock_display[3]=0x00;
		    clock_display[4]=0x00;
		  }
		  else
		  {
			clock_display[3]=SMG_duan[clock_fen/10];	
			clock_display[4]=SMG_duan[clock_fen%10];	
		  }

		  if(clock_mode==3)
		  {	 
			 clock_display[6]=0x00;    
		     clock_display[7]=0x00;
		  }
		  else
		  {
			clock_display[6]=SMG_duan[clock_miao/10];    
			clock_display[7]=SMG_duan[clock_miao%10];
		  }
		}
	  }
	  if((TIME[0]==clock_miao)&&(TIME[1]==clock_fen)&&(TIME[2]==clock_shi))
	  {
	    if(mode_display==0)
	    clock_flag=1;	
	  }

	  temperature=temp_get();
	  temp_display[5]=SMG_duan[temperature%100/10];
	  temp_display[6]=SMG_duan[temperature%10];

	   key_val=Key_init();
	   if(mode_display==0)								 
	   {
	     if(clock_flag)							   //闹钟提示状态下,按下任意键关闭提示功能
	     { 		   
	       if(key_val)
		   clock_flag=0;		  
	     }
	   }
	   switch(key_val)
	   {
		 case 4:		       
			   if(mode_display==3)				  //闹钟设置
			   {
			     if(clock_mode==1)
			     {				   				   				   
				   if(clock_shi>0)
				   clock_shi--;			
			     }
				 if(clock_mode==2)
			     {				   				   				   
				   if(clock_fen>0)
				   clock_fen--;
			     }
				 if(clock_mode==3)
			     {				   				   				   
				   if(clock_miao>0)
				   clock_miao--;				   
			     }
			   }
			   if(mode_display==1)				  //时间设置
			   {
			     if(mode==1)
			     {				   				   				   
				   if(shi>0)
				   shi--;			
			     }
				 if(mode==2)
			     {				   				   				   
				   if(fen>0)
				   fen--;
			     }
				 if(mode==3)
			     {				   				   				   
				   if(miao>0)
				   miao--;				   
			     }
			   }  	
			   break;
		 case 5:		      
		       if(mode_display==1)
			   {
			     if(mode==1)
			     {				   				   
				   shi++;
				   if(shi==24)
				   shi=0;			
			     }
				 if(mode==2)
			     {				   				   
				   fen++;
				   if(fen==60)
				   fen=0;
			     }
				 if(mode==3)
			     {				   				   
				   miao++;
				   if(miao==60)
				   miao=0;				   
			     }
			   }

			   if(mode_display==3)
			   {
			     if(clock_mode==1)
			     {				   				   
				   clock_shi++;
				   if(clock_shi==24)
				   clock_shi=0;			
			     }
				 if(clock_mode==2)
			     {				   				   
				   clock_fen++;
				   if(clock_fen==60)
				   clock_fen=0;
			     }
				 if(clock_mode==3)
			     {				   				   
				   clock_miao++;
				   if(clock_miao==60)
				   clock_miao=0;				   
			     }
			   }
			   break;
		 case 6:		       
			   if(mode_display==0)
			   {
				  mode_display=3;					//进入时间设置界面
			   }
			   if(mode_display==3)
			   {
				  clock_mode++;
				  if(clock_mode==4)
				  {
				    clock_mode=0;
					mode_display=0;
				  }
			   }
			   break;
		 case 7:		       		     		   
			   if(mode_display==0)
			   {
				  mode_display=1;					//进入时间设置界面
			   }
			   if(mode_display==1)
			   {
			     if(mode==0)
				 {
				 	shi=(TIME[2]/16)*10+TIME[2]%16;
					fen=(TIME[1]/16)*10+TIME[1]%16;
					miao=(TIME[0]/16)*10+TIME[0]%16;
					set_display[0]=SMG_duan[shi/10];	
		            set_display[1]=SMG_duan[shi%10];
					set_display[3]=SMG_duan[fen/10];
		            set_display[4]=SMG_duan[fen%10];
					set_display[6]=SMG_duan[miao/10];    
		            set_display[7]=SMG_duan[miao%10];
				 }	
				 mode++;
				 if(mode==4)
				 {
			       mode=0;
				   mode_display=0;					   //返回时间显示界面
				   
				   TIME[2]=(shi/10)*16+shi%10;					//十进制再转成十六进制
				   TIME[1]=(fen/10)*16+fen%10;
				   TIME[0]=(miao/10)*16+miao%10;
				   DS1302();									//重新写入时间
				 }			     
			   }
			   break;
	   }
	   if(mode_display==1)
	   {
	    if(set_blink)
		{
		  if(mode==1)										//时
		  {		    			
	        set_display[0]=SMG_duan[shi/10];	
		    set_display[1]=SMG_duan[shi%10];	  			   
		  }	
		  if(mode==2)									 //分
		  {		    
	         set_display[3]=SMG_duan[fen/10];
		     set_display[4]=SMG_duan[fen%10];		
		  }
		  if(mode==3)								   //秒
		  {	 		     
	        set_display[6]=SMG_duan[miao/10];    
		    set_display[7]=SMG_duan[miao%10];	 
		  }
		}
		else
		{
		  if(mode==1)
		  {
			set_display[0]=0x00;	
		    set_display[1]=0x00;
		  }
		  else
		  {
			set_display[0]=SMG_duan[shi/10];	
		    set_display[1]=SMG_duan[shi%10];
		  }
		  if(mode==2)
		  {
			set_display[3]=0x00;
		    set_display[4]=0x00;
		  }
		  else
		  {
			set_display[3]=SMG_duan[fen/10];
		    set_display[4]=SMG_duan[fen%10];	
		  }
		  if(mode==3)
		  {	 
			 set_display[6]=0x00;    
		     set_display[7]=0x00;
		  }
		  else
		  {
			set_display[6]=SMG_duan[miao/10];    
		    set_display[7]=SMG_duan[miao%10];
		  }
		}
	  }
   }
}
#define KEY P3
#define key_state0 0
#define key_state1 1
#define key_state2 2

uchar Key_init()
{
   static uchar key_state=0;							  //要定义成静态变量
   uchar key_press,key_return=0;
   key_press=KEY&0X0F;
   switch(key_state)
   {
	 case key_state0:
	      if(key_press!=0x0f)
		  key_state=key_state1;
		  break;
	 case key_state1:
	      if(key_press!=0x0f)
		  {
			 if(key_press==0x0e)  	key_return=7;
			 if(key_press==0x0d)  	key_return=6;
			 if(key_press==0x0b)  	key_return=5;
			 if(key_press==0x07)
			 { 
			   if(mode_display==0)
			   mode_display=2; 	
			   key_return=4;
			 }
		     key_state=key_state2;
		  }
		  else
          key_state=key_state0;
		  break;
	 case key_state2:								 //判断按键是否松开
	      if(key_press==0x0f)
		  {
		   key_state=key_state0;
		   if(mode_display==2)
		   {
		     mode_display=0;
		   }
		  }
		  break;
   }
   return  key_return;
}

void Timer0Init()		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;
	ET0=1;
}

void Timer0() interrupt 1
{
   uchar i;
   static uint SMG_count=0,led_count=0,blink_count=0,set_count=0;
   SMG_count++;	  set_count++;
 
   if(SMG_count==3)
   {
	 SMG_count=0;
	 P2=0XC0;P0=0X00;
	 P2=0XC0;P0=SMG_wei[i];
	 if(mode_display==0)						 //时间显示
	 {
	   P2=0XE0;P0=~time_display[i];
	 }
	 if(mode_display==1)					   //时间设置显示
	 {
	   P2=0XE0;P0=~set_display[i];
	 }
	 if(mode_display==2)					 //温度显示
	 {
	   P2=0XE0;P0=~temp_display[i];
	 }
	 if(mode_display==3)					 //闹钟设置显示
	 {
	   P2=0XE0;P0=~clock_display[i];
	 }
	 i++;
	 if(i==8)
	 i=0;
   }
   if(clock_flag)
   {
     led_count++;
     if(led_count>200)
     {
	  led_count=0;
	  led_blink++;
	  if(led_blink==2)
	  led_blink=0;
	  blink_count++;							//200ms加一次
	 } 
     if(led_blink)
	 {
	   P2=0X80;P0=0xfe;
	 }
	 else
	 {
	   P2=0X80;P0=0xff;
	 }
	 if(blink_count>25)		//如果5s时。led恰巧亮着,那么它就不会熄灭,所以要大于
     {
	   blink_count=0;
       clock_flag=0;
	   
     }   
   }  
   if(set_count==1000)
   {
	 set_count=0;
	 set_blink++;
	 if(set_blink==2)
	 set_blink=0;
   }   
}

DS1302时钟模块

#include "ds1302.h"

unsigned char code Write_addr[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char code Read_addr[]={0x81,0x83,0x85,0x87,0x89,0x8ab,0x8d};

unsigned char TIME[]={0X50,0X59,0X23};
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);	 /*写入数据:dat*/
	RST_CLR;				 /*停止DS1302总线*/
}

/********************************************************************/ 
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp;
	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总线*/
	_nop_();
	SD=0;
	_nop_();
	SD=1;
	_nop_();

	return temp;
}

void DS1302()
{
   int i;
   Ds1302_Single_Byte_Write(0x8e,0x00);		//0x8e为写地址,WP=0,允许写操作
   for(i=0;i<3;i++)
   {
	  Ds1302_Single_Byte_Write(Write_addr[i],TIME[i]);
   }
   Ds1302_Single_Byte_Write(0x8e,0x80);	   //WP=1,禁止写操作
}

void Read_time()
{
   int i;
   for(i=0;i<3;i++)
   {
	  TIME[i]=Ds1302_Single_Byte_Read(Read_addr[i]);
   }
}

DS18B20温度传感器模块

#include "onewire.h"

//单总线延时函数
void Delay_OneWire(unsigned int t)
{
  while(t--);
}
void Delay500us();		//@11.0592MHz
void Delay100us();		//@11.0592MHz
void Delay60us();		//@11.0592MHz
void Delay15us();		//@11.0592MHz

void delayms(unsigned char ms)
{
  int i,j;
  for(i=0;i<ms;i++)
    for(j=850;j>0;j--);
}
bit Init_DS18B20(void)
{
	bit initflag = 0;
	DQ = 1;
	Delay_OneWire(12);
	DQ = 0;
	Delay500us(); 
	DQ = 1;
	Delay15us(); 
	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;
		Delay60us();
		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;
		}	    
		Delay100us();	
	}
	return dat;
}

void DS18B20()
{
   Init_DS18B20();
   delayms(1);
   Write_DS18B20(0xcc);
   Write_DS18B20(0x44);

   Init_DS18B20();
   delayms(1);
   Write_DS18B20(0xcc);
   Write_DS18B20(0xbe);
}

int temp_get()
{
   int low,high;
   int temp;

   DS18B20();
   low=Read_DS18B20();
   high=Read_DS18B20();

   temp=high<<4;
   temp|=low>>4;

   return temp;
}
void Delay500us()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 6;
	j = 93;
	do
	{
		while (--j);
	} while (--i);
}
void Delay100us()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 2;
	j = 15;
	do
	{
		while (--j);
	} while (--i);
}

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

	i = 1;
	j = 162;
	do
	{
		while (--j);
	} while (--i);
}

void Delay15us()		//@11.0592MHz
{
	unsigned char i;

	i = 39;
	while (--i);
}

以上就是代码全部内容,欢迎交流,共同学习~

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