用状态机做独立按键检测

合集下载

3.2.2独立按键检测(消抖原理)(精)

3.2.2独立按键检测(消抖原理)(精)

按键的去抖
机械式按键在按下或释放时,由于机械弹性作用的影响,通常伴随 有一定时间的触点机械抖动,然后其触点才稳定下来,抖动时间一 般为510ms,在触点抖动期间检测按键的通与断状态,可能导致 判断出错。
键按下
前沿抖动
)检测按键
(b)释放按键
按键去抖流程图
独立式按键
实际应用中,一般希望按键一次按下单片机只处理 一次,但由于单片机执行程序的速度很快,按键一次 按下可能被单片机多次处理。为避免此问题,可在按 键第一次按下时延时10ms之后再次检测按键是否按下, 如果此时按键仍然按下,则确定有按键输入。这样便 可以避免按键的重复处理。
计数器
按键按照结构原理可分为两类,一类是触点式开关按键, 如机械式开关、导电橡胶式开关等;另一类是无触点开关 按键,如电气式按键,磁感应按键等。前者造价低,后者 寿命长。按键按照接口原理可分为编码键盘与非编码键盘 两类。 这两类键盘的主要区别是识别键符及给出相应键码的方 法。编码键盘主要是用硬件来实现对按键的识别,硬件结 构复杂;非编码键盘主要是由软件来实现按键的定义与识 别,硬件结构简单,软件编程量大。这里将要介绍的独立 式按键和矩阵式键盘都是非编码键盘。
2.任务分析
(2)独立式按键的软件设计
在单片机应用系统中 主程序一般是循环结构,键盘程 序作为子程序供主程序调用。单片机按键控制系统的主程 序结构图所示。
物理按键抖动波形图
按键消抖一般有两种方法,即硬件消抖和软件消抖。
硬件消抖方法
在软件设计中,当单片机检测到有键按下时,可以 先延时一段时间越过抖动过程再对按键识别。
独立式按键电路配置灵活,软件结构简单,但每个按键必须占用 一根I/O口线,因此,在按键较多时,I/O口线浪费较大,不宜采用。

51单片机独立按键实验

51单片机独立按键实验

实验5 单片机独立按键控制数码管加1我们在使用家用电器时经常需要通过按键给电器输入指令,让电器执行动作,比如电磁炉的开关,电饭煲定时时间设定等。

我们知道单片机只能识别高低电平,对51单片机来说,0V为低,5V为高。

按键就相当于一个开关,按下时候导通,按键弹开时断开。

机械式按键再按下或释放时,由于机械弹性作用的影响,通常伴随有一定时间的触点机械抖动,然后其触点才稳定下来。

其抖动过程如图1(a)所示,抖动时间的长短与开关的机械特性有关,一般为5 ~10 ms。

从图中可以看出,在触点抖动期间检测按键的通与断状态,可能导致判断出错。

即按键一次按下或释放被错误地认为是多次操作,这种情况是不允许出现的。

为了克服按键触点机械抖动所致的检测误判,必须采取去抖动措施,可从硬件、软件两方面予以考虑。

一般来说,在键数较少时,可采用硬件去抖,而当键数较多时,采用软件去抖。

(本学习板采用软件去抖方式)。

软件去抖的流程图如图1(b)所示。

从按键的去抖流程图我们可以知道,检测到有键按下时,应延时等待一段时间(可调用一个5ms~10ms的延迟子程序),然后再次判断按键是否被按下,若此时判断按键仍被按下,则认为按键有效,若此时判断按键没有被按下,说明为按键抖动或干扰,应返回重新判断。

键盘真正被按下才可进行相应的处理程序,此时基本就算实现了按键输入,进一步的话可以判断按键是否释放。

8个独立按键电路图从图中可知独立式按键采用每个按键单独占用一根I/O 口线结构。

当按下和释放按键时,输入到单片机I/O 端口的电平是不一样的,因此可以根据不同端口电平的变化判断是否有按键按下以及是哪一个按键按下。

按键和单片机引脚连接并加了上拉电阻,这样当没有按键按下的时候,I/O 输入的电平是高电平,当有按键按下的时候,I/O 输入的电平是低电平。

虽然独立式按键电路配置灵活,软件结构简单,但每个按键必须占用一根I/O 口线,因此,在按键较多时,I/O 口线浪费较大。

vivado按键消抖原理

vivado按键消抖原理

vivado按键消抖原理按键消抖是指在数字电路中,当按键按下或释放时,由于按键机械开关的特性,会导致电路出现不稳定的信号状态。

这种不稳定状态可能会导致错误的触发,例如出现多次触发或漏触发。

因此,为了确保按键信号的稳定性和可靠性,需要进行按键消抖处理。

按键消抖的原因主要有两个方面。

首先,按键机械开关的接触面存在微小的弹跳现象,当按键按下或释放时,接触面会在短时间内反复接触和分离,导致电路信号出现多次变化。

其次,由于电路中存在的噪声干扰,也会使得按键信号产生抖动。

为了解决按键消抖问题,可以采用硬件和软件两种方法。

硬件方法主要通过添加滤波电路或使用稳定的按键开关来消除按键弹跳现象。

滤波电路可以通过RC电路或者使用专用的按键消抖芯片来实现。

而软件方法主要通过在数字电路中添加按键消抖算法来处理按键信号。

在Vivado中,按键消抖可以通过使用状态机来实现。

状态机是一种用于描述系统行为的模型,可以根据输入信号的状态变化来改变系统的状态和输出。

在按键消抖中,可以使用状态机来检测按键信号的变化,并根据一定的状态转换规则来消除按键弹跳现象。

具体实现时,可以将按键信号作为输入,将按键状态和输出作为状态机的状态和输出。

当按键信号发生变化时,状态机会根据一定的状态转换规则进行状态转换,并输出消抖后的按键信号。

常用的状态转换规则包括按键按下时状态转换为按下状态,按键释放时状态转换为释放状态,以及连续按键时状态不变。

在Vivado中,可以使用Verilog或VHDL等硬件描述语言来编写状态机代码。

首先,需要定义状态机的输入、输出和状态变量,并初始化各个变量的初始值。

然后,需要编写状态转换规则和输出逻辑,根据输入信号的状态变化来改变状态和输出。

最后,需要将状态机代码综合生成对应的逻辑电路,并进行仿真和验证。

总结起来,按键消抖是数字电路设计中常见的问题,为了确保按键信号的稳定性和可靠性,需要进行按键消抖处理。

在Vivado中,可以使用状态机来实现按键消抖,通过定义状态转换规则和输出逻辑,消除按键弹跳现象。

实验三_用状态机实现序列检测器的设计

实验三_用状态机实现序列检测器的设计

实验三_用状态机实现序列检测器的设计引言:序列检测器是一类常用的电子设计电路,它在接收到特定的输入序列时,会产生特定的输出序列。

在许多应用场景中,如通信系统、数字信号处理和自动控制等领域,序列检测器都发挥着重要的作用。

本实验将利用状态机的概念,设计并实现一个简单的序列检测器。

一、序列检测器的设计原理序列检测器的设计原理基于状态机的思想。

状态机是一种抽象的计算模型,它由一组状态、一组输入和一组转移动作组成。

在序列检测器中,输入序列被连续地输入,状态也会根据输入进行不断变化。

当状态机检测到了预设的特定输入序列时,就会产生相应的输出序列。

二、序列检测器的设计步骤1.确定输入和输出序列:首先确定所需检测的输入序列和对应的输出序列,这将决定状态机的状态转移条件。

2.绘制状态转移图:根据输入和输出序列,绘制状态转移图,即用状态变量和状态转移条件表示状态转移关系。

3.设计状态机的状态转移表:根据状态转移图,将所有可能的状态转移关系整理为一个状态转移表。

4.实现状态机的代码逻辑:根据状态转移表,编写代码实现状态机的逻辑功能。

三、设计实例在本实验中,我们以一个简单示例为例,演示序列检测器的设计流程。

假设输入序列为0101,当检测到该输入序列时,输出序列为011.确定输入和输出序列:输入序列为0101,输出序列为012.绘制状态转移图:根据输入和输出序列,绘制状态转移图如下:0/00,S0,1/1/1说明:状态S0表示未检测到特定输入序列,状态S1表示检测到特定输入序列。

3.设计状态机的状态转移表:根据状态转移图,得到状态转移表如下:输当前状态,0,1S0,S0,S1S1,S0,S14.实现状态机的代码逻辑:根据状态转移表,编写代码实现状态机的逻辑功能,伪代码如下:if (当前状态 == S0)if (输入 == 0)当前状态=S0;输出=0;} else if (输入 == 1)当前状态=S1;输出=0;}} else if (当前状态 == S1)if (输入 == 0)当前状态=S0;输出=1;} else if (输入 == 1)当前状态=S1;输出=1;}}四、实验总结本实验利用状态机的思想,设计并实现了一个简单的序列检测器。

STM32按键扫描之状态机

STM32按键扫描之状态机

STM32按键扫描之状态机问题描述:STM32平台GPIOA_Pin_6连接独立按键。

现需要实现:当按键按下后在1秒内释放了,此时计数值加1,而当按键按下后在1秒内没有释放,那么以后每隔0.5秒,计数值就会自动加上10,直到按键释放为止。

实现原理:采用有限状态机分析,事半功倍。

状态转换图如下:因此该状态图有四种状态:初始状态无按键状态(NoKeyDownStatus)、按键确认状态(KeySureDownStatus)、单次按键状态(OnceKeyDownStatus)、和连发状态(ContiousKeyDownStatus)。

系统每10ms进入读按键状态函数:StateStatus ReadKeyStatus(void)定义一个枚举类型列出该系统所有的状态:typedef enum{NoKeyDownStatus=0,KeySureDownStatus,OnceKeyDownStatus,ContiousKeyDownStatus}StateStatus;/**************************************************************Name :StateStatus ReadKeyStatus(void)*Function :Get the key status at the frequency of 10ms*Input :None*Output :Key status*************************************************************/StateStatus ReadKeyStatus(void){static StateStatus state = NoKeyDownStatus;static int TimeCount=0;int KeyPress = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);StateStatus KeyReturn = NoKeyDownStatus;switch(state){case NoKeyDownStatus:if(!KeyPress){state = KeySureDownStatus ;}break;case KeySureDownStatus:if(!KeyPress){state = OnceKeyDownStatus ;TimeCount = 0;}else{state = NoKeyDownStatus ;}break;case OnceKeyDownStatus:if(KeyPress) //if the kye is up,so it's a normal key.{state = NoKeyDownStatus ;KeyReturn = OnceKeyDownStatus;}/*-If the status keep 1s,state switch to contious status-*/ else if(++TimeCount>=100){state = ContiousKeyDownStatus ;TimeCount = 0;KeyReturn = ContiousKeyDownStatus ;}break;case ContiousKeyDownStatus:if(KeyPress){state = NoKeyDownStatus ;KeyReturn = NoKeyDownStatus ;}/*-contious status have stay for 0.5s-*/else if(++TimeCount>50){//state = ContiousKeyDownStatus;KeyReturn = ContiousKeyDownStatus;TimeCount = 0;}/*if it dose not uplift but stay for ContiousKeyDownStatus less than 0.5s*/else{KeyReturn = NoKeyDownStatus;}break;}return KeyReturn;}代码微分析:如图在计时状态一时,其状态转换条件有:1)该状态没有维持1S时,按键就已抬起,此时转换到无按键按下状态。

独立按键识别-单片机原理-实验报告

独立按键识别-单片机原理-实验报告

宁德师范学院计算机系
实验报告
(2014—2015学年第 2学期)
课程名称单片机原理
实验名称独立按键识别
专业计算机科学与技术(软工)年级 2012级
学号 B2012103145 姓名冯武
指导教师杨烈君
实验日期 2015.5.27
实验步骤、实验结果及分析:
1 实验步骤:
1、使用Proteus ISIS 7 Professional
应用程序,建立一个.DSN文件
2、在“库”下拉菜单中,选中“拾取元件”(快捷键P),分别选择以下元件:AT89C51、CAP、CAP-ELEC、CRYSTAL、RESPACK-8。

3、构建仿真电路
图1 按键识别1、2
图2 按键识别3
图3按一下暂停
图4归零
图5时钟调整
电路图
注:1、报告内的项目或设置,可根据实际情况加以补充和调整 2、教师批改学生实验报告应在学生提交实验报告10日内。

单片机按键单击双击长按功能实现

单片机按键单击双击长按功能实现

单片机按键单击双击长按功能实现在很多嵌入式系统中,都需要对按键进行检测和处理,以实现不同的功能。

常见的按键功能包括单击、双击和长按。

在这篇文章中,我们将介绍如何使用单片机实现这些按键功能。

首先,我们需要连接一个按键到单片机的I/O口。

按键通常是一个开关,有两个接触点。

当按键按下时,两个接触点会闭合,导致I/O口的电平发生变化。

我们可以利用这个变化来检测按键的状态。

为了实现按键功能,我们需要编写一段程序来监测按键的状态。

以下是一个简单的流程:1.初始化I/O口:将按键连接到I/O口上,并将I/O口设置为输入模式。

2.监测按键状态:定时读取I/O口的电平状态,以检测按键是否按下。

如果I/O口电平发生变化,则按键被按下或松开。

3.单击功能:当按键被按下时,记录当前时间,并等待一段时间,如果超过这段时间,说明按键已松开,则触发单击功能。

4.双击功能:如果在两次按键之间的时间间隔内再次检测到按键按下,则触发双击功能。

5.长按功能:当按键被按下一段较长的时间后,触发长按功能。

下面我们来具体介绍如何实现这些功能。

首先,我们需要初始化单片机的I/O口。

这个过程可以通过配置相应的寄存器实现。

具体的方法和步骤依赖于你使用的单片机型号和开发环境。

在这里,我们不具体展开,而是假设我们已经成功初始化了I/O口。

接下来,我们需要设置一个计时器用于定时检测按键的状态。

计时器的定时周期决定了我们可以检测的最短按键时间间隔。

通常,我们使用一个定时器来实现单击和双击功能,使用另一个定时器来检测长按功能。

一旦我们完成了计时器的配置,我们就可以开启定时器中断,并启动计时器。

每当定时器溢出时,中断函数会被触发,我们可以在这个函数中检测按键的状态。

在中断函数中,我们读取I/O口的电平状态,并根据当前的按键状态做出相应的处理。

首先,我们需要检测按键是否按下。

为了防止按键的抖动和误触发,我们使用一个状态机来确定按键的状态。

状态机的状态可以分为按下和松开两种。

最简洁的按键检测 原理算法 c语言

最简洁的按键检测 原理算法 c语言

最简洁的按键检测原理算法 c语言按键检测是在电子设备中常见的操作,它可以实现对按键的状态进行监测和响应。

本文将介绍一种简洁的按键检测原理算法,并使用C语言进行实现。

在电子设备中,按键通常是一种开关,用于接通或断开电路。

按下按键时,电路闭合,产生一个信号,通过按键检测可以获取到这个信号,并进行相应的处理。

按键检测的原理算法如下:1. 初始化:首先需要对按键进行初始化设置,包括设置按键引脚的输入/输出状态和电平状态。

2. 检测按键状态:通过读取按键引脚的电平状态来检测按键的状态。

一般来说,按键引脚的电平为高电平(1)表示按键未按下,低电平(0)表示按键按下。

3. 延时:为了避免检测到按键的抖动(按键在按下和松开的瞬间会产生多次信号),可以在检测到按键状态改变后进行一个短暂的延时,一般为几毫秒。

4. 再次检测:在延时后,再次读取按键引脚的电平状态。

如果检测到的状态与之前不同,说明按键的状态发生了改变。

5. 处理按键事件:根据按键的状态改变来进行相应的处理,比如执行一段代码、发送一个信号等。

6. 循环检测:以上步骤需要放在一个循环中进行,以实现对按键状态的持续监测和响应。

下面是一个简单的按键检测的C语言示例代码:```c#include <stdio.h>#include <wiringPi.h>#define BUTTON_PIN 17int main(){if (wiringPiSetup() == -1) // 初始化wiringPi库{printf("wiringPi setup failed!\n");return -1;}pinMode(BUTTON_PIN, INPUT); // 设置按键引脚为输入模式int previousState = HIGH; // 初始状态为未按下while (1){int currentState = digitalRead(BUTTON_PIN); // 读取按键引脚的电平状态if (currentState != previousState) // 检测到按键状态改变{delay(50); // 延时50毫秒,避免按键抖动currentState = digitalRead(BUTTON_PIN); // 再次读取按键引脚的电平状态if (currentState != previousState) // 再次检测到按键状态改变{if (currentState == LOW) // 按键按下{printf("Button pressed!\n");// 其他处理代码...}else // 按键松开{printf("Button released!\n");// 其他处理代码...}}}previousState = currentState; // 更新前一个状态}return 0;}```以上代码使用了wiringPi库来进行GPIO的控制和读取,需要在编译时加上-lwiringPi选项。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

人机界面最重要的就是按键了,觉得按键做的最好的就是手机的按键了,有长按、敌探、连发等功能。

还有组合等。

一个好的按键程序用书本上学的按键检测方法已经不能适应工程的需要了,为此人们设计出一种状态机检测按键的方法。

在一个系统中按键是随机的,因此系统软件对按键要一直循环查询,由于按键检测过程需要进行消抖处理,因此取状态机的时间序列为10ms,这样不仅可以跳过按键抖动的影响,同时也小于0.3-0.5秒的稳定闭合期,不会将按键的操作过程丢失。

程序实现方法,用定时器定时10ms,每隔10ms检测一次按键,将一个按键的检测过程分为几个不同的状态,最简单的分为初使状态-按键闭合确认状态-按键释放状态,如果要求按键实现的功能越多,状态也就越多,比如还有常用的长按状态。

以下是一个状态机按键程序,仅供参考。

程序基于AVR 单片机, key.h文件的一部分
#define KEY0_PORT PORTD
#define KEY0_DDR DDRD
#define KEY0_PIN PIND
#define KEY0 PD0
#define KEY1_PORT PORTD
#define KEY1_DDR DDRD
#define KEY1_PIN PIND
#define KEY1 PD1
#define KEY2_PORT PORTD
#define KEY2_DDR DDRD
#define KEY2_PIN PIND
#define KEY2 PD2
#define KEY3_PORT PORTD
#define KEY3_DDR DDRD
#define KEY3_PIN PIND
#define KEY3 PD3
#define KEY0_STATUS (BIT_STATUS(KEY0_PIN,KEY0))
#define KEY1_STATUS (BIT_STATUS(KEY1_PIN,KEY1))
#define KEY2_STATUS (BIT_STATUS(KEY2_PIN,KEY2))
#define KEY3_STATUS (BIT_STATUS(KEY3_PIN,KEY3))
#define KEY_SERIES_FLAG 200 //按键连发开始所需时间长度
#define KEY_SERIES_DELAY 5 //按键连发的时间间隔长度
//按键属性
#define KEY_DOWN 0xA0
#define KEY_LONG 0xB0
#define KEY_LIAN 0xC0
#define KEY_UP 0xD0
#define KEY_LONG 0xB0
#define KEY_LIAN 0xC0
#define KEY_UP 0xD0
#define NO_KEY 0x00
#define KEY0_DOWN 0X01
#define KEY1_DOWN 0X02
#define KEY2_DOWN 0X03
#define KEY3_DOWN 0X04
#define KEY0_PRESS (KEY_DOWN|KEY0_DOWN)
#define KEY1_PRESS (KEY_DOWN|KEY1_DOWN)
#define KEY2_PRESS (KEY_DOWN|KEY2_DOWN)
#define KEY3_PRESS (KEY_DOWN|KEY3_DOWN)
key.c文件一部分
static uchar Get_Key(void)
{
if (KEY0_STATUS==0) return KEY0_DOWN;
if (KEY1_STATUS==0) return KEY1_DOWN;
if (KEY2_STATUS==0) return KEY2_DOWN;
if (KEY3_STATUS==0) return KEY3_DOWN;
return NO_KEY;
}
uchar Key_Scan(void)
{
static uchar Key_State = 0; //按键状态
static uchar Key_Prev = 0; //上一次按键 static uchar Key_Delay = 0; //按键连发时间 static uchar Key_Series = FALSE; //标志连发开始
uchar Key_Press = NO_KEY; //按键值
uchar Key_Return = NO_KEY; //按键返回值
Key_Press = Get_Key();
switch (Key_State)
{
case 0://按键初始态00
if (Key_Press !=NO_KEY)//有按键按下
{
Key_State = 1;//转到按键确认
Key_Prev = Key_Press;//保存按键状态
}
break;
case 1://按键确认态01
if ( Key_Press ==Key_Prev )//确认和上次按键相同
{
Key_State = 2;//判断按键长按
//返回按键按下键值,按键按下就响应,如果想弹起来再响应
//可以在弹起来后再返回按键值
Key_Return = KEY_DOWN | Key_Prev;
}
else//按键抬起,是抖动,不响应按键
{
Key_State = 0;
}
break;
case 2://按键释放态10
if (Key_Press == NO_KEY )//按键释放了
{
Key_State = 0;
Key_Delay = 0;
Key_Series = FALSE;
Key_Return = KEY_UP | Key_Prev; //返回按键抬起值 break;
}
if ( Key_Press ==Key_Prev )
{
Key_Delay++;
if ((Key_Series==TRUE) && (Key_Delay>KEY_SERIES_DELAY)) {
Key_Delay = 0;
Key_Return = KEY_LIAN | Key_Press; //返回连发的值 Key_Prev = Key_Press; //记住上次的按键.
break;
}
if (Key_Delay>KEY_SERIES_FLAG)
{
Key_Series = TRUE;
Key_Delay = 0;
Key_Return = KEY_LONG | Key_Prev; //返回长按后的值 break;
}
}
default :
break;
}
return Key_Return;
}
每10ms调用一次按键检测,根据Key_Return的值来判断按键的操作,用状态机省去传统按键的延时去抖,也不在在按键的死等待,对程序时间的利用有很大的帮助,根据按键返回的状态值,事件可以在按键按下响应,也可以在按键弹起来响应,也可以实现连发、长按等功能。

相关文档
最新文档