背景

只要使用单片机,按键检测基本上是一定要实现的功能。按键检测要好用,最重要的是实时和去抖。初学者往往会在主循环调用按键检测程序(实时)并利用延时去抖(准确)。这种在主循环内延时的做法对整个程序非常不友好,也非常不高效。因此,本篇就我自己实现的一个检测按键并可判断按键是否长短按的程序做个介绍和记录。

正文

在硬件连接上,按键一端连接在普通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”置为无按键按下状态以此来同步实际按键状态。

实际代码如下:

void scan_key(void)
{
unsigned char key_status; if((longkey == 0) && (keybuf != _KEYNULL)){
// 在keybuf被标记为长按或短按后,若是按键已经松开,
// 则在主循环跑完一次后,及时将按键状态标记为无按键按下。
keybuf = _KEYNULL;
}
if(key_handle == _ON) { //5ms进入一次
key_handle = _OFF; // 复位5ms标志位
key_status = GPIO_ReadInputDataBit(KEYRESET_GPIO_PORT, KEYRESET_GPIO_PIN);
if(key_status == 0) { //按下按键
longkey++;
}
else { // 松开按键
if((longkey >= 3) && (longkey <= 100) ){ // 15ms - 1s
keybuf = _SHORTKEY;
} else if(longkey >= 200) { // 2s
keybuf = _LONGKEY;
} else {
keybuf = _KEYNULL;// 若为扰动,按键状态也该为无按键按下
}
longkey = 0;
}
}
}

补充:

Tony~Liu讨论了下,发现其实还有效率更高,占用CPU更少的按键检测办法。

在硬件上,按键连接在具有外部中断的IO口上,按键连接在该IO口上的脚外部上拉,按键另一端接地。

在软件上,连接按键的IO口配置为双边沿中断,同时配置一个1ms定时器中断。当按键按下时,触发外部中断,在外部中断内判断IO口电平,以此确定此为上升沿还是下降沿。下降沿则代表按键按下,开始计时,上升沿则代表按键松开,停止计时。上升沿中断时,在中断内置位“key_handle”,主循环在判断到“key_handle”被置位后,则开始判断计时器时间,若是时间在10ms-1s内,(10ms是去抖值,1s是与短按与长按的分界点。)则判断按键为短按;若时间大于1s,则判断按键为长按。具体实施也很简单,在此就不再贴代码,只是说说这种思想。

至此,记录完毕

记录时间:2017-1-19

记录地点:深圳WZ

STM32f103按键检测程序实现长按短按的更多相关文章

  1. 第33章 TIM—电容按键检测—零死角玩转STM32-F429系列

    第33章     TIM—电容按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...

  2. 长连接 短连接 RST报文

    https://baike.baidu.com/item/短连接 短连接(short connnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数 ...

  3. 第12章 GPIO输入—按键检测

    第12章     GPIO输入—按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...

  4. 第12章 GPIO输入-按键检测—零死角玩转STM32-F429系列

    第12章     GPIO输入—按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...

  5. nRF51822外设应用[2]:GPIOTE的应用-按键检测

    版权声明:本文为博主原创文章,转载请注明作者和出处.    作者:强光手电[艾克姆科技-无线事业部] 1. nRF51822寄存器类型 nRF51822的寄存器和一般的单片机有所差别,nRF51822 ...

  6. 第13章 GPIO输入—按键检测

    本章参考资料:<STM32F76xxx参考手册>.库帮助文档<STM32F779xx_User_Manual.chm>. 按键检测使用到GPIO外设的基本输入功能,本章中不再赘 ...

  7. STM32F103 串口-IAP程序升级

    STM32F103 串口-IAP程序升级 通常情况下我们给STM32系列的单片机烧录程序文件的时候,使用SWD.J-link或者通过设置BOOT引脚后,使用串口进行程序下载,这样的方式直接一次性将程序 ...

  8. Scheme语言实例入门--怎样写一个“新型冠状病毒感染风险检测程序”

    小学生都能用的编程语言 2020的春季中小学受疫情影响,一直还没有开学,孩子宅在家说想做一个学校要求的研究项目,我就说你做一个怎么样通过编程来学习数学的小项目吧,用最简单的计算机语言来解决小学数学问题 ...

  9. 按键检测GPIO输入

    1. 项目 通过按键控制开关LED灯,按下按键灯亮,再按一下灯灭. 2. 代码 mian.c #include "stm32f10x.h" //相当于51单片机中的 #includ ...

随机推荐

  1. Laravel 中的 Many-To-Many

    在实际的开发中,我们经常会接触到几种常见的对应关系模式: One-To-One //一对一 One-To-Many //一对多 Many-To-Many //多对多 在刚刚开始接触到这些概念的时候,其 ...

  2. Canvas基础——钟表绘制

    首先,canvas语法基础薄弱的小伙伴请点这里,剩下的小伙伴们可以接着往下看了. 一个表,需要画什么出来呢:3条线(时分秒针),1个圆(表盘),以及60条短线/点(刻度). 嗯,没毛病. 那接下来让我 ...

  3. (十一)数组array

    变量:只能存一个值,数组可以存多个值 (1)普通数组,索引下标是整数: 1)定义: 方法一:一次赋一个值:语法:数组名[下标]=变量值 array[1]=linux array[2]=shell 方法 ...

  4. CF 1005A Tanya and Stairways 【STL】

    Little girl Tanya climbs the stairs inside a multi-storey building. Every time Tanya climbs a stairw ...

  5. mysql 查看表结构方法

    留给自己备查: mysql 导出为 csv 文件时如果直接使用导出命令是无法导出表结构的, 因此我们需要能够查询表结构的方法: 方法如下: 1.desc(描述)命令 desc tablename;de ...

  6. notepad++ remove duplicate line

    To remove duplicate lines just press Ctrl + F, select the “Replace” tab and in the “Find” field, pla ...

  7. Fiddler 高级用法:Fiddler Script 与 HTTP 断点调试

    转载自 https://my.oschina.net/leejun2005/blog/399108 1.Fiddler Script 1.1 Fiddler Script简介 在web前端开发的过程中 ...

  8. HTTP状态代码集

    所有 HTTP 状态代码及其定义.   代码  指示     2xx  成功     200  正常:请求已完成.     201  正常:紧接 POST 命令.     202  正常:已接受用于处 ...

  9. [BZOJ4530]大融合

    LCT维护子树信息 维护两个子树信息,$vinf_x$表示节点$x$的所有轻儿子子树信息,$inf_x$表示以$x$为根的LCT子树(包含虚边)的信息 对$vinf$: access时,断开$x$的原 ...

  10. 【kd-tree】bzoj3290 Theresa与数据结构

    离线所有操作,对所有可能存在的点建立kd-tree,add相当于权值+1,cancel相当于权值-1. 修改操作要记录kd-tree上每个点的fa,从底向上地进行修改. 优化:若一个矩形框的sumv= ...