关于stm32短按,长按,双击的处理(基于蓝桥杯嵌入式 stm g431)

基于网上学习,自我总结理解如下:

按键简介

按键工作原理

按键(轻触开关)常用于用户输入、模式切换、功能选择等场景。其由弹簧片和触点组成,按下时可以实现电路的闭合。按下时接通电路,松开时断开。

其常常搭配上拉或下拉电阻使用,搭配上拉电阻时,其接在近地侧,抬起时信号线高电平,按下拉低信号线;搭配下拉电阻时,其接在近电源侧,抬起时信号线低电平,按下拉高信号线。

开发板按键电路:

由此可知在此块开发板的按键为上拉电阻,即没有按时为高电平(1),按下则为低电平(0)。

GPIO输入的CubeMX配置和HAL库使用

经过前述分析,可知按键相关引脚连接和配置要求如下:

按键

对应引脚

配置

配置后效果

KEY1

PB0

上拉输入

默认高定平,按下低电平

KEY2

PB1

上拉输入

默认高定平,按下低电平

KEY3

PB2

上拉输入

默认高定平,按下低电平

KEY4

PA0

下拉输入

默认低定平,按下高电平

在CubeMX配置文件的GPIO配置中确认相关配置:

HAL库的引脚状态读取API:

/**
  * @brief  Reads the specified input port pin.
  * @param  GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
  * @param  GPIO_Pin: specifies the port bit to read.
  *         This parameter can be GPIO_PIN_x where x can be (0..15).
  * @retval The input port pin value.
  */
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)

随后关于按键read函数(其中分析有点复杂,本博主就不解释):

uint8_t key_value,key_down,key_up,key_old;
void KEY_Read(void)
{
   if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0) key_value=1;
	 else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0) key_value=2;
   else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0) key_value=3;
	 else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0) key_value=4;
	 else key_value=0; //默认为0
	
	key_down=key_value&(key_value^key_old);
	key_up=~key_value&(key_value^key_old);
	key_old=key_value;
  
}

main.c:

void KEY_Proc(void)
{
	
	if(uwTick-Key_Tick<20) //官方建议20ms
		return;
	Key_Tick=uwTick;
	KEY_Read();

关于短按(这个不解释,都看得懂):

//按键的短按处理
	if(key_up==1) {}
  else if(key_up==2) {}
	else if(key_up==3) {}
  else if(key_up==4) {}

关于长按:

本博主自我理解示意图(字可能不太好看…..):

 

即当按键按下时,高电平变为低电平,此时将定义长按的tick等于uwtick(即清零开始计算),再然后如果按键值还是按下的值并且超过800ms(普遍认为长按为800ms),则进行长按的实现函数

注意:若短按为按下触发的话(不是抬起触发),则长按和短按都会执行,所以注意!!!!

代码:

else if(key_down== 1||key_down== 2||key_down==3||key_down==4)
		{
			long_Tick=uwTick;
		}
		if(key_value==1&&(uwTick-long_Tick>800))
		{
		time++;
		}
	 else if(key_value==2&&(uwTick-long_Tick>800))
		{
			time--;
		}
	else if(key_down==3&&(uwTick-long_Tick>800))
		{
			
		}
	else if(key_down==4&&(uwTick-long_Tick>800))
		{
			
		}

 关于双击:

本博主自我理解示意图(字可能不太好看…..):

 即当按键第一次按下时,按键1的计数值=1,然后在此条件下,若按键1又按下了,且没有超过300ms(普遍认为300ms以内为双击所花费时间),则进行双击任务函数,若大于300ms则进行单按操作。

注意:这样会与前面的单按给混在一起,所以需要自我进行小修改;而且,双击这里的单按触发会比短按稍微慢一些些,可以看的出来。

代码:

if(key_down==1&&key_num_1==0)
	{
		key_num_1=1;
		double_Tick=uwTick;
	}
	else if(key_num_1==1)
	{ 
		if(key_down==1&& uwTick - double_Tick<300)
		{
			key_num_1=0;
			time=10;
		}
		else if(uwTick-double_Tick>300)
		{key_num_1=0;}
	}

总结:

 短按长按双击都可以很方便的使用内部定时器来这样执行,同时其他模块亦是如此,都万变不离其宗。

(本人学生,若有问题,大家可以相互交流学习,共同发展)

 

作者:学嵌入式的小白_1

物联沃分享整理
物联沃-IOTWORD物联网 » 关于stm32短按,长按,双击的处理(基于蓝桥杯嵌入式 stm g431)

发表回复