任务4.1 基于状态机的程序架构
车载供氢系统控制器开发

车载供氢系统控制器开发叶川;马天才;陈翌;杨柳明【摘要】针对某燃料电池客车35 MPa气态储氢系统的控制器进行了设计开发.根据燃料电池客车供氢系统的需求,对控制器的MCU、电源、信号处理、驱动输出、CAN通讯等模块进行了硬件设计,基于状态机和任务调度模式完成了控制器软件的开发,实现了供氢系统温度、压力、环境氢气浓度等信号的检测功能,且能够与燃料电池发动机控制器通过CAN总线通讯并对高压氢气瓶阀进行控制.此外,软件采用的模块化设计处理手段提高了控制器针对不同应用场景的可移植性.【期刊名称】《汽车技术》【年(卷),期】2019(000)002【总页数】5页(P48-52)【关键词】燃料电池客车;车载供氢系统;控制器【作者】叶川;马天才;陈翌;杨柳明【作者单位】同济大学,上海 201804;同济大学新能源工程中心,上海 201804;同济大学,上海 201804;同济大学新能源工程中心,上海 201804;同济大学,上海 201804;同济大学,上海 201804;同济大学新能源工程中心,上海 201804【正文语种】中文【中图分类】U469.7;TB471 前言由于能源与环境问题日益突出,传统内燃机汽车难以将排放降低到理想范围[1,2]。
燃料电池是一种高效、清洁的电化学发电技术,近年来成为最有可能替代传统发动机技术的先进新能源汽车技术[3]。
供氢系统为燃料电池发动机系统的关键组成部分,车载储氢多采用高压气态储氢,压力在20~70 MPa范围内[4]。
目前车载供氢系统缺乏国内统一标准,据了解国内大多数供氢系统的控制被集成在燃料电池发动机控制器(FCU,Fuelcell Con⁃trol Unit)中,导致FCU与供氢系统耦合过强,系统的移植性、兼容性较差。
特别对于大型客车而言,供氢系统氢瓶大多设置在车辆顶部,导致线束过长、线束过重等问题。
近年来,相关人员针对车载供氢系统进行了研究与开发,如,吴兵等人[4]在供氢系统设计中提出了HMS(氢管理系统)的使用,但是仅针对特定供氢系统,并没有进行分布式设计;全书海等人[5]基于PIC18F258单片机设计了用于供氢系统的控制器,但是缺少针对不同供氢系统的兼容性和可移植性的设计,实际运用场景较为局限。
基于状态机的充电桩控制系统设计

[1.42,1.43] PWM6V
[1.38,1.39] PWM9V
[1.34,1.35] PWM12V
其他
无
本系统设计基于UCOSII实时操作系统,共使
用了 7个任务,所有的功能都是在任务中完成,为
保证任务的独立运行每个任务都有自己的堆栈
区,任务的各种参数(如表2所示)由任务控制块
进行记录,其中有三个最重要的参数:任务函数指
案,以解决充电桩的安全问题⑵;邵伟伟研究了充 电桩的效能问题,采用V2G技术提出太阳能与电 网结合的充电桩方案设计,解决充电桩效能问 题⑶;吴锤等研究了有限状态机分类、设计流程、 设计思想和电路实现;陈改霞等研究了小型燃 煤锅炉的工作原理,基于有限状态机思想以单片 机为主控制器设计了一种智能锅炉控制器,实现 锅炉的温度、液位等信息的采集与控制⑷;莫建麟 等研究了基于卷积神经网络的嵌入式系统图像分 类算法,为嵌入式系统设计提供可借鉴参考案 列切,张思聪等研究了系统远程升级问题,基于 IAP原理提出了一种以STM32为控制器的充电桩 系统远程升级方案设计,可有效解决系统远程升 级问题囲。刘建梁等研究了三相交流电进行电动
等研究了电动车充电桩的安全问题,提出了一种 基于MSP430单片机为核心的交流充电桩设计方
车充电的优点,提出了一种基于STM32的三项交 流电充电桩设计方案,解决充电桩效率问题⑼;刘
作者简介:肖连军,硕士,讲师,合肥学院人工智能与大数据学院。研究方向:控制理论与控制技术研究。 张鸿恺,硕士,讲师,安徽建筑大学电子与信息工程学院。研究方向:控制理论与控制技术研究。
图3控制系统结构图 2.1 RFID接口设计
系统设计采用射频IC卡存储用户ID和数据, 用户通过在阅读器上刷卡实现身份识别并对充电 桩控制系统进行控制,阅读器与主mcu的 PB12-PB15通过接口相连,通信方式为SPI,其中 RHD_SDA为阅读器数据信号,接主mcu的PB12, RFID_SCLK为阅读器的时序信号,接主mcu的
有关FPGA的毕业论文---精品模板

天津工业大学毕业设计(论文)基于FPGA的LCD显示控制系统的设计姓名:马震院(系)别: 信息与通信工程学院专业: 电子信息工程班级:电子061指导教师:周勇职称:讲师2010年 6 月13 日天津工业大学毕业设计(论文)任务书院长教研室主任指导教师毕业设计(论文)开题报告表天津工业大学毕业设计(论文)进度检查记录天津工业大学本科毕业设计(论文)评阅表摘要本课题主要任务是设计基于FPGA的LCD控制器,兼顾好程序的易用性,以方便之后模块的移植和应用。
本课题的设计采用了带ST7920驱动的12864-12的液晶模块,并使用Xilinx公司的spartanII系列的XC2STQ144来作为核心的控制器。
控制器部分采用VHDL语言编写,主体程序采用了状态机作为主要控制方式。
ST7920是一种内置128x64-12汉字图形点阵地液晶显示控制模块,用于显示汉字和模型。
最后实现使用FPGA在LCD上的任意位置显示任意的16*16像素的中文字符以及16*8的英文字符,另外要能根据输入数据的变化同步变化LCD上显示的内容.同时要能将储存模块中的图片数据正常地显示在LCD上。
该课题的研究将有助于采用FPGA的系列产品的开发,特别是需要用到LCD 的产品的开发。
同时可以大大缩短FPGA的开发时间。
另外,由于模块的易用性,也将使得更多的采用FPGA的产品之上出现LCD,增加人机之间的交互性,为行业和我们的生活带来新的变化。
关键词:ST7920;12864—12 ;VHDL;FPGA ;LCDABSTRACTIn this project, the main object is to design a LCD controller based on FPGA,and at the same time emphasize on the convenience for the later application and migration. In this project, This topic is designed with a belt—driven 12864—12 ST7920 LCD module, and use the Xilinx's spartanII series XC2STQ144 as the core of the controller。
嵌入式系统应用程序方案之一——基于事件驱动的应用程序框架

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

转换(Transition)
在状态转换时执行的操作或命令,可以是 输出信号、内部变量赋值或调用其他程序 等。
从一个状态到另一个状态的过渡过程,由事 件触发并执行相应的动作。
02 SFC系统架构与组成
整体架构概述
SFC(Service Function Chaining)系统是一种网络服务架构,旨在通过将一系 列网络功能(如防火墙、负载均衡器、深度包检测等)链接起来,为用户提供定 制化的网络服务。
某大型互联网公司采用SFC技术,成功构建了高 效、安全的数据中心网络,显著提升了网络性能 和安全性。
案例二
一家跨国企业利用SFC实现企业网络的优化,通 过灵活的服务链部署,满足了不同业务部门的网 络需求。
案例三
某5G运营商运用SFC支持网络切片,为不同行业 客户提供了高质量的定制化网络服务。
未来发展趋势预测
SFC系统架构包括三个主要组成部分:分类器、服务功能链和服务功能。其中, 分类器负责识别和分类网络流量,将其导向相应的服务功能链;服务功能链则定 义了一系列网络功能的处理顺序;服务功能则是实现各种网络功能的实体。
关键组件功能介绍
01
分类器(Classifier):负责根据预设 规则对网络流量进行分类,将不同类 别的流量导向相应的服务功能链。分 类器可以实现基于五元组(源IP、目 的IP、源端口、目的端口、协议类型 )的流量分类,也可以支持更复杂的 分类算法。
。
数据备份与恢复
定期备份重要数据,确保数据 安全,同时制定数据恢复计划
以应对可能的数ቤተ መጻሕፍቲ ባይዱ丢失。
日志监控与分析
收集、分析系统日志,发现潜 在问题,提前预警。
性能优化策略分享
优化数据库性能
图解FreeRTOS 原理系列之任务管理器基本框架

内核任务管理器需求先来对比一下裸奔系统与RTOS应用系统的编程模型,看看两种编程的不同画风。
裸奔系统在不用RTOS的单片机应用开发时,编程模型大概是这样的画风:•程序的主体是一个死循环,该应用程序由一系列协同工作的函数片段组成,相互实现逻辑配合,实现用户业务需求。
该应用程序独占单片机,常规的单片机系统都仅有有一个计算单元核。
•普通外设I/O,这里所说I/O是指广义的I/O,比如GPIO、PWM、ADC、DAC、LCD显示(当然这里并不严谨,比如ADC,DAC、LCD等也可以产生中断)等。
中断函数将异步事件接收成或报文或标志或数值,在与主循环发生逻辑关联。
•中断外设,比如UART、USB、I2C、定时器、DMA等根据应用需求而使用的中断。
这些中断都需要相应的中断函数进行处理异步中断事件。
对于输出可能采样主动输出,一般由主循环某一个动作执行;对于输入设备或许采用轮询方式,在与主循环进行耦合。
RTOS应用系统在一个基于RTOS应用系统中,其编程模型大致是下面这样一个画风,有多个并行的任务在相对长的宏观时间维度看起来,多个任务是并行运行的,但对于常规单片机而言(一般都是单核),任一时刻只有一个任务或中断函数在独占CPU核。
•常见的RTOS没有设备驱动模型,没有对外设设备进行抽象,中断函数将会由用户或调用RTOS 机制,比如event/signal等与任务进行通信•任务间还有可能需要通信,或传递消息,或完成某项需求相互间需要同步等•同样任务需要与硬件普通IO外设进行打交道,或入或出。
但有可能是这个任务实现,也有可能是哪个任务执行。
完全取决于开发人员如何设计。
•RTOS实现任务的切入切出,切入使某任务运行;切出使某任务挂起,出让CPU,暂停运行。
•RTOS充当底层支持功能,RTOS还提供丰富的时间管理,队列、邮箱等机制供应用开发使用。
对于单片机而言,一般只有一个核,所有RTOS为了方便理解,可以看成是最最主要的目就是通过软件方法将硬件CPU核程序运行环境抽象为每一个应用任务虚拟出一个软核。
南理工考研软件工程复习资料:提要与习题3(答案)

习题参考答案【3-1】从下列有关系统结构图的叙述中选出正确的叙述。
(1) 系统结构图中反映的是程序中数据流的情况。
(2) 系统结构图是精确表达程序结构的图形表示法。
因此,有时也可将系统结构当作程序流程图使用。
(3) 一个模块的多个下属模块在系统结构图中所处的左右位置是无关紧要的。
(4) 在系统结构图中,上级模块与其下属模块之间的调用关系用有向线段表示。
这时,使用斜的线段和水平、垂直的线段具有相同的含义。
〖解〗(4)分析:系统结构图反映的是系统中模块的调用关系和层次关系,谁调用谁,有一个先后次序(时序)关系。
所以系统结构图既不同于数据流图,也不同与程序流程图。
数据流图仅描述数据在系统中如何流动,如何处理和存储,它不考虑时序关系。
图中的有向线段表示了数据流。
程序流程图描述程序中控制流的情况,即程序中处理的执行顺序和执行序列所依赖的条件,图中的有向线段(流线)表示的是控制流,从一个处理走到下一个处理。
但在系统结构图中的有向线段表示调用时程序的控制从调用模块移到被调用模块,并隐含了当调用结束时控制将交回给调用模块。
如果一个模块有多个下属模块,这些下属模块的左右位置可能与它们的调用次序有关。
例如,在用结构化设计方法依据数据流图建立起来的变换型系统结构图中,主模块的所有下属模块按逻辑输入、中心变换、逻辑输出的次序自左向右一字排开,左右位置不是无关紧要的。
所以只有最后的一个叙述是正确的。
【3-2】软件的开发工作经过需求分析阶段,进入( A )以后,就开始着手解决“怎么做”的问题。
常用的软件设计方法有( B )、( C )、( D )和( E )等方法。
供选择的答案:A ~ B.①程序设计②设计阶段③总体设计④定义阶段⑤SD方法⑥SP方法C. ①Jackson方法②瀑布法③快速原型法④回溯法D ~ E. ①LCP(Wanier)方法②递归法③Parnas方法④自下而上修正⑤逐步求精法⑥检测校正法〖解〗A. ②, B. ⑤, C. ①, D. ①, E. ③。
2019国开电大《程序设计基础》形考任务4答案

二、选择题(每题4分,合计40分)
2下列叙述中正确的是
选择一项:
C
A.算法就是程序
B.设计算法时只需要考虑结果的可靠性
C.以上三种说法都不对
D.设计算法时只需要考虑数据结构的设计3下列叙述中正确的是
选择一项:
B. 以上三种说法都不对
选择一项:
A.数据比较
B.算术运算
C.逻辑运算
D.循环结构
7在求解规模较大的问题时,可以把它分解成若干个规模较小的子问题,求出各个子问题的 解之后,再把这些解合成原问题的解,这种方法是()。
选择一项:
A.穷举法
B.回溯法
C.递归法
D.分治法
8当一个算法输入不合法的数据时,应当能够作适当处理,不致于引起严重后果,这属于算 法的()。
4一个算法应该具有“确定性”等5个特性,下面对另外4个特性的描述中错误的是()
选择一项:
A.有零个或多个输入
B.可行性
C.有穷性
D.有零个或多个输出5下面叙述正确的是()。
选择一项:
A.算法的时间复杂度是指执行算法所需要的计算工作量
B. 算法的效率只与问题的规模有关,而与数据的存储结构无关
D.算法的时间复杂度与空间复杂度一定相关6那一项不属于算法的四种基本的功能操作()。
1.算法的四种基本操作是逻辑运算、算数运算、数据比较、数据传送。
2.算法的控制结构有三种基本形式:顺序结构、选择结构、循环结构。
3.评价算法需要从几个不同的角度考虑,最主要的是正确性和运行效率。
4.算法的运行效率包括两方面,算法的时间复杂度和算法的空间复杂度。
5.结构化程序设计的总体思想是采用模块化结构,自顶向下、逐步求精。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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消抖延时是通过定时器来完成的)。