任务4.1 基于某状态机的程序架构

合集下载

jki状态机中三个核心的编写规则

jki状态机中三个核心的编写规则

JKI状态机中三个核心的编写规则1. 简介JKI状态机(JKI State Machine)是一种基于LabVIEW软件的状态机框架,用于开发可靠、可扩展和易维护的应用程序。

它采用了数据驱动的设计理念,以及一些编程最佳实践,使得开发者能够更加高效地编写代码。

在JKI状态机中,有三个核心的编写规则,即:单一职责原则、封装性原则和松耦合原则。

这些原则帮助开发者创建清晰、灵活且易于维护的状态机代码。

2. 单一职责原则单一职责原则(Single Responsibility Principle)是指一个类或模块应该只有一个引起它变化的原因。

在JKI状态机中,每个状态和每个事件都应该具有清晰明确的职责。

2.1 状态的单一职责每个状态应该只关注自己所负责的任务或功能。

例如,在一个自动售货机的状态机中,可以定义以下几个状态:待命、选择商品、投入硬币、出货等。

每个状态只需要关注自己对应功能的实现即可,不需要关心其他状态的逻辑。

2.2 事件的单一职责每个事件应该只触发一种状态转换或执行一种功能。

例如,在自动售货机的状态机中,可以定义以下几个事件:按下商品按钮、投入硬币、取出商品等。

每个事件只需要执行对应的操作即可,不需要处理其他不相关的逻辑。

遵循单一职责原则可以使代码更加清晰、易读和易于维护,同时也方便进行功能扩展和修改。

3. 封装性原则封装性原则(Encapsulation Principle)是指将数据和行为捆绑在一个对象中,并对外提供接口进行访问。

在JKI状态机中,封装性原则帮助开发者隐藏状态机的内部实现细节,只暴露必要的接口。

3.1 封装状态和事件将状态和事件封装成独立的对象,通过定义公共接口来控制其行为。

例如,在LabVIEW中可以创建一个名为”State”的类来表示状态,并在其中定义相应的方法和属性。

通过这种方式,可以将状态的实现细节隐藏起来,只提供给外部必要的操作接口。

3.2 封装状态转换逻辑将状态之间的转换逻辑封装成独立的函数或方法。

状态机分层 c语言

状态机分层 c语言

状态机分层 c语言(原创实用版)目录1.状态机分层概述2.状态机的实现方法3.C 语言在状态机分层中的应用4.实例分析正文1.状态机分层概述状态机分层是一种在计算机科学中广泛应用的设计模式,主要用于处理系统中的复杂状态和行为。

它通过将系统的状态划分为多个层次,从而降低了问题的复杂性。

状态机分层可以应用于各种场景,例如编译器、网络协议、游戏引擎等。

2.状态机的实现方法状态机通常由状态、事件和动作组成。

状态表示系统的当前情况,事件表示系统中的触发器,动作表示系统在特定状态下需要执行的操作。

状态机的实现方法主要有两种:一种是基于有限自动机(Finite Automaton,FA),另一种是基于图灵机(Turing Machine,TM)。

有限自动机是一种用来表示系统的状态和状态转换的计算模型,而图灵机则是一种理论模型,用于描述具有无限存储空间的计算过程。

3.C 语言在状态机分层中的应用C 语言是一种广泛应用的编程语言,它具有强大的功能和高性能。

在状态机分层中,C 语言可以用来实现状态机,以及处理状态机之间的交互。

C 语言提供了丰富的数据类型、运算符和控制结构,可以方便地表示和处理状态机的状态、事件和动作。

此外,C 语言还具有底层访问能力,可以实现高效的系统调用和硬件操作。

4.实例分析以一个简单的编译器为例,它主要包括词法分析器、语法分析器和语义分析器。

在这些分析器中,词法分析器和语法分析器可以看作是状态机。

词法分析器负责处理输入字符串中的字符,将它们转换为记号(token)。

语法分析器则负责将记号序列转换为抽象语法树(Abstract Syntax Tree,AST)。

在这个过程中,词法分析器和语法分析器需要不断地处理输入事件,并根据当前状态执行相应的动作。

C 语言可以用来实现这些状态机,以及处理它们之间的交互。

总之,状态机分层是一种有效的设计模式,可以帮助我们处理复杂的系统状态和行为。

C 语言作为一种功能强大的编程语言,在状态机分层中具有广泛的应用。

嵌入式系统应用程序方案之一——基于事件驱动的应用程序框架

嵌入式系统应用程序方案之一——基于事件驱动的应用程序框架

列,以启动相应的处理。
数据流程
技术支持:028-85136173
2

嵌入式系统应用程序方案之一
各个任务模块的主要功能之一就是对各级应用数据进行必要的加工,并形成新的数据。 典型的数据加工可以是:
对串口来的数据进行帧格式分析,提取相关数据,即通常的通讯规约分析; 对 AD 采集的原始数据进行某种统计处理,提取特征数据; 读取数字输入状态,进行必要处理; 读取网络报文,进行必要的应用层规约解析 应用数据存文件,文件数据处理等等 由于每个任务的执行机会具有一定的不确定性,因此需要对数据开设一定的缓冲区,对 一般的应用来说,数据处理通常都是顺序进行的,所以数据缓冲区的结构通常采用 FIFO 数 据结构,缓冲区的数据单元即可是简单的字节、字,也可以是复合的数据结构。在英创提供 的程序中,串口的数据缓冲区就是采用的 FIFO 数据结构,数据单元为一个字节,FIFO 结 构的数据缓冲区也称为环型 buffer。 可以由一个任务作数据处理,另一个任务作数据传送,对多任务共享的单一数据单元, 可通过设置信号灯的方法来确保数据单元的完整性,对多个数据单元,同样可考虑采用 FIFO 数据结构。对数据响应时间有严格要求的应用,也可以用一个任务实现数据采集处理和网络 通讯全过程。 以下具体介绍实现上述方案的主要代码。建议用户在阅读本文之前,已对英创嵌入式模 块的功能测试程序有了基本了解。
// 可以根据应用定义更多的命令
#define #define
MaxCmdStack 400
PARLEN
14
// 定义系统任务队列的长度 // 每个命令所带参数的长度
class TaskQueue
{
static unsigned int PutIdx;

状态机c语言精选全文

状态机c语言精选全文

可编辑修改精选全文完整版状态机c语言状态机是一个重要的概念,它能够帮助我们理解和描述复杂的系统的转换过程。

当我们讨论一个状态机时,一般会考虑它的输入信号,它的内部状态,和它的输出信号。

状态机也可以用来映射实际的系统的行为,从而实现预期的功能。

C语言是一种通用的、高级的编程语言,由计算机科学家詹姆斯沃森于1972年发明。

它是一种结构化的、编译型的语言,它可以用来编写复杂的程序。

状态机c语言是一种在c语言中实现状态机的编程方式,它可以将一个状态机的数据和算法表示为c语言的结构体以及函数。

通过使用状态机c语言,可以更加有效和可靠地构建状态机,从而使复杂的系统更加容易维护和理解。

状态机c语言提供了一种非常灵活的机制,它可以帮助我们更好地控制系统的行为。

它可以使状态机更容易编写和理解,并且可以提高系统的可靠性。

此外,它可以简化状态表设计,使得用状态机构建的系统更容易维护和管理。

状态机c语言可以在很多方面帮助我们构建和管理复杂的系统。

它可以使状态机更容易编写和理解,可以显著减少状态表设计。

它可以使系统更加可靠,更容易维护和管理。

此外,它可以简化状态表设计,使得用状态机构建的系统更容易维护和管理。

C语言的状态机实现方式可以使用多种形式,如:状态表、状态函数、事件函数等。

状态表是一种常见的实现方式,它通过使用二维的表格来描述状态转换的过程,以及在不同状态之间发生什么样的事件。

状态函数是另一种实现状态机的方式,它通过在每一个状态之后定义一个函数来控制状态转换,以及在不同状态之间发生什么样的事件。

而事件函数是一种可以抽象描述状态转换的方式,它可以把不同的事件统一到一个函数中,并在函数中对各种事件进行判断和处理,从而实现状态机的功能。

状态机c语言在当今的软件开发中扮演着重要的角色,它可以更好地控制复杂系统的行为,使得系统更容易维护和理解,从而提高软件的可靠性和性能。

状态机c语言不仅可以用于实际的软件开发,而且也可以用于学术研究中,通过将状态机的概念和算法应用于实际的编程,可以更加深入地理解状态机的工作原理,从而更好地提升自己的技术能力。

状态机分层 c语言

状态机分层 c语言

状态机分层什么是状态机?状态机是一种数学模型,用于描述系统的行为。

它由一组状态、转移条件和动作组成。

状态表示系统所处的情况,转移条件表示状态之间的关系,动作表示状态转移时执行的操作。

在计算机科学中,状态机被广泛应用于软件开发和硬件设计中。

它能够清晰地描述系统的行为,帮助开发人员更好地理解和实现系统逻辑。

C语言中的状态机在C语言中,我们可以使用条件语句和循环语句来实现状态机。

通过不同的条件判断和循环控制,我们可以实现不同状态之间的转移和动作的执行。

C语言中的状态机通常使用switch语句来实现。

switch语句根据表达式的值,选择执行与之匹配的case语句,从而实现不同状态之间的转移和动作的执行。

以下是一个简单的示例,展示了如何使用C语言实现一个简单的状态机:#include <stdio.h>enum State {STATE_A,STATE_B,STATE_C};int main() {enum State currentState = STATE_A;while (1) {switch (currentState) {case STATE_A:printf("In State A\n");// 执行状态A的动作currentState = STATE_B; // 状态转移break;case STATE_B:printf("In State B\n");// 执行状态B的动作currentState = STATE_C; // 状态转移break;case STATE_C:printf("In State C\n");// 执行状态C的动作currentState = STATE_A; // 状态转移break;default:printf("Invalid state\n");break;}}return 0;}在上面的示例中,我们定义了一个枚举类型State,表示状态机的不同状态。

状态机分层 c语言

状态机分层 c语言

状态机分层 c语言状态机是一种常用的软件设计工具,它被广泛应用于各种领域,包括嵌入式系统、通信协议、自动控制等等。

在C语言中,我们可以通过编写代码来实现状态机,以便有效地描述和管理系统的各种状态和转换。

首先,我们需要了解什么是状态机。

状态机是由一组状态和状态之间的转换组成的模型。

在状态机中,每个状态代表着系统所处的一种状态或情况,而状态之间的转换则表示系统在不同状态之间的切换。

通过定义状态和转换,我们可以清晰地描述系统在各种情况下的行为。

在C语言中,我们通常会使用枚举类型来定义不同的状态。

例如,我们可以定义一个枚举类型来表示系统的状态,如下所示:```cenum {STATE_IDLE,STATE_RUNNING,STATE_PAUSED,STATE_ERROR};```在这个例子中,我们定义了四个状态:空闲、运行、暂停和错误。

每个状态都对应着系统的一种运行情况。

接下来,我们需要定义状态之间的转换。

在C语言中,我们可以使用条件语句(如if语句或switch语句)来实现状态之间的转换。

例如,我们可以使用switch语句来处理系统在不同状态下的不同行为,如下所示:```cswitch (state) {case STATE_IDLE:// 处理空闲状态下的行为break;case STATE_RUNNING:// 处理运行状态下的行为break;case STATE_PAUSED:// 处理暂停状态下的行为break;case STATE_ERROR:// 处理错误状态下的行为break;default:// 处理未知状态下的行为break;}```通过使用条件语句,我们可以根据当前的状态来执行相应的行为。

这样,我们就可以根据系统的状态来实现不同的功能和逻辑。

在实际应用中,状态机还可以进一步分层。

我们可以将状态机分成多个层次,每个层次对应着系统的不同功能或模块。

通过分层,我们可以更好地组织和管理状态机,使其更加清晰和可维护。

C语言异步编程详解

C语言异步编程详解

C语言异步编程详解异步编程是一种在计算机科学中常用的编程模式,它允许同时执行多个任务,提高程序的并发性和响应速度。

C语言作为一种通用的高级编程语言,也有自己的异步编程方式。

本文将详细介绍C语言中的异步编程方法和技巧。

一、异步编程的概念和优势异步编程是一种非阻塞式的编程模式,意味着程序在等待某个任务完成时不会被阻塞,而是会继续执行其他任务。

这种方式可以提高程序的效率和性能,特别适用于处理大量的IO操作和并发任务。

在传统的同步编程中,程序需要等待每个任务完成才能继续执行下一个任务,这样会导致程序的响应速度变慢。

而异步编程则能够在等待某个任务完成的同时,继续执行其他任务,从而提高了程序的并发性和响应速度。

二、C语言中的异步编程方法在C语言中,异步编程可以通过以下几种方法实现。

1. 回调函数(Callback)回调函数是一种常见的异步编程技术,它允许在某个任务完成后自动调用指定的函数。

在C语言中,可以通过注册回调函数的方式实现异步操作。

下面是一个简单的示例,演示了如何使用回调函数实现异步编程:```c#include <stdio.h>void asyncOperation(void (*callback)(void)) { // 模拟异步操作printf("正在执行异步操作...\n");// 模拟异步操作完成后的回调callback();}void callback() {printf("异步操作已完成\n");}int main() {asyncOperation(callback);// 执行其他任务printf("继续执行其他任务...\n");return 0;}```在上面的示例中,`asyncOperation`函数模拟了一个异步操作,在操作完成后调用了注册的回调函数`callback`。

通过这种方式,程序可以在等待异步操作完成时继续执行其他任务,而无需等待异步操作的完成。

编程思想 总结 状态机

编程思想 总结 状态机

编程思想总结状态机状态机(State Machine)是一种常见的编程思想,它将程序的运行过程分解为一系列离散的状态,并定义了状态之间的转换条件。

状态机的核心思想是在不同的状态下执行不同的操作,根据输入或者事件将程序的状态从一个状态转换为另一个状态。

状态机通常包含以下几个要素:1. 状态(State):程序运行时所处的特定状态。

每个状态都有固定的行为和特性。

2. 事件(Event):触发状态转换的输入或者条件。

当某个事件发生时,状态机将根据当前状态以及事件的类型执行相应的动作。

3. 转换条件(Transition):决定状态机从一个状态转换到另一个状态的条件。

当满足转换条件时,状态机将执行相应的状态转换操作。

4. 动作(Action):状态转换时执行的操作或者行为。

动作可以是一段代码逻辑,也可以是调用其他函数或者方法。

根据状态机的特点和应用场景,可以将状态机分为以下几种类型:1. 简单状态机(Simple State Machine):也称为有限状态机,只有有限个状态和转换条件。

每次只在一个状态之间转换,不涉及并发和并行操作。

2. 层次状态机(Hierarchical State Machine):状态之间可以存在层次关系,一个状态可以包含多个子状态。

状态之间的转换可能涉及到多层次的状态切换。

3. 并发状态机(Concurrent State Machine):多个状态之间可以并行执行,相互之间没有依赖关系。

每个状态可能独立地进行状态转换。

状态机的优点有:1. 结构清晰:将复杂的程序逻辑分解成多个离散的状态,易于理解和维护。

2. 灵活性强:可以根据实际需求定义不同的状态和状态转换条件,适应不同的应用场景。

3. 可扩展性好:可以随时添加新的状态或者修改已有的状态转换条件,不影响其他部分的代码。

4. 并发执行:并发状态机可以实现多个状态的并行执行,提高程序的处理效率和响应速度。

状态机的缺点有:1. 复杂度高:状态机需要定义多个状态和状态转换条件,可能会增加代码的复杂度和工作量。

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

项目4简易数字钟的设计(2)计算机专业有门必修课程叫“软件工程”,这门课程告诉软件学习者们如何系统性的、规范化的、可定量的过程化方法去开发和维护软件。

我们在学习单片机编程的过程当中,也应该借鉴“软件工程”课程当中的讲述的方法和手段,去维护和规范我们的单片机程序。

在本单元当中,我们安排了4个任务。

任务1介绍了一种基于状态机的程序框架,通过状态机的学习,初学者可以写出思路清晰、多任务运行流畅的程序。

任务2介绍了程序的风格和可移植性,规范了变量和函数等的命名,并简单介绍了C51中提高程序可移植性的方法。

任务3介绍了程序模块化的实现方法,让初学者学会合理的管理程序。

任务4中运用本单元所讲的知识,结合前一单元,完成简易数字钟的设计。

【内容安排】4.1 基于状态机的程序框架4.2 程序的风格和可移植性4.3 程序的模块化4.4 简易数字钟的设计任务4.1 基于状态机的程序框架4.1.1 任务介绍上一单元中已经多次提到多任务运行时,延时函数(DelayMs())对程序的危害性,堵塞CPU,系统任务的实时性得不到有效的保证。

在3.4节中,提到中断可以提高任务的实时性,但是单片机的中断数量是有限的,不可能每一个任务都有中断。

在 3.5节中,通过定时器中断服务函数提供的时标信号,定时扫描LED和数码管,可以消除延时函数,时标信号给我们提供了一种新的思路来消除延时函数(本质上还是借助于中断)。

但是LED闪烁和动态数码管扫描都是属于状态时间分配均匀的(LED闪烁有两个状态,亮和灭分配时间相等;数码管每个位扫描的时间也相等),程序易于实现。

对于像按键检测这样的(时间分配不均匀的)任务,怎样来消除程序中的延时呢?本节任务是:利用本节所讲“状态机”,改写独立按键程序,并增加“长按”、“连击”等功能。

4.1.2 知识准备1、状态机的思想网络上经常报道特级象棋大师车和多人一起下象棋,采用的方式是“车轮战”。

车轮战有两种方式:(1)象棋大师先和甲开始下象棋,直到有了结果,然后才轮到乙和象棋大师对阵,下完了之后,然后是丙......,一直到和最后一个人下完。

(2)象棋大师先和A下一步棋,然后再和B下一步棋,然后再和C,和......,和所有人下完一遍后,再回头从A开始,一个人接一个人。

很显然“车轮战”的第1种方式效率不如第2种方式效率高,报道上的“车轮战”也是指的第2种方式。

原因在于象棋大师的水平远远高于其他人,如果采用第一种方式,象棋大师下一步棋很快,甲需要考虑很长时间才能落子,象棋大师在和甲下棋的过程中,其他人只能等待。

如果采用第二种方式,象棋大师和甲只下一步棋,然后再和乙也下一步棋,和所有人下完一步棋之后,再从甲开始,这样看起来是所有人都在下象棋,效率自然远高于第一种方式。

“车轮战”的第2种方式,实际上就是程序中状态机的基本原理。

程序中的多个任务可以看成是其他棋手,CPU是象棋大师,CPU在执行多个任务时,不再是先执行任务1,执行完任务1后,再执行任务2,而是把每个任务又划分出多个小任务(小任务中没有时间等待),CPU每次只执行每个任务中的小任务,执行完任务1中的一个小任务后,然后快速转向任务2中的小任务,按照这种模式轮询下去,由于CPU很快(象棋大师),整个程序中的任务都得到了实时的执行。

任务中的小任务是按照任务的状态来划分的,故称为“状态机”。

上一单元中,利用定时器的时标信号扫描动态数码管的程序实际上也是采用了状态机的原理。

时标信号到来后,CPU扫描1位数码管,然后去执行别的任务,下一个时标信号到来后,再扫描下一位数码管。

6位数码管的扫描被分成了6个子任务,CPU每一次只执行一个子任务。

2、任务的划分数码管扫描的任务划分非常简单,因为每一个子任务执行的时间时均匀的,而且任务很相似。

但是程序中大多数任务划分出来的子任务时间分布不均匀,而且划分出来的子任务不相似。

举个例子,2个LED,第一个LED按照亮1秒,灭2秒的方式闪烁,第2个LED按照亮2秒,灭1秒的方式闪烁,要求不用延时函实现。

我们先给出程序,通过程序学习状态机的实现方法。

#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit LED1=P1^0; //第一个LED1接口定义sbit LED2=P1^1; //第二个LED2接口定义bit FlagSystem1Ms=0; //系统1ms时标信号//定时器0初始化void Timer0Init(){TMOD=0x02; //GATE=0,C/T=0,M1M0=02;TH0=56; //高8位RAM赋值TL0=56; //低8位RAM赋值,200us定时ET0=EA=1; //开定时器中断和总中断 TR0=1; //开启定时器}//第一个LED以亮1秒,灭2秒的方式闪烁void Led1Twinkle(){static uchar Led1State=0; //状态机变量1static uchar Led1Cnt=0; //计数变量1swithch(Led1State){case 0: //LED1亮状态{LED1=0;if(++Led1Cnt>=1000) //LED1亮1秒后,跳转到灭状态{Led1Cnt=0;Led1State=1;}}break;case 1: //LED1灭状态{LED1=1;if(++Led1Cnt>=2000) //LED1灭2秒后,返回到亮状态 {Led1Cnt=0;Led1State=0;}}break;}}//第二个LED以亮2秒,灭1秒的方式闪烁void Led2Twinkle(){static uchar Led2State=0; //LED2状态机变量static uchar Led2Cnt=0; //LED2计数变量swithch(Led2State){case 0: //LED2亮状态{LED2=0;if(++Led2Cnt>=2000) //LED2亮2秒后,跳转到灭状态 {Led2Cnt=0;Led2State=1;}}break;case 1: //LED2灭状态{LED2=1;if(++Led2Cnt>=1000) //LED2灭1秒后,返回到亮状态 {Led2Cnt=0;Led2State=0;Led2State=1;}}break;case 1: //LED2灭状态{LED2=1;if(++Led2Cnt>=1000) //LED2灭1秒后,返回到亮状态 {Led2Cnt=0;Led2State=0;}}break;}}//主函数void main(){TimeriInit(); //定时器0初始化while(1){if(FlagSystem1Ms==1) //间隔1ms轮询系统任务{FlagSystem1Ms=0;Led1Twinkle(); //任务1Led2Twinkle(); //任务2}}}//定时器0中断服务函数,提供2ms的时标信号void timer0_intr(void) interrupt 1{static uchar Cnt200us=0; //200us计数变量if(++Cnt200us>=5) //0.2ms*5=1ms{Cnt200us=0; //清空计数变量FlagSystem1Ms=1; //1ms时标信号置位}}整个程序的框架思路清晰,定时器0产生1ms时标信号供主函数使用,主函数每间隔1ms 执行任务1和任务2。

任务1和任务2实现内容类似,下面我们分析任务1的内容。

任务1中的Led1Twinkle()函数是通过状态机完成的,状态机由switch-case语句构造。

在程序中先定义状态机变量(Led1State,静态局部变量),并赋初值0,以及时间计数变量(Led1Cnt)。

LED1的状态为亮1秒,灭2秒,分2个状态,所以switch-case语句中对应LED1的两个状态有两个case分支,状态机变量(Led1State有2个值,分别为0和1。

系统上电运行,1ms时标到来,第一次执行任务1,由于Led1State初值为0,则进入到第一个分支,在case语句中,CPU只执行两条语句:点亮LED1;让计数变量加1(Led1Cnt=1),并判断是否等于1000,如果不是则直接跳出switch-case语句(break不可以忽略),任务1执行完毕,然后再执行任务2。

下一个1ms再到来,再进入第一个分支,计数变量再加1(Led1Cnt=2),再退出,时标信号到来,计数变量再加1,一直循环下去...。

直到计数变量满足了大于等于1000的条件,则计数变量置0,并把状态机变量置1(LedState=1),指向第二个分支,退出任务。

下一个1ms再次到来时,进入任务1后,根据状态机变量的值,进入到程序的第二个分支,熄灭LED1,重新对计数变量计数,接下来的程序运行模式和第一个分支是一样的。

总结:“状态机”的思想实际上是把系统所有任务按照任务的状态划分出多个子任务,以时标信号为基准,主程序不停的轮询各任务中的子任务。

子任务之间的跳转依靠计数变量计数或者某些状态量的改变。

3、基于状态机的按键检测上一单元中的独立按键的扫描程序如下:if(KeyInput==0) //检测到按键按下{DelayMs(10); //延时消抖if(KeyInput==0) //再次检测按键是否按下{DispBuffer[0]=DispCnt/10;DispBuffer[1]=DispCnt%10;if(++DispCnt>=100) //每按一次,计数器加1,超过DispCnt=0;while(!KeyInput); //等待按键释放}}}在按键的扫描程序中,存在着DelayMs()延时堵塞主程序,比延时更堵塞系统的是等待按键释放语句:while(!KeyInput); 按键从按下到弹起最小也得几百个ms,程序执行到这一步的话,程序指针长时间停留在等待释放语句上,严重阻碍了其它任务的执行。

总之,这种简单的按键检测方法作为基础学习和简单系统中可以用,但实际产品中,有很大的缺陷和不足。

在实际产品中,基于状态机的按键效率更高,功能强大。

图4.1.1是基于状态机的独立按键检测的状态转换图,根据按键检测三部曲,分为三个状态。

“状态0”为初次检测按键按下状态。

系统由定时器产生的时标信号来驱动每隔10ms检测按键有没有被按下,如果没有检测到按键按下时,状态机中的状态就会一直停留在“状态0”上,如果检测到按键按下,则将状态变量指向“状态1”。

“状态1”是按键消抖状态。

在“状态0”中首次检测到按键按下后,将状态机变量指向“状态1”,下一个10ms到来后,进入到“状态1”中(10ms消抖延时是通过定时器来完成的)。

相关文档
最新文档