基于状态机的51单片机独立按键检测与消抖思路

2020-01-21来源: 51hei关键字:状态机  51单片机  独立按键检测  消抖

状态机的按键检测思路2
先回顾一下定义:
状态机有如下性质
按键状态机发生状态迁移的条件
如何准确检测条件是否发生并进行状态迁移
确保状态机能稳定地进行迁移
按键消抖的原理:状态切换
按键操作触发的时机

先回顾一下定义:
按键从未按下到按下,再到弹起,可以视为一个有4个状态的有限状态机。  分别是未按下、前沿抖动、按下、后沿抖动。  
即按键只在这4个状态间进行迁移,而且是当条件满足时按一定的顺序进行迁移:  未按下­­(条件1)­>前沿抖动­­(条件2)­>按下­­(条件3)­>后沿抖动­­(条件4)­>未按下  当且仅当条件成立时,才进行状态的迁移,当条件不成立时,状态机会保持当前状态不变。

状态机有如下性质

1.状态机会在条件满足时发生状态转移,由于每个状态会持续一段时间,而我们需要按键是理想的,即我们需要一个瞬间的按键事件,而不是连续的按键事件。  
总结:  
(1)当状态转移条件成立时,要进行状态的迁移。 
(2)状态转移是瞬间的,所以我们把某个状态转移当成按键来用。 
(3)未进行状态转移时,状态机会保持之前的状态。

按键状态机发生状态迁移的条件

0.png 

即如何对状态机的迁移条件进行准确判定。  
如何准确检测条件是否发生并进行状态迁移
注意:按键的初始状态是未按下
//在定义时将按键状态初始化为未按下
unsigned char KEY_Status = NOPRESS;

(1)条件1:前沿抖动开始  
从未按下状态到前沿抖动开始这一事件发生,电平为由1变为0  
即在未按下状态下,突然检测到低电平,就说明迁移条件成立了,立即把状态迁移到前沿抖动,或执行其他操作。
//KEY_Status == NOPRESS && KEY_Value == 0,等价于条件1成立
if (NOPRESS ==  KEY_Status && 0 == KEY_Value)
{
KEY_Status = PRESHAKE; //执行状态迁移
timer(); //设置一个10ms定时器,用定时器溢出事件来模拟前沿抖动结束事件。
}

(2)条件2:前沿抖动结束  
从前沿抖动状态到前沿抖动结束这一事件发生,有大约10毫秒的时间,虽然没有具体的事件,但可以用定时器中断来模拟前沿抖动结束事件。在前沿抖动的状态下,一旦定时器中断,就说明迁移条件成立了,立即把状态迁移至按下,或执行其他操作。

  1. //若PRESHAKE == KEY_Status && 1 == TF1 则条件2成立

  2. if (PRESHAKE == KEY_Status && 1 == TF1)

  3. {

  4. KEY_Status = PRESS; //执行状态迁移

  5. TF = 0; //清除溢出标志

  6. TR1 = 0; //关闭定时器

  7. }


(3)条件3:后沿抖动开始  
从按下状态到后沿抖动开始这一事件发生,电平由0变1,即只要在按下状态中检测到电平为1,就认为迁移条件成立了,立即把状态迁移至后沿抖动。

  1. //KEY_Status == PRESS && KEY_Value == 1则条件3成立

  2. if (PRESS == KEY_Status && 1 == KEY_Value)

  3. {

  4. KEY_Status = TAILSHAKE; //执行状态迁移

  5. n++; //执行想要的操作

  6. timer(); //用定时器溢出来模拟后沿抖动结束事件

  7. }


(4)条件4:后沿抖动结束  
从后沿抖动状态到后沿抖动结束这一事件发生,虽然没有具体的事件,但是历时是确定的,基本在10ms左右,可以通过定时器溢出来模拟后沿抖动结束事件。一旦定时器溢出(或者定时器中断发生),就说明迁移条件成立了,立即把状态迁移至未按下。

//TF1 == 1即后沿抖动结束标志。
//要在此时关闭定时器,防止重复判断。
if (1 == TF1)
{
KEY_Status = NOPRESS;
TF1 = 0; //清除溢出标志
TR1 = 0; //关闭定时器
}

确保状态机能稳定地进行迁移

如果状态能稳定的迁移,也就是说如果我们能对状态发生迁移的条件进行准确判断,
状态机就会实现稳定的迁移。就可以在此基础上进行其他操作,不用担心状态机的状态界定错误,因为状态机是可以稳定迁移的。 

 
所以关键是对状态发生迁移的条件进行准确判定,从而使各个状态不发生交叉,即稳定迁移。  


要反复检查上面我们对状态机迁移条件界定是否准确。直到确定是准确的,就可以在此基础上做点别的事情了。  


可以在心中模拟程序执行来验证思路是否正确。

按键消抖的原理:状态切换

(按键)状态机中,由于状态的切换是通过判定条件来进行的,一旦条件成立,状态就瞬间切换了,每个状态会持续一段时间,在此期间循环可能会执行多次,但由于状态切换的条件不满足,所以不会进入if语句中操作。所以如果把任何状态切换到下一状态的瞬间当成按键事件,那么按键就只会被检测到一次,这就是按键消抖的原理。

按键操作触发的时机
实际测试发现,把对按键事件的响应操作放在后沿抖动开始时(即状态机由按下状态迁
移到后沿抖动状态的瞬间)效果比较不错,不会显得太敏感也不会显得很迟钝。


关键字:状态机  51单片机  独立按键检测  消抖 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic486353.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:51单片机理通定时器输出PWM例程
下一篇:编程实现单片机ds18b20温度测量及显示系统

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

基于状态机的按键长按,短按,双击 单片机源程序
;                               //按键被按下,状态转换到按键消抖和确认状态//                        break;                case key_state_1:       
发表于 2020-02-09
avr单片机mega32基于状态机的按键设计
以前用延时消抖,比较浪费时间,现在用状态机设计,不占用太多时间,但是需要一个定时器。1.状态机按键消抖*****************************************************************//状态机按键消抖//CPU:mega32//编译器:winavr#include <avr/io.h>#include <avr/interrupt.h>char key_scan(void);#define PRESS   ( PIND&(1<<3) ) == 0#define NOT_PRESS  
发表于 2019-11-28
avr单片机mega32基于状态机的按键设计
【单片机笔记】状态机效率地按键扫描、识别及检测方法
可以看出优先级的顺序为:KEY1>KEY2>KEY3>KEY4>KEY5。当然需要使用多少个按键根据项目的需求来定,理论支持多少个独立按键都是可以的。第三部分:状态机的按键判定部分//状态机static u8 Key_Scan(void){ static u8 state = 0; //按键初始化状态 static u8 KEY_LAST=0,KEY_NOW=0; //记录两次电平的状态 u8 KEY_VALUE=0;  KEY_NOW = Key_Read();//读按键值    switch(state) { case 0: { if(KEY_NOW
发表于 2019-02-18
STM32 状态机实现按键消抖处理源码
;    https://blog.csdn.net/weixin_40779546/article/details/81776171****--------------文件信息--------------------------------------------------------------------------------**文件名    : key.c**描 述       : 按键状态机**                     
发表于 2019-01-14
stm32F103状态机矩阵键盘
矩阵键盘程序,作为麦知club小车项目的一部分,从IAR状态机应用修改而来。IAR7.4+STM32CUBEMX调试通过。键盘行4,列3,每条线都有10K上拉电阻。改到4×4矩阵也很容易。行线设置为 输入,针脚为浮空; 列线设置为开漏输出。不支持长按和组合键,主要是我不会改。在OS中使用20ms任务周期调用。以下贴出代码。keypad.h/* * * Name: keypad.h */  #ifndef KEYPAD_H  #define KEYPAD_H    #include "stm32f1xx_hal.h"  
发表于 2018-06-22
单片机步进电机转速控制程序(速度LED显示)
单片机源程序如下://数码管位 高位-----低位//四个按键控制步进电机:正转,反转,加1,减1//上电时电机启动,数码管上显示速度最小档1,加减档位均能通过数码管显示出来,电机采用单双八拍方式//电机转速一共10档,通过按键调节转速 //电机正转时最高位数码管显示0,反转时显示1  #include<reg51.h>#define uchar unsigned char#define uint unsigned int#define led P0//数码管段选#define haha P2sbit s1 = P1^0;sbit s2 = P1^1;sbit s3 = P3^0;sbit
发表于 2020-02-08
单片机步进电机转速控制程序(速度LED显示)
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved