0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于状态机和面向对象的思想设计按键检测模块

工程师进阶笔记 来源:工程师进阶笔记 2024-11-14 11:44 次阅读

物理按键,在很多嵌入式产品里面应用得非常广泛,很多嵌入式软件工程师在刚刚开始入门的时候,点完灯之后就开始学习按键输入检测。按键输入可以说是继点灯之后,又一经典的嵌入式入门必学内容之一。 在很多嵌入式入门学习的教程里面,按键原理普遍被认为是“很简单”的知识点之一,按键输入检测的原理,无非就是通过CPU不断扫描按键引脚的电平状态,或者采用单片机引脚外部中断方式,然后在死循环或者中断服务程序里面处理按键被按下后的逻辑。 然而,在这个“很简单的高低电平检测”的原理背后,通过产品经理给物理按键各个动作赋予的(难以理解的)意义,一个小小的物理按键开始变得复杂起来,这些动作包括:按下、抬起、单击、双击、点动、长按、组合按键。。。等等。 以上这些复杂的按键动作,已经不是一个“简单的高低电平检测”所能描述清楚的了,成熟的单片机按键检测模块,必须能很好地处理以上按键动作,并且具有很高的内聚度,与单片机的底层引脚尽量低耦合,且能提供灵活的应用层调用接口。 采用嵌入式 C 语言面向对象的思想,通过状态机和回调函数的方式,我们来编写一个通用的按键检测模块,以更好地覆盖单片机的物理按键应用场合。

以下是物理按键模块的设计过程。

1、这个通用的物理按键模块,主要是由4个源代码文件组成,key_driver.c和key_driver.h主要是驱动层接口,主要面向不同的单片机引脚适配。key_module.c和key_module.h主要是面向应用层接口,与芯片硬件引脚无关。

1ddeec5c-906b-11ef-a511-92fbcf53809c.jpg

2、key_driver.c 和 key_driver.h主要是用来适配不同的单片机GPIO外设的,在key_driver.h里面,声明了一个key_driver_t类型的结构体,主要提供GPIO引脚初始化接口以及引脚电平读取接口,如下图所示。

1de7b116-906b-11ef-a511-92fbcf53809c.jpg

3、在key_driver.c里面,主要是对初始化接口和引脚电平读取接口的具体实现,比如,引脚初始化接口_init()函数和电平读取接口_read_pin_state(),其具体实现如下图所示。

1dee39f0-906b-11ef-a511-92fbcf53809c.jpg

4、在key_driver.c里面,定义了一个key_driver结构体变量,记住这个变量,很重要,后面会被key_module进行调用,key_driver的具体内容如下图所示。

1e11f39a-906b-11ef-a511-92fbcf53809c.jpg

5、在key_module.h里面,主要是声明了两个重要的结构体,key_t结构体是面向单个按键对象的,主要是包括按键ID以及按键状态枚举,还有一些变量是用来进行按键检测过程的,key_manager_t结构体主要是用来管理多个按键对象的,包括各个按键动作的函数接口,还有按键引脚的驱动程序,如下图所示。

1e1630f4-906b-11ef-a511-92fbcf53809c.jpg

6、按键模块还对外提供了多个外部调用接口,包括模块初始化,按键模块时间更新,按键模块的时基更新,按键模块的按键动作回调函数处理,如下图所示。

1e1a5652-906b-11ef-a511-92fbcf53809c.jpg

7、在key_module.c里面,主要是对以上外部接口的具体实现,比如,key_module_init()主要是对按键模块的各个参数初始化,以及注册按键模块的引脚驱动程序,代码如下图所示。

1e24c740-906b-11ef-a511-92fbcf53809c.jpg

8、在key_module_update()函数里面,主要是以状态机和回调函数的方式,处理各个按键状态和动作,按键状态有KEY_IDLE、KEY_PRESSED、KEY_RELEASED、KEY_SINGLE_CLICK、KEY_DOUBLE_CLICK、KEY_LONG_PRESS。代码如下图所示。

1e2932e4-906b-11ef-a511-92fbcf53809c.jpg

9、在各个不同的状态里面,通过回调函数的方式,分别对按下、抬起、单击、双击、长按、等按键动作进行处理,限于篇幅,这里只列出部分代码,具体实现请参考具体源码和注释。

1e418c0e-906b-11ef-a511-92fbcf53809c.jpg

10、按键模块需要对其提供系统时基,通常以1毫秒或者10毫秒作为时间基准,key_module_ticks_update()主要是在外部定时器或者外部1毫秒线程中被调用,key_module_set_event_handler()主要是用来设置各个按键状态的回调函数,如下图所示。

1e5838e6-906b-11ef-a511-92fbcf53809c.jpg

11、如何使用key_module?假如项目采用RT-Thread进行调度,在main()函数里面,先创建一个key_module_thread()线程,然后在该线程里面先对按键管理器进行初始化,然后注册各种按键状态的回调函数,最后在while循环里面,更新按键管理器的时基以及状态更新函数,线程主体以1毫秒的间隔进行调度,如下图所示。

1e5e1356-906b-11ef-a511-92fbcf53809c.jpg

12、以上,就是一个通用的单片机按键模块具体设计,通过这个按键检测模块,可以很好地处理各种按键状态事件,并且该按键模块在设计上遵循设备与驱动分离的原则,尽量做到了高内聚低耦合,具体很好的移植性和单片机平台适配性。 13、美中不足的是,这个模块还没有加入组合按键处理,感兴趣的读者,可以下载该模块的源码,对其进行修改和扩展。源码获取请点击【阅读原文】。

-END-

往期推荐:点击图片即可跳转阅读

1e63b892-906b-11ef-a511-92fbcf53809c.jpg

试了一下 GPT-4o,让它帮我分析电路原理图。

1e6f2af6-906b-11ef-a511-92fbcf53809c.jpg

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 状态机
    +关注

    关注

    2

    文章

    492

    浏览量

    27530
  • 按键检测
    +关注

    关注

    0

    文章

    23

    浏览量

    4834

原文标题:基于状态机和面向对象的思想,设计一个通用的按键检测模块。

文章出处:【微信号:工程师进阶笔记,微信公众号:工程师进阶笔记】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    STM32按键消抖——入门状态机思维

    本篇介绍了嵌入式软件开发中常用的状态机编程实现,并通过按键消抖实例,以常用的switch-case形式,实现了对应的状态机编程代码实现,并通过测试,串口打印对应状态,分析
    的头像 发表于 09-02 21:54 4819次阅读
    STM32<b class='flag-5'>按键</b>消抖——入门<b class='flag-5'>状态机</b>思维

    STM32按键状态机2——状态简化与增加长按功能

    本篇继续介绍状态机的使用,在上篇的基础上,通过简化按键去抖逻辑,并增加按键长按功能,进一步介绍状态图的修改与状态机代码的实现,并通过实际测试
    的头像 发表于 09-03 21:26 4106次阅读
    STM32<b class='flag-5'>按键</b><b class='flag-5'>状态机</b>2——<b class='flag-5'>状态</b>简化与增加长按功能

    状态机编程实例-面向对象状态设计模式

    本编介绍了状态机编程的第3种方法——面向对象状态设计模式,通过C++的继承特性,以及类指针,实现炸弹拆除小游戏中的状态机功能。
    的头像 发表于 06-28 09:04 1508次阅读
    <b class='flag-5'>状态机</b>编程实例-<b class='flag-5'>面向</b><b class='flag-5'>对象</b>的<b class='flag-5'>状态</b>设计模式

    玩转Spring状态机

    说起Spring状态机,大家很容易联想到这个状态机和设计模式中状态模式的区别是啥呢?没错,Spring状态机就是状态模式的一种实现,在介绍S
    的头像 发表于 06-25 14:21 934次阅读
    玩转Spring<b class='flag-5'>状态机</b>

    状态机编程

    状态机编程基于状态机按键输入软件接口设计一般的教课书中给出的按键输入软件接口程序通常非常简单,在程序中一旦检测
    发表于 07-10 18:00

    你真的知道面向过程和面向对象的区别吗?精选资料分享

    在面试时经常会被问到面向过程和面向对象有什么区别,虽然都是编程的一种思想,但是他们的侧重点不同,我们从以下几个方面进行简单总结。1. 面向
    发表于 07-21 08:53

    利用状态机按键消抖程序

    利用状态机按键消抖程序讲解,很好的资料下载吧。
    发表于 01-11 09:32 30次下载

    嵌入式软件中状态机的抽象与实现

    文中提出了 在嵌入式软件中把状态机作为一个独立模块从控制模块中抽象出来的思想 , 描述了 抽象出来的状态机
    发表于 03-22 15:47 1次下载

    基于状态机的单片按键短按长按功能的实现

    本文主要介绍了基于状态机的单片按键短按长按功能的实现,按键的击键过程也是一种状态的切换,也可以看着是一个
    发表于 12-28 08:43 1.9w次阅读
    基于<b class='flag-5'>状态机</b>的单片<b class='flag-5'>机</b><b class='flag-5'>按键</b>短按长按功能的实现

    面向过程和面向对象有什么区别

    面向过程(pop)和面向对象(oop)是什么  1. pop(Process-oriented programming)的缩写,“面向过程”是一种是事件为中心的编程
    发表于 05-13 18:12 2次下载
    <b class='flag-5'>面向</b>过程<b class='flag-5'>和面向</b><b class='flag-5'>对象</b>有什么区别

    C++语言和面向对象程序设计教程

    章至第11章介绍符合C++国际标准的C++面向对象程序设计思想和方法;第12章和第13章分别介绍面向对象建模
    发表于 03-02 08:00 6次下载

    FPGA:状态机简述

    是FPGA设计中一种非常重要、非常根基的设计思想,堪称FPGA的灵魂,贯穿FPGA设计的始终。 02. 状态机简介 什么是状态机状态机通过不同的
    的头像 发表于 11-05 17:58 7376次阅读
    FPGA:<b class='flag-5'>状态机</b>简述

    什么是状态机状态机5要素

    玩单片还可以,各个外设也都会驱动,但是如果让你完整的写一套代码时,却无逻辑与框架可言。这说明编程还处于比较低的水平,你需要学会一种好的编程框架或者一种编程思想!比如模块化编程、状态机
    的头像 发表于 07-27 11:23 2w次阅读
    什么是<b class='flag-5'>状态机</b>?<b class='flag-5'>状态机</b>5要素

    如何以面向对象思想设计有限状态机

    有限状态机又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型,用英文缩写也被简...
    发表于 02-07 11:23 4次下载
    如何以<b class='flag-5'>面向</b><b class='flag-5'>对象</b>的<b class='flag-5'>思想</b>设计有限<b class='flag-5'>状态机</b>

    按键状态机代码

    自己写的按键状态机,需要的时候根据情况修改一下
    发表于 03-27 10:42 8次下载