【蓝桥杯单片机国赛】长按和短按

  • Post author:
  • Post category:其他




【蓝桥杯单片机国赛】长按和短按



问题

第九届蓝桥杯单片机设计与开发项目决赛有这一部分:

“S7 :定义为参数”设置”按键,按下此按键,进入电压阈值参数设置界面(图6), 在阈值设置界面下,S6″回显”按键定义为阈值调整功能(备注:非阈值设置界面下,S6按键为回显功能),每次按下S6,电压阈值增加0.1V,长按0.8秒以上,可实现快速增加功能(备注:电压阈值设置范围:0.1V~5.0V),阈值调整完成后,再次按下S7按键,退出”设置”界面(图6),返回数据显示界面。”

如何利用定时器区分长按和短按?



解决思路

设置两类变量

1.检测当前状态变量 (如flag_key_1,count_t)

他们会随着按键的状态随时发生变化

2.记录当前状态变量 (如flag_key_2,time_dat)

用于记录第一种变化,便于后续的数据处理



例题

短按S7点亮L1,短按S7点亮L2,短按S6点亮L3,短按S6点亮L4

衡量长按短按的时间自拟

(硬件平台:北京国信长天科技CT107D 单片机综合实训平台)

按键处理函数:

void Scanf_Key()
{
  
	while(S7 == 0)	 	//flag_key_1是是否按下的标志位,如果按下就为1,没按下就为0
	{
		NixieTube_show();
		flag_key_1 = 1;	
	}
	
	while(S6 == 0)	 	
	{
		NixieTube_show();
		flag_key_1 = 2;	
	}
		
	if((S7 != 0)||(S6 != 0))
   	{
		flag_key_1 = 0;	
   	}		
}

定时器中断服务函数:

void Time_Ser()interrupt 3
{
	  TH1 = (65536-50000)/256;
      TL1 = (65536-50000)%256;
	  if(flag_key_1 != 0)	  //当按键按下时count才计数
	  {
		   count_t++;
		   time_dat = count_t;	   //记录完把值赋给time_dat
		   flag_key_2 = flag_key_1;	//把选择什么按键记录下来
	  }
	  else count_t = 0;
}

数据处理函数(此处是点亮LED):

void LED_Show()
{
	 switch(flag_key_2)
	 {
		 case 1:
				 if((time_dat <= 10)&&(time_dat >= 1))//(time_dat >= 1)也有消抖的作用  
				 {
				 	LED_dat = ~0x01;
				 }
				 else if(time_dat >= 10)
				 {
				 	LED_dat = ~0x02;
				 }
				 break;
		 case 2:
				 if((time_dat <= 10)&&(time_dat >= 1))  
				 {
				 	LED_dat = ~0x04;
				 }
				 else if(time_dat >= 10)
				 {
				 	LED_dat = ~0x08;
				 }
				 break;
	}	 
	XBYTE[0x8000] = LED_dat;
	flag_key_2 = 0;			   //处理完毕之后flag_key_2要清零

}



整体代码参考

#include <STC15F2K60S2.h>
#include "absacc.h"


unsigned char code NixieTube_date[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char LED_dat = 0xff;
	
sbit S7 = P3^0;
sbit S6 = P3^1;

unsigned int count_t = 0,time_dat= 0; 



void NixieTube_show();
void Delay(unsigned int t);


unsigned char flag_key_1 = 0,flag_key_2 = 0;

void NixieTube_Byte_show(unsigned char pos,unsigned char value)
{
	XBYTE[0xc000] = 0x00;
	XBYTE[0xe000] = value;
	XBYTE[0xc000] = (0x01<<pos);
}


void Delay(unsigned int t)
{
	while(t--);
}


		 
void System_init()
{
   XBYTE[0x8000] = 0xff;
   XBYTE[0xa000] = 0x00;

}



void Time_Init() //定时器1初始化
{
	TMOD = 0x10;
	TH1 = (65536-50000)/256;
	TL1 = (65536-50000)%256;
	TR1 = 1;
	ET1 = 1;
	EA = 1;
		
}

/*================================
这里的变量有2类
1.检测当前状态变量 (如flag_key_1,count_t)
	他们会随着按键的状态随时发生变化
2.记录当前状态变量 (如flag_key_2,time_dat)
	用于记录第一种变化
================================*/


void NixieTube_show() //可以用这个函数看按键的状态
{
	NixieTube_Byte_show(0,NixieTube_date[flag_key_1/10]);Delay(100);
	NixieTube_Byte_show(1,NixieTube_date[flag_key_1%10]);Delay(100);
	NixieTube_Byte_show(1,0xff);
}


void Time_Ser()interrupt 3
{
	  TH1 = (65536-50000)/256;
      TL1 = (65536-50000)%256;
	  if(flag_key_1 != 0)	  //当按键按下时count才计数
	  {
		   count_t++;
		   time_dat = count_t;	   //记录完把值赋给time_dat
		   flag_key_2 = flag_key_1;	//把选择什么按键记录下来
	  }
	  else count_t = 0;
}
void Scanf_Key()
{
  
	while(S7 == 0)	 	//flag_key_1是是否按下的标志位,如果按下就为1,没按下就为0
	{
		NixieTube_show();
		flag_key_1 = 1;	
	}
	
	while(S6 == 0)	 	
	{
		NixieTube_show();
		flag_key_1 = 2;	
	}
		
	if((S7 != 0)&&(S6 != 0))
   	{
		flag_key_1 = 0;	
   	}		
}
void LED_Show()
{
	 switch(flag_key_2)
	 {
		 case 1:
				 if((time_dat <= 10)&&(time_dat >= 1))//(time_dat >= 1)也有消抖的作用  
				 {
				 	LED_dat = ~0x01;
				 }
				 else if(time_dat >= 10)
				 {
				 	LED_dat = ~0x02;
				 }
				 break;
		 case 2:
				 if((time_dat <= 10)&&(time_dat >= 1))  
				 {
				 	LED_dat = ~0x04;
				 }
				 else if(time_dat >= 10)
				 {
				 	LED_dat = ~0x08;
				 }
				 break;
	}	 
	XBYTE[0x8000] = LED_dat;
	flag_key_2 = 0;			   //处理完毕之后flag_key_2要清零

}
void main()
{
	System_init();
	Time_Init();
	while(1)
	{
	   NixieTube_show();
	   LED_Show();
	   Scanf_Key();
	}
}



版权声明:本文为weixin_45413123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。