STM32f103按键检测程序实现长按短按
背景
只要使用单片机,按键检测基本上是一定要实现的功能。按键检测要好用,最重要的是实时和去抖。初学者往往会在主循环调用按键检测程序(实时)并利用延时去抖(准确)。这种在主循环内延时的做法对整个程序非常不友好,也非常不高效。因此,本篇就我自己实现的一个检测按键并可判断按键是否长短按的程序做个介绍和记录。
正文
在硬件连接上,按键一端连接在普通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按键检测程序实现长按短按的更多相关文章
- 第33章 TIM—电容按键检测—零死角玩转STM32-F429系列
第33章 TIM—电容按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...
- 长连接 短连接 RST报文
https://baike.baidu.com/item/短连接 短连接(short connnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数 ...
- 第12章 GPIO输入—按键检测
第12章 GPIO输入—按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...
- 第12章 GPIO输入-按键检测—零死角玩转STM32-F429系列
第12章 GPIO输入—按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...
- nRF51822外设应用[2]:GPIOTE的应用-按键检测
版权声明:本文为博主原创文章,转载请注明作者和出处. 作者:强光手电[艾克姆科技-无线事业部] 1. nRF51822寄存器类型 nRF51822的寄存器和一般的单片机有所差别,nRF51822 ...
- 第13章 GPIO输入—按键检测
本章参考资料:<STM32F76xxx参考手册>.库帮助文档<STM32F779xx_User_Manual.chm>. 按键检测使用到GPIO外设的基本输入功能,本章中不再赘 ...
- STM32F103 串口-IAP程序升级
STM32F103 串口-IAP程序升级 通常情况下我们给STM32系列的单片机烧录程序文件的时候,使用SWD.J-link或者通过设置BOOT引脚后,使用串口进行程序下载,这样的方式直接一次性将程序 ...
- Scheme语言实例入门--怎样写一个“新型冠状病毒感染风险检测程序”
小学生都能用的编程语言 2020的春季中小学受疫情影响,一直还没有开学,孩子宅在家说想做一个学校要求的研究项目,我就说你做一个怎么样通过编程来学习数学的小项目吧,用最简单的计算机语言来解决小学数学问题 ...
- 按键检测GPIO输入
1. 项目 通过按键控制开关LED灯,按下按键灯亮,再按一下灯灭. 2. 代码 mian.c #include "stm32f10x.h" //相当于51单片机中的 #includ ...
随机推荐
- UpdateData、Invalidate、InvalidateRect和UpdateWindow及RedrawWindow
Invalidate 在消息队列中加入一条WM_PAINT消息,其无效区为整个客户区. 窗口的客户区无效意味着需要重绘.例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的 ...
- Python 进阶 之 lambda 匿名函数
lambda 是个匿名函数,通常用于简单判断或者处理,例如判断一个数的奇偶性,过滤字符串,逻辑运算等等. lambda表达式: >>>lambda x:x*x >>> ...
- Chrome崩溃卡死
Chrome崩溃卡死主要是Flash崩溃导致,解决办法:1,chrome://plugins,停用Chrome自带的Flash插件:2,停用GPU加速.chrome://flags,停用对所有网页执行 ...
- JDBC连接池(数据源)
自定义连接池:用装饰设计模式将原连接的close方法改造成将连接还回数据源:装饰设计模式:http://www.cnblogs.com/tongxuping/p/6832518.html: 开源数据库 ...
- 洛谷 P1068 分数线划定【结构体排序】
题目描述 世博会志愿者的选拔工作正在 A 市如火如荼的进行.为了选拔最合适的人才,A 市对 所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试.面试分数线根 据计划录取人数的150%划 ...
- RPD Volume 168 Issue 4 March 2016 评论4
Non-vascular interventional procedures: effective dose to patient and equivalent dose to abdominal o ...
- 【构造】Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) D. Artsem and Saunders
根据那两个式子 g(h(x))=x h(g(x))=f(x) 可以推出来两个新的式子 g(f(x))=g(x) h(x)=f(h(x)) 于是,我们先找到f(x)的所有不动点,有几个不动点,m就是多少 ...
- Java高级架构师(一)第11节:Mybatis的分页实现
- iOS中用json接收图片的二进制流
标题可能说的有点混乱,再好好描述一下我遇到的问题: 我负责做一款App的iOS版本,服务器和Android版本都开发完了.服务器的图片存的不是路径,而是在数据库中的blob流对象,由于要求所有数据都用 ...
- sql字段字符用做其他类型查询
select * FROM aa where parent = %@ ORDER BY cast(seq as integer) ASC