我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 1454|回复: 9

[技术文章] 基于状态机的按键扫描程序

[复制链接]
  • TA的每日心情

    2024-12-23 16:35
  • 签到天数: 100 天

    [LV.6]常住居民II

    3万

    主题

    8254

    回帖

    8万

    积分

    三级逆天

    积分
    81484

    终身成就奖特殊贡献奖原创先锋奖金点子奖优秀斑竹奖宣传大使奖

    发表于 2018-1-5 16:11:25 | 显示全部楼层 |阅读模式

    马上注册,结交更多好友,享用更多功能,让你轻松玩转社区

    您需要 登录 才可以下载或查看,没有账号?立即注册

    ×
    基于状态机的按键扫描程序
    所谓人机交互,无外乎是利用微控制器检测用户的输入指令,以及将设备的状态信息通过显示器显示出来,微控制器通过检测用户输入的指令,来及时响应用户的操作;用户则通过LCD等显示设备显示出来的信息,来实时的了解设备的运行状况。因此,一套优秀的人机接口,对一个嵌入式设备来说是多么的重要。有了人机接口,那么嵌入式的所有功能,都可以慢慢实现了。下面就有我来给大家讲讲人机交互里面最简单的输入设备,按键的扫描实现方法吧。
    按键的扫描方式主要有下面几种:
    1、死循环扫描方式:这种扫描方式,一般出现在大量的单片机教程及51开发板的配套例程里面,因此一般单片机初学者多是用这种扫描方式,因为这种扫描方式简单直接,也比较好理解。假定按键端口为PIN_KEY1,延时函数为delay_ms(unsined int ms),则死循环扫描方式的实现方式如下:
    //由于超出字数,具体程序请大家阅读附件理解,抱歉。
    以上就是死循环扫描方式的按键扫描实现方法,是最简单的方法,这种方法最大的缺点就是占用CPU时间过长。当实现的功能比较简单,例如只是控制一个LED灯的亮灭,感觉不出这种方法的缺点。但是当功能比较多的时候,就会造成系统比较卡顿的现象,使系统运行不流畅,造成的原因就是delay_ms(20),因为在延时的20ms里面,CPU完全是死等在那里,不去处理其他任何功能,只有当按键松开后,才会去处理其他功能,如果到处都充满了这种死循环,那么就会有很多功能得不到及时的响应,而造成系统卡顿。
    2、中断方式:这种按键扫描方式一般是利用外部中断来实现,因为外部中断一般具有上升沿触发中断、下降沿触发中断、高电平触发中断、低电平触发中断等,当按键没有按下时为高电平,按下按键后,会有一个下降沿或者是低电平,外部中断检测到该信号后,进入外部中断处理程序,从而实现按键扫描。这种方式一般利用在一些需要低功耗应用的场合,当MCU进入低功耗模式时,需要一个外部中断来唤醒MCU,进入运行模式,这时我们可以利用一个外部中断来唤醒MCU,并且通过外部中断来检测扫描按键是否按下,实现特定的功能。外部中断扫描方式的主要优点是,平时不需要MCU的参与,也就不消耗MCU的运行时间,只有当检测到外部中断时,才处理按键事件;缺点是一般MCU的外部中断口不多,而外部中断一般是用来处理一些比较紧急的功能,比如过零检测等功能的。因此,外部中断扫描方式也不是最常用的按键扫描方法。
    3、ADC检测按键:这种方法一般是使用在具有ADC功能的单片机上,当IO口不足时,可以使用一个AD口来检测按键,每个按键按下时,AD采集到的数据不一样,从而来实现按键的检测。
    4、定时器定时扫描方式:这种方法和方法1有点类似,只是不会像方法1那样死等在那里消耗MCU运行时间,而是通过定时器扫描来实现。首先,MCU检测到按键后,定时器定时,达到一定时间后,继续扫描按键是否按下,然后计时按键按下的时间,当20ms以后按键还是按下状态,则执行按键操作,反之则认为是抖动。下面是我利用状态机实现的一个按键扫描程序,先贴出源代码再讲解实现过程。
    //由于贴源代码超出字数,此处程序请大家看附件资料理解,抱歉,大家可以安装Source Insight 3阅读,里面已经附件里面已经建好了工程。

    //main函数如下:
    void main(void)
    {
           //系统初始化
           SystemInit();
           while(1)
    {
           if(SystemFlag.fTimer_5ms)//a
           {
                  SystemFlag.fTimer_5ms = 0;//b
                  process_key();//c
    }
    }
    }
    注解:
    a、查询5ms标志是否为真,这个标志是在定时器中断里面置位的,5ms定时到,就置位该标志。
    b、清楚5ms到标志;
    c、调用按键扫描函数,这样按键扫描函数是5ms执行一次。
    process_key()函数里面的具体的按键功能执行函数请查看附件,里面注释的很清楚了。
    以上程序实现的功能是,短按K1,LED1亮,LED2灭;短按K2,LED1灭,LED2亮;长按K1两秒,LED1翻转;长按K2两秒,LED2翻转;K1和K2同时按下2秒,LED1和LED2都翻转。附件使用的是瑞萨R5F100FC单片机编程实现的,大家可以移植到任何平台,不会的可以跟帖回复,我可以和大家共同探讨。
    我想经过了上面的讲解,大家对按键的几种扫描实现方式都有了一个足够的认识了,大家也可以看出状态机编程应用比较实用。将一个功能,分解成多个不同的状态,每个状态处理一个步骤,简单易懂,而且也更加容易实现。
    如果你是个单片机初学者,或者是还在使用死循环扫描按键的程序员,那么请赶紧抛弃死循环吧,尽量用定时器中断来实现一个简单的前后台系统。
    我自己是一个很喜欢使用状态机机制来编程的人,因为我觉得那样对系统的整个运行流程比较清晰。好了,今天就先写到这里了,以后我有空会继续分享一些个人编程过程中用到的方法,只希望对单片机初学者有个抛砖引玉的效果,让他们编程时,尽量从产品角度来编写程序。

    如果你对以上程序还有疑问,欢迎跟帖回复( ^_^ )。
    如果想更加详细的了解状态机按键扫描的实现,推荐大家看两本书,一本是“匠人手记 一个单片机工作者的实践与思考(第2版)”,一本是“AVR单片机嵌入式系统原理与应用实践”,大家可以先到网上看看书籍目录,
    回复

    使用道具 举报

    该用户从未签到

    111

    主题

    770

    回帖

    2208

    积分

    1元学习Allegro(1期)

    积分
    2208

    终身成就奖

    发表于 2018-1-5 17:41:59 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    12

    主题

    7222

    回帖

    5073

    积分

    二级逆天

    积分
    5073

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2018-1-5 20:53:30 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    218

    主题

    1269

    回帖

    3504

    积分

    allegro-171023高级班

    积分
    3504

    终身成就奖

    发表于 2018-1-6 08:38:09 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    700

    主题

    656

    回帖

    1630

    积分

    百元学习allegro

    积分
    1630

    终身成就奖

    QQ
    发表于 2018-1-6 08:58:20 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    2

    主题

    2415

    回帖

    11

    积分

    二级逆天

    积分
    11

    社区居民终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2018-1-6 09:00:41 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-10-18 12:25
  • 签到天数: 2 天

    [LV.1]初来乍到

    6

    主题

    1932

    回帖

    2575

    积分

    1元学习PADS(2期)

    积分
    2575

    终身成就奖优秀斑竹奖

    QQ
    发表于 2018-1-6 09:05:54 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    30

    主题

    4174

    回帖

    0

    积分

    百元学习allegro

    积分
    0

    终身成就奖优秀斑竹奖

    发表于 2018-1-6 09:13:25 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-6-14 16:03
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    0

    主题

    1万

    回帖

    7618

    积分

    二级逆天

    积分
    7618

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2018-1-6 15:57:40 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:31
  • 签到天数: 173 天

    [LV.7]常住居民III

    250

    主题

    3658

    回帖

    1万

    积分

    三级逆天

    积分
    10503

    终身成就奖特殊贡献奖原创先锋奖

    QQ
    发表于 2018-1-9 17:39:22 | 显示全部楼层
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    每日签到,有金币领取。


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    ( 闽ICP备2024076463号-1 ) 论坛技术支持QQ群171867948 ,论坛问题,充值问题请联系QQ1308068381

    平平安安
    TOP
    快速回复 返回顶部 返回列表