找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9690|回复: 2
打印 上一主题 下一主题
收起左侧

STM32f103按键检测程序实现长按短按

[复制链接]
跳转到指定楼层
楼主
ID:374488 发表于 2018-7-19 00:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
背景只要使用单片机,按键检测基本上是一定要实现的功能。按键检测要好用,最重要的是实时和去抖。初学者往往会在主循环调用按键检测程序(实时)并利用延时去抖(准确)。这种在主循环内延时的做法对整个程序非常不友好,也非常不高效。因此,本篇就我自己实现的一个检测按键并可判断按键是否长短按的程序做个介绍和记录。
正文在硬件连接上,按键一端连接在普通IO口上,另一端接地,IO配置为内部弱上拉。
在软件上,先配置一个5ms定时器并打开中断,每进入该定时中断则置位一次标志位“key_handle”。接着在主循环调用一个“scan_key()”函数,判断“key_handle”标志位是否在定时器内被置位,若被置位则将该位复位并读取连接按键的IO口值。
此时,“scan_key()”函数内分为按键按下和松开两个分支:
  • 按键按下,则计数值“longkey”每隔5ms自加一次,因为这个分支每隔5ms才会进入执行一次;
  • 按键放开,则先判断“longkey”的值,若“longkey”的值换算出来代表按键按下时间在10ms-1s内,(10ms是去抖值,1s是与短按与长按的分界点。)则判断按键为短按;若“longkey”的值大于1s,则判断按键为长按。并将按键状态赋值给按键状态变量“keybuf”。同时,由于此时按键已经放开,因此“longkey”的值要置位“0”等待用户下次按下按键并执行从“0”开始的自加操作。
若程序又一次进入按键检测代码段,说明所有功能块代码已经获知key状态,有对key感兴趣的代码段也肯定已经进行过相应处理,因此此时要及时将“keybuf”置为无按键按下状态以此来同步实际按键状态。
实际代码如下:
  1. void scan_key(void)
  2. {
  3.     unsigned char key_status;
  4.    
  5.     if((longkey == 0) && (keybuf != _KEYNULL)){
  6.         // 在keybuf被标记为长按或短按后,若是按键已经松开,
  7.         // 则在主循环跑完一次后,及时将按键状态标记为无按键按下。
  8.         keybuf = _KEYNULL;
  9.     }
  10.     if(key_handle == _ON) { //5ms进入一次
  11.         key_handle = _OFF;    // 复位5ms标志位
  12.         key_status = GPIO_ReadInputDataBit(KEYRESET_GPIO_PORT, KEYRESET_GPIO_PIN);
  13.         if(key_status == 0) {   //按下按键
  14.             longkey++;
  15.         }
  16.         else {  // 松开按键
  17.             if((longkey >= 3) && (longkey <= 100) ){    // 15ms - 1s
  18.                 keybuf = _SHORTKEY;
  19.             } else if(longkey >= 200) { // 2s
  20.                 keybuf = _LONGKEY;
  21.             } else {
  22.                 keybuf = _KEYNULL;// 若为扰动,按键状态也该为无按键按下
  23.             }
  24.             longkey = 0;
  25.         }
  26.     }
  27. }
复制代码

补充:和Tony~Liu讨论了下,发现其实还有效率更高,占用CPU更少的按键检测办法。
在硬件上,按键连接在具有外部中断的IO口上,按键连接在该IO口上的脚外部上拉,按键另一端接地。
在软件上,连接按键的IO口配置为双边沿中断,同时配置一个1ms定时器中断。当按键按下时,触发外部中断,在外部中断内判断IO口电平,以此确定此为上升沿还是下降沿。下降沿则代表按键按下,开始计时,上升沿则代表按键松开,停止计时。上升沿中断时,在中断内置位“key_handle”,主循环在判断到“key_handle”被置位后,则开始判断计时器时间,若是时间在10ms-1s内,(10ms是去抖值,1s是与短按与长按的分界点。)则判断按键为短按;若时间大于1s,则判断按键为长按。具体实施也很简单,在此就不再贴代码,只是说说这种思想。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:281804 发表于 2018-7-20 11:43 | 只看该作者
emmmm照着试试吧 新手表示还是得动动手才知道是什么
回复

使用道具 举报

板凳
ID:388231 发表于 2019-9-6 15:05 | 只看该作者
longkey 如果计数到100-200之间,就会进入最后else里面,要改一下
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表