STM32--按键抖动问题的探讨

转载请说明出处。

接上文STM32–矩阵键盘的设计实现

按键抖动

成功扫描到按键按下后,由于按键本身有着不可避免的抖动问题,一般我们会设置一段延时,延时过后再次判断按键是否按下。
一个按键按下到松开的逻辑过程
这是使用逻辑分析仪捕捉的一个按键从按下到松开的过程(高电平为按下)。可以发现,在按下的一瞬间,按键的电平发生了一段无规律跳动,这个就是抖动。
很多在学校的小伙伴可能对这种现象不以为然。当然,设置一小段时间的delay的确可以解决这个问题。但在一些公司的项目开发中,是不允许使用任何的延时函数的,这会造成主程序的阻塞(即使是几毫秒的延时阻塞也不允许),用按键触发的外部中断或者用while来判断按键松开也会对主函数造成一瞬间的阻塞(不松开按键主程序就无法继续执行那种),这也是不允许的。
那么,不允许使用延时函数来过滤抖动信号,还有什么方法来解决这个问题呢?
很多小伙伴应该会立马给出一个答案:定时器
定时器的确可以完美解决这个问题。将定时器配置为每1ms触发一次定时器中断,或者每5ms、10ms触发一次,通过这个设置计时标志,只需要检测这个计时标志是否到达所需要的时间,到了之后再检测按键是否按下。期间不会对主程序造成阻塞,程序会一直循环执行。

比如我们配置一个定时器TIM2

static void MX_TIM2_Init(void)
{	
  //Tout = ((10 Period)*(7200 Prescaler))/72000000 Hz(外部高速时钟) = 0.001s 	

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 7200-1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 10-1;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

每1ms触发一次计数溢出中断,函数外部设置一个全局变量,在中断回调函数中每触发一次对这个值进行自增。

uint16_t ShakeTime = 0;		//全局变量
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	if (htim->Instance == htim2.Instance){
		ShakeTime++;
		
		//这个的作用是防止计数溢出。对这个全局变量清零的比较频繁的话可以不用这段代码
		if (ShakeTime >= 32768){
			ShakeTime = 0;
		}
	}
}

每1ms触发一次计数溢出中断,也就是说这个全局变量每1ms自增一次。

在检测到按键按下后,把这个值清零,之后在每一轮的程序循环中,只需要检测这个全局变量是否自增到了某个数字,到了之后再对按键电平进行检测即可。

特殊情况

我们对这个按键抖动的问题一般只对按下时进行解决而已,但有没有想过,在松开的瞬间,按键是否也会产生抖动?

答案是有的,不过松开按键产生抖动的情况可能会比按下按键的情况少一点,但在项目开发中,如果对产品设计严格一点的话,这也是一个不允许被忽略的问题。
按键按下到送开的过程

从图中我们可以看到,按键按下跟松开时都有一段时间的抖动。比如按键操作一个LED灯,结合上述提出的情况,这段松开按键的过程如果不做任何处理的话,很有可能会造成一瞬间的一亮一灭,然后又会点亮。在严格一点的项目开发中是不允许这种情况出现的。

什么,你说松开的一瞬间即使抖动,由于LED被操作了一次,这段抖动也可以被开头的消抖操作给自动过滤掉,没问题啊?

那么我们再看一下这个
按键按下到松开的过程
(没想到吧)

这种现象我估计在按键使用过久老化之后才会出现的多(你啪啦啪啦瞎乱按一通也可能会出现),不对这个进行处理的话,产品使用久了,按键抖动的厉害,可能就会导致操作失误。

解决办法倒也简单,检测到按键松开时再进行抖动检测就好,跟上面按下时检测抖动的步骤基本一样。

相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页