STM32按键扫描及按键消抖

一.按键消抖

1.原理

在STM32单片机中,其硬件的按键设计有一些缺点,当我们按下按键时,并不会直接输出一个高或低电平,松开时也同理,如图

这是因为按键的机械设计,按下或松开时会有抖动,称为机械抖动,这样会对想通过按键实现的功能输出不稳定。

2.解决办法

解决方法有硬件消抖和软件消抖,这里我们只讨论软件消抖。

单次机械抖动的持续时间大约为10ms~20ms,在我们前期没有学习定时器和中断的情况下,只需要在按下按键和松开按键后面加一个简单的延时10ms~20ms函数就可以。

二.按键扫描函数

1.示例

先看一段代码


u8 key_scan(void)
{
	
	u8 key = 0xff;
	
	//检测按键按下
	if((KEY1)||(!KEY2)||(!KEY3)||(!KEY4))
	{
		//延时消抖
		delay_ms(20);
		
		//再次检测按键按下
		if(KEY1)
		//赋值键值
		key = 1;
	  if(!KEY2)
		key = 2;
		if(!KEY3)
		key = 3;
		if(!KEY4)
		key = 4;
		
	}
	
	//等待按键抬起
   while((KEY1)&&(!KEY2)&&(!KEY3)&&(!KEY4))
	{
	}
    delay_ms(20);
	
	//返回键值
	return key;
}

在这段代码中按键KEY1是高电平触发,KEY2,KEY3,KEY4都是低电平触发。

乍一看,是不是这段代码就已经实现了按键扫描的功能了,当按下按键1时触发消抖然后变量key被赋值1,之后通过while循环来卡住程序判断按键有没有松开,最后返回key也就是1到函数,在主函数设置一个变量接住这个按键扫描函数,当这个变量为1时就可以实现你想实现的功能。其他按键也同理。

但是,如果你想在主函数中的按键控制功能后面再实现别的功能,比如实现一个流水灯功能。你会发现,当你按下某个按键没有松开时,该按键对应的功能被实现,但流水灯的程序却被等待按键抬起的程序卡住了没有运行。虽然说谁都不会闲着按着按键很久不松,但人类正常按下按键到松开的时间终归有大约100ms的时间,这对于人类来说时间很短,但对单片机来说可以执行很多很多次任务,因为单片机执行程序是微秒级的。对于那些项目级程序来说,这种程序可能会造成一些漏洞。

那我们能不能去掉那条等待按键抬起的程序呢,答案是不行的,因为去掉之后,我们按一次按键就会执行多次按键扫描函数,原因如之前所讲———按一次按键大概100ms左右,在这期间主函数循环早已执行很多次了。说到主函数,顺便提一下,按键扫描函数完成后是要放在主函数的while循环里面的,这是因为STM32需要不断读取GPIO引脚的状态,以检查是否有按键被按下。

2.标志位思想

我们可以在按键扫描函数里增加一个变量代表标志位。

u8 key_scan(void)
{
	static u8 flag = 1;
	u8 key = 0xff;
	
	//检测按键按下
	if(((KEY1)||(!KEY2)||(!KEY3)||(!KEY4)) && flag)
	{
		//延时消抖
		delay_ms(20);
		flag = 0;
		//再次检测按键按下
		if(KEY1)
		//赋值键值
		key = 1;
	  if(!KEY2)
		key = 2;
		if(!KEY3)
		key = 3;
		if(!KEY4)
		key = 4;
		
	}
	
	//等待按键抬起
   else if((!KEY1)&&(KEY2)&&(KEY3)&&(KEY4))
	{
		delay_ms(20);
		flag = 1;
	}
	
	//返回键值
	return key;
}

在上述程序中,我们可以看出,当我们按下某个按键没松开时,标志位flag进行锁定,所以只会返回一次按键对应键值,其他返回值则会返回初始值0xff(因为按键没松开,程序会循环执行,不断产生返回值),按键松开后则会解锁标志位,解锁标志位后才能让下一次按键按下能返回键值。这段代码则不会卡住主程序,因为代码里面没有任何的while函数而是选择结构。

3.思路

最后我们说一下按键扫描的思路

①检测按键是否按下

②延时10~15ms

③再检测按键是否按下

④等待按键抬起  

⑤返回键值

该思路会卡住主程序,解决方案:增加标志位

通过按下按键锁定标志位,抬起按键解锁标志位

如果按键按下没有抬起,通过标志位锁定,不允许再识别按键

按键抬起标志位解锁,下次按按键又允许识别按键

  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值