[蓝桥杯国赛]练手第八届省赛题目

题目为基于单片机的电子钟程序设计与调试

分析

程序如何宏观规划(十分重要)

特点:切换界面多
方法:多个界面时用一个变量display_mode来管理,按键按下后对display_mode赋值,在while(1)每2ms程序里写if(display_mode==…)来完成功能

按键调整RTC时间

思路:
按键后,记录当前RTC的值,即时分秒,根据其他按键操作,对记录下的变量操作,最后再对RTC赋值set_sfm就可以
Tip:
①涉及到操作RTC的hour min sec最好将要操作的转换为10进制,16进制不能++操作
②出现了按键不起作用,是因为++save_shi,但是每次save_shi会被shi赋值,所以按键无效。要通过按键改变输出值,则输出更改输入固定的变量,不然总是被赋新值,按键操作不起作用了
③RTC不能直接放在WHLIE1里 更新太快不可以,每2或者3ms更新一次即可,不然不会更新数据
④RTC:如果跳动,或1s跳两下说明中断干扰了

松开按键检测

状态机消抖的KEY_STATE_2状态下就可以检测是否松开

//根据是否松开来决定是否切换界面
		case KEY_STATE_2:
			if(key_temp==NO_KEY)
			{
				if(display_mode==3)display_mode=0;
				key_state=KEY_STATE_0;
			}
			break;

闹钟提示功能关闭实现

①5s自动关闭
当闪烁的时候有一个标志,定时5s结束闪烁的方法:
闪烁标志开始时,5s定时也开始了,如果5s到了闪烁标志被清掉
②按键手动关闭(闹钟提示状态下,按下任意按键,关闭闪烁提示功能)

case KEY_STATE_1:
			if(key_temp == NO_KEY)
			{
				key_state=KEY_STATE_0;
			}
			else
			{
				if(alarm_led_flag==1)
				{
					key_delete_alarm=1;
				}
				switch(key_temp)
				{
					.....
					....
				}

灯闪烁实现

比如0.2s标志bit切换,一个功能亮,一个功能灭

			if(alarm_led_flag==1 && key_delete_alarm==0)
			{
				if(delay_200ms_flag_flag==0)
				{P2=0x80;P0=0xfe;P2=0x00;}//亮
				else
				{P2=0x80;P0=0xff;P2=0x00;}//灭
			}

待调整位闪烁

定义了一个set_clock_number,这个是按键按一次加一,切换到下一调整位,在不同调整位闪烁相应位置的数码管,按set_clock_number切换到4时,就切换到初始显示模式(这是本题的要求)

if(display_mode==2)	//闹钟设置界面
			{	
				alarm_display_menu[0]=smg_duan[alarm_shi/10];alarm_display_menu[1]=smg_duan[alarm_shi%10];
				alarm_display_menu[3]=smg_duan[alarm_fen/10];alarm_display_menu[4]=smg_duan[alarm_fen%10];
				alarm_display_menu[6]=smg_duan[alarm_miao/10];alarm_display_menu[7]=smg_duan[alarm_miao%10];
				
				if(set_clock_number==1)
				{

					if(blink_1s_flag==0)		//1s闪烁
					{
						alarm_display_menu[0]=smg_duan[alarm_shi/10];alarm_display_menu[1]=smg_duan[alarm_shi%10];
					}
					else
					{
						alarm_display_menu[0]=0x00;alarm_display_menu[1]=0x00;
					}
				}
				if(set_clock_number==2)
				{

					if(blink_1s_flag==0)		//1s闪烁
					{
						alarm_display_menu[3]=smg_duan[alarm_fen/10];alarm_display_menu[4]=smg_duan[alarm_fen%10];
					}
					else
					{
						alarm_display_menu[3]=0x00;alarm_display_menu[4]=0x00;
					}
				}
				if(set_clock_number==3)
				{

					if(blink_1s_flag==0)		//1s闪烁
					{
						alarm_display_menu[6]=smg_duan[alarm_miao/10];alarm_display_menu[7]=smg_duan[alarm_miao%10];						
					}
					else
					{
						alarm_display_menu[6]=0x00;alarm_display_menu[7]=0x00;						
					}
				}
				if(set_clock_number==4)//恢复
				{
					display_mode=0;
					set_clock_number=0;
				}
			}

代码

晚上熬夜写的,可能可读性不强


#include "STC15F2K60S2.h"
#include "ds1302.h"
#include "onewire.h"

#define u8 unsigned char
#define u16 unsigned int
	
#define NO_KEY 0xff
#define KEY_STATE_0 0
#define KEY_STATE_1 1
#define KEY_STATE_2 2

u8 code smg_duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40,0x00};
u8 code smg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 display_menu[8]={0};
u8 set_clock_display_menu[8]={0};
u8 temperature_display_menu[8]={0};
u8 alarm_display_menu[8]={0};

sbit buzzer=P0^6;
sbit relay=P0^4;
sbit LED1=P0^0;

bit blink_1s_flag=0;
bit delay_200ms_flag_flag=0;
bit alarm_led_flag=0;

u8 temperature_val=0;
u8 circle_2ms_flag=0;

u8 shi,fen,miao;
u8 alarm_shi=0,alarm_fen=0,alarm_miao=0;
u8 save_shi,save_fen,save_miao;
u8 set_clock_number=0;

u8 key_val=0;

u8 display_mode=0;//0:时钟显示界面	1:时钟设置界面	2:闹钟设置界面	3:温度显示界面
u8 key_delete_alarm=0;//0:正常	1:取消功能






u8 Read_Key(void)
{
	static u8 key_state = KEY_STATE_0;
	u8 key1,key2,key_temp;
	u8 key_return=0;
	
	P30=0;P31=0;P32=0;P33=0;P34=1;P35=1;P42=1;P44=1;
	if(0==P34)key1=0xe0;
	if(0==P35)key1=0xd0;	//1101 0000
	if(0==P42)key1=0xb0;//1011
	if(0==P44)key1=0x70;
	if( 1==P34 && 1==P35 && 1==P42 && 1==P44)key1=0xf0;
	
	P30=1;P31=1;P32=1;P33=1;P34=0;P35=0;P42=0;P44=0;
	if(0==P30)key2=0x0e;
	if(0==P31)key2=0x0d;	//1101 0000
	if(0==P32)key2=0x0b;//1011
	if(0==P33)key2=0x07;
	if( 1==P30 && 1==P31 && 1==P32 && 1==P33)key2=0x0f;
	
	key_temp=key1|key2;
	
	switch(key_state)
	{
		case KEY_STATE_0:
			if(key_temp != NO_KEY)
			{
				key_state=KEY_STATE_1;
			}
			break;
		case KEY_STATE_1:
			if(key_temp == NO_KEY)
			{
				key_state=KEY_STATE_0;
			}
			else
			{
				if(alarm_led_flag==1)
				{
					key_delete_alarm=1;
				}
				switch(key_temp)
				{
					case 0x77:key_return=4;break;
					case 0x7b:key_return=5;break;
					case 0x7d:key_return=6;break;
					case 0x7e:key_return=7;break;
					case 0xb7:key_return=8;break;
					case 0xbb:key_return=9;break;
					case 0xbd:key_return=10;break;
					case 0xbe:key_return=11;break;
					case 0xd7:key_return=12;break;
					case 0xdb:key_return=13;break;
					case 0xdd:key_return=14;break;
					case 0xde:key_return=15;break;
					case 0xe7:key_return=16;break;
					case 0xeb:key_return=17;break;
					case 0xed:key_return=18;break;
					case 0xee:key_return=19;break;
				}
				key_state=KEY_STATE_2;
			}
			break;
		case KEY_STATE_2:
			if(key_temp==NO_KEY)
			{
				if(display_mode==3)display_mode=0;
				key_state=KEY_STATE_0;
			}
			break;
	}
	return key_return;
}


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

//---------------------------------------------------------------------
//---------------------------------------------------------------------
//---------------------------------------------------------------------
//---------------------------------------------------------------------
//---------------------------------------------------------------------




void main(void)
{
	Timer0Init();
	P2=0xa0;buzzer=0;relay=0;P2=0x00;
	set_sfm(23,59,58);
	
	display_menu[2]=0x40;
	display_menu[5]=0x40;
	set_clock_display_menu[2]=0x40;
	set_clock_display_menu[5]=0x40;
	alarm_display_menu[2]=0x40;
	alarm_display_menu[5]=0x40;
	while(1)
	{
		if(circle_2ms_flag==1)
		{
			circle_2ms_flag=0;

			///
			if(display_mode==0)	//时钟显示界面
			{
				EA=0;
				shi=Read_Ds1302(0x85);
				fen=Read_Ds1302(0x83);
				miao=Read_Ds1302(0x81);
				shi=(shi/16)*10+shi%16;
				fen=(fen/16)*10+fen%16;
				miao=(miao/16)*10+miao%16;
				EA=1;
				display_menu[0]=smg_duan[shi/10];display_menu[1]=smg_duan[shi%10];
				display_menu[3]=smg_duan[fen/10];display_menu[4]=smg_duan[fen%10];
				display_menu[6]=smg_duan[miao/10];display_menu[7]=smg_duan[miao%10];
			}
			
			/
			if(display_mode==1)	//时钟设置界面
			{
				save_shi=shi;												//巨坑,最好shi,fen,miao自己使用的都转换为10进制,因为16进制++会有问题
				save_fen=fen;
				save_miao=miao;
				set_clock_display_menu[0]=smg_duan[save_shi/10];set_clock_display_menu[1]=smg_duan[save_shi%10];
				set_clock_display_menu[3]=smg_duan[save_fen/10];set_clock_display_menu[4]=smg_duan[save_fen%10];
				set_clock_display_menu[6]=smg_duan[save_miao/10];set_clock_display_menu[7]=smg_duan[save_miao%10];
				if(set_clock_number==1)
				{

					if(blink_1s_flag==0)		//1s闪烁
					{
						set_clock_display_menu[0]=smg_duan[save_shi/10];set_clock_display_menu[1]=smg_duan[save_shi%10];
					}
					else
					{
						set_clock_display_menu[0]=0x00;set_clock_display_menu[1]=0x00;
					}
				}
				if(set_clock_number==2)
				{

					if(blink_1s_flag==0)		//1s闪烁
					{
						set_clock_display_menu[3]=smg_duan[save_fen/10];set_clock_display_menu[4]=smg_duan[save_fen%10];
					}
					else
					{
						set_clock_display_menu[3]=0x00;set_clock_display_menu[4]=0x00;
					}
				}
				if(set_clock_number==3)
				{

					if(blink_1s_flag==0)		//1s闪烁
					{
						set_clock_display_menu[6]=smg_duan[save_miao/10];set_clock_display_menu[7]=smg_duan[save_miao%10];						
					}
					else
					{
						set_clock_display_menu[6]=0x00;set_clock_display_menu[7]=0x00;						
					}
				}
				if(set_clock_number==4)//恢复
				{
					display_mode=0;
					set_clock_number=0;
//					set_sfm(((save_shi/16)*10+save_shi%16),((save_fen/16)*10+save_fen%16),((save_miao/16)*10+save_miao%16));	//这里被困扰了好久

					set_sfm(save_shi,save_fen,save_miao);
				}
			}
			
			/
			if(display_mode==3)	//温度显示界面
			{
				temperature_val = rd_temperature_f();
				temperature_display_menu[5]=smg_duan[temperature_val/10];
				temperature_display_menu[6]=smg_duan[temperature_val%10];
				temperature_display_menu[7]=0x39;
			}
			
			if(display_mode==2)	//闹钟设置界面
			{	
				alarm_display_menu[0]=smg_duan[alarm_shi/10];alarm_display_menu[1]=smg_duan[alarm_shi%10];
				alarm_display_menu[3]=smg_duan[alarm_fen/10];alarm_display_menu[4]=smg_duan[alarm_fen%10];
				alarm_display_menu[6]=smg_duan[alarm_miao/10];alarm_display_menu[7]=smg_duan[alarm_miao%10];
				
				if(set_clock_number==1)
				{

					if(blink_1s_flag==0)		//1s闪烁
					{
						alarm_display_menu[0]=smg_duan[alarm_shi/10];alarm_display_menu[1]=smg_duan[alarm_shi%10];
					}
					else
					{
						alarm_display_menu[0]=0x00;alarm_display_menu[1]=0x00;
					}
				}
				if(set_clock_number==2)
				{

					if(blink_1s_flag==0)		//1s闪烁
					{
						alarm_display_menu[3]=smg_duan[alarm_fen/10];alarm_display_menu[4]=smg_duan[alarm_fen%10];
					}
					else
					{
						alarm_display_menu[3]=0x00;alarm_display_menu[4]=0x00;
					}
				}
				if(set_clock_number==3)
				{

					if(blink_1s_flag==0)		//1s闪烁
					{
						alarm_display_menu[6]=smg_duan[alarm_miao/10];alarm_display_menu[7]=smg_duan[alarm_miao%10];						
					}
					else
					{
						alarm_display_menu[6]=0x00;alarm_display_menu[7]=0x00;						
					}
				}
				if(set_clock_number==4)//恢复
				{
					display_mode=0;
					set_clock_number=0;
				}
			}
			
			/
			if(alarm_shi==shi && alarm_fen==fen && alarm_miao==miao)
			{
				alarm_led_flag=1;
			}
			if(alarm_led_flag==1 && key_delete_alarm==0)
			{
				if(delay_200ms_flag_flag==0)
				{P2=0x80;P0=0xfe;P2=0x00;}//亮
				else
				{P2=0x80;P0=0xff;P2=0x00;}//灭
			}
			key_val=Read_Key();
			
			switch(key_val)
			{
				case 4:
					if(display_mode==0)
					{
						display_mode=3;
					}
					if(display_mode==1)
					{
						switch(set_clock_number)
						{
							case 1:
								if(shi>0)
								shi--;
								break;			//出现了按键不起作用,是因为++save_shi,每次save_shi会被shi赋值,所以按键无效
							case 2:
								if(fen>0)
								fen--;
								break;
							case 3:
								if(miao>0)
								miao--;
								break;
						}
					}
					if(display_mode==2)
					{
						switch(set_clock_number)
						{
							case 1:
								if(alarm_shi>0)
								alarm_shi--;
								break;			//出现了按键不起作用,是因为++save_shi,每次save_shi会被shi赋值,所以按键无效
							case 2:
								if(alarm_fen>0)
								alarm_fen--;
								break;
							case 3:
								if(alarm_miao>0)
								alarm_miao--;
								break;
						}
					}
					break;
				case 5:
					if(display_mode==1)
					{
						switch(set_clock_number)
						{
							case 1:
								if(shi<23)
								shi++;
								break;			//出现了按键不起作用,是因为++save_shi,每次save_shi会被shi赋值,所以按键无效
							case 2:
								if(fen<59)
								fen++;
								break;
							case 3:
								if(miao<59)
								miao++;
								break;
						}
					}
					if(display_mode==2)
					{
						switch(set_clock_number)
						{
							case 1:
								if(alarm_shi<23)
								alarm_shi++;
								break;			//出现了按键不起作用,是因为++save_shi,每次save_shi会被shi赋值,所以按键无效
							case 2:
								if(alarm_fen<59)
								alarm_fen++;
								break;
							case 3:
								if(alarm_miao<59)
								alarm_miao++;
								break;
						}
					}
					break;
				case 6:
					if(display_mode==0 || display_mode==2)
					{
						display_mode=2;
						set_clock_number++;;
					}
					break;
				case 7:
					display_mode=1;
					set_clock_number++;
				
					
					break;
				case 8:break;
				case 9:break;
				case 10:break;
				case 11:break;
				case 12:break;
				case 13:break;
				case 14:break;
				case 15:break;
				case 16:break;
				case 17:break;
				case 18:break;
				case 19:break;
			}

		}

	}
}


void tm0_isr() interrupt 1 using 1
{
	static int delay_10ms_flag_int=0,delay_2ms_flag_int=0,i=0,blink_1s_flag_int=0,delay_200ms_flag_int=0,delay_200ms_flag_count=0;
	delay_10ms_flag_int++;delay_2ms_flag_int++,blink_1s_flag_int++,delay_200ms_flag_int++;
	if(delay_10ms_flag_int==10)		
	{

		delay_10ms_flag_int=0;
	}
	if(delay_2ms_flag_int==2)
	{
		circle_2ms_flag=1;
		delay_2ms_flag_int=0;
		P2=0xc0;P0=0x00;P2=0x00;
		if(display_mode==0)P2=0xe0;P0=~display_menu[i];P2=0x00;
		if(display_mode==1)P2=0xe0;P0=~set_clock_display_menu[i];P2=0x00;
		if(display_mode==2)P2=0xe0;P0=~alarm_display_menu[i];P2=0x00;
		if(display_mode==3)P2=0xe0;P0=~temperature_display_menu[i];P2=0x00;
		P2=0xc0;P0=smg_wei[i];P2=0x00;
		i++;
		if(i==8)i=0;
	}
	if(blink_1s_flag_int==1000)//1s
	{
		blink_1s_flag_int=0;
		blink_1s_flag=~blink_1s_flag;
	}
	if(delay_200ms_flag_int==200)
	{
		delay_200ms_flag_int=0;
		delay_200ms_flag_flag=~delay_200ms_flag_flag;
	}
	if(alarm_led_flag==1)				//亮5s怎么写,我想了好久!!!! 
	{
		delay_200ms_flag_count++;//
		if(delay_200ms_flag_count==5000)
		{
			alarm_led_flag=0;
			delay_200ms_flag_count=0;
			{P2=0x80;P0=0xff;P2=0x00;}//灭

		}
	}


}

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