AVR单片机教程——按键动作
本文隶属于AVR单片机教程系列。
上一篇教程中我们学习了如何读取按键状态。而按键的动作,比如单击,至少需要两个状态才能判定,长按、双击的判定更加复杂。今天我们来学习如何使用库函数判断按键单击,以及其实现原理。
我们要实现的是:当一个按键被单击时,一个LED的状态改变(即亮变暗,暗变亮);4个按键对应4个LED。利用库提供的 button_pressed 函数,很容易就能实现这个功能。
#include <ee1/button.h>
#include <ee1/led.h>
#include <ee1/delay.h> int main()
{
led_init();
button_init(PIN_0, PIN_1);
while ()
{
for (uint8_t i = ; i != BUTTON_COUNT; ++i)
if (button_pressed(i))
led_flip(i);
delay();
}
}
在主循环中,程序对每个按键调用 button_pressed ,若返回真,则用 led_flip 将LED状态反转。
按键动作需要两个状态来判断,而函数在当下是无法从按键读取到以前的信息的,只能在本次调用时保存状态以供下次使用。自动变量保存的内容无法保留到下一次调用,可选的有全局变量与静态变量。由于此状态只被这一个函数使用,可以把它定义成静态变量。
button_pressed 函数可以判断4个按键的动作,每个按键需要一个 bool 变量,即一个bit的存储空间。为了节省空间,我使用了位操作,这里先不讲,把重心放在按键动作判断逻辑上。以下是判断一个按键动作的函数。
bool pressed()
{
static bool status = true;
bool pre = status;
status = button_down(BUTTON_0);
return !pre && status;
}
静态变量 status 用于保存按键在上一次调用时的状态。函数体中,先用自动变量 pre 临时保存了 status ,然后将 status 更新为当前的状态。return 语句返回的是 !pre && status ,即仅当 pre 为假且 status 为真时返回 true 。其逻辑为,如果上一次按键没有被按下而这一次被按下,则按键被单击了。
想一想,为什么 status 的初值要设置成 true ?
另外,上面的代码开头处的蓝色 bool 特别醒目,因为博客园代码着色是按照C#的规则,bool 是其中一个关键字。但是应当注意,C语言中没有 bool 这个关键字,而是 _Bool ;bool 与 true 和 false 都在 <stdbool.h> 中定义。
我们还没有解释过第一段代码中的 delay() 。如果你把它去掉,你会发现判定经常出错,往往在抬起的时候被多判定了一次,在按得不是很用力时很不稳定。这是按键内部的机械结构决定的,当处于连通和不连通位置的交界处时,单片机检测到的电平会迅速跳变(按键的原理,以及单片机如何检测按键状态,将在几篇后介绍),而一段延时就可以让这些跳变的电平被 button_down 函数忽略。这里的40是根据经验选取的。其实把40换成10到100之间的数,手感基本没有差别。
然而,即使有这句延时,单击判定还是有出错的时候。如果不能允许这样的错误,就需要“消抖”上场了,我们以后再讲。
作业:给其中一个按键加上一个功能,让它控制其余按键是否启用。
AVR单片机教程——按键动作的更多相关文章
- AVR单片机教程——按键状态
好久没更新了,今天开始继续,争取日更. 今天我们来讲按键.开发板的右下角有4个按键,按下会有明显的“咔嗒”声.如何检测按键是否被按下呢?首先要把按键或直接或间接地连接到单片机上.与之前使用的4个LED ...
- AVR单片机教程——数字输入
我们已经学习了如何使用按键和拨动开关,不知你有没有好奇 button_down 和 switch_status 等函数是如何实现的.本篇教程带你一探究竟,让我们从按键的原理开始. 在原理图中,按键的符 ...
- AVR单片机教程——拨动开关
在按键的上方有4个拨动开关.开关与按键,在原理和使用方法上都是很类似的,但有不同的用途——按键按下后松开就会弹起,而开关可以保存其状态. <switch.h> 定义了与开关相关的函数.sw ...
- AVR单片机教程——ADC
ADC 计算机的世界是0和1的.单片机可以通过读取0和1来确定按键状态,也可以输出0和1来控制LED.即使是看起来不太0和1的PWM,好像可以输出0到5V之间的电压一样,达到0和1之间的效果,但本质上 ...
- AVR单片机教程——串口发送
本文隶属于AVR单片机教程系列. 到目前为止,我们的开发板只能处理很小量的数据:读取几个引脚电平,输出几个LED,顶多用数码管显示一个两位数字.至于输入一个指令.输出一条调试信息,甚至用scanf ...
- AVR单片机教程——PWM调光
本文隶属于AVR单片机教程系列. PWM 两位数码管的驱动方式是动态扫描,每一位都只有50%的时间是亮的,我们称这个数值为其占空比.让引脚输出高电平点亮LED,占空比就是100%. 在驱动数码管时 ...
- AVR单片机教程——走向高层
本文隶属于AVR单片机教程系列. 在系列教程的最后一篇中,我将向你推荐3个可以深造的方向:RTOS.C++.事件驱动.掌握这些技术可以帮助你更快.更好地开发更大的项目. 本文涉及到许多概念性的内容 ...
- AVR单片机教程——旋转编码器
好久没写这个系列了.今天讲讲旋转编码器. 旋转编码器好像不是单片机玩家很常用的器件,但是我们的开发板上有,原因如下: 旋转编码器挺好用的.电位器能旋转的角度有限,旋转编码器可以无限圈旋转:旋转时不连续 ...
- AVR单片机教程——数码管
先解答之前一个思考题:如果不把引脚配置为输出而写高电平,连接LED会怎样? 实验结果是,LED会亮,但相比于输出高电平的情况,亮度很低.这是为什么呢? 通过上一篇教程我们知道,引脚输入输出模式是由寄存 ...
随机推荐
- javascript 终极循环方法for... of ..推荐
js目前有很多的循环方法,如for, forEach, for .. in, for of 等等,而在ES6里面,我们又增加了一些数据结构,比如set,map,Symbol等. 那么我们该选取哪一 ...
- Tomcat启动问题:严重[main] org.apache.catalina.core.AprLifecycleListener.init An incompatible version...
今天观察tomcat启动日志,有一些以前没注意到的信息: 严重 [main] org.apache.catalina.core.AprLifecycleListener.init An incompa ...
- HTML5 Geolocation(地理定位)
一.背景 在HTML规范中,增加了获取用户地理信息的API,这样使得可以基于用户位置开发互联网应用,即基于位置服务 鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的. Inter ...
- [RN] React Native 使用 react-native-vector-icons 图标显示问号
我在第一次使用 react-native-vector-icons 时图标显示问号 后来在网上查了很多文章,发现原因有两个 1)安装完 react-native-vector-icons 后,没有li ...
- 洛谷 P3371 【模板】单源最短路径(弱化版) 题解
P3371 [模板]单源最短路径(弱化版) 题目背景 本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779. 题目描述 如题,给出一个有向图,请输出从某一点出 ...
- 微信小程序七夕节礼物
VSCode Node.js HbuilderX 安装前端开发环境 [外链图片转存失败(img-aXUJRfXc-1565136341881)(https://upload-images.jiansh ...
- 从海量数据中寻找出topK的最优算法代码
package findMinNumIncludedTopN;/** * 小顶堆 * @author TongXueQiang * @date 2016/03/09 * @since JDK 1.8 ...
- 动态代理之投鞭断流!看一下MyBatis的底层实现原理
转:https://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247486856&idx=1&sn=d430be5d14d1 ...
- 【软工实践】Beta冲刺(1/5)
链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 登陆注册.查看用户信息.添加用户任务.查看任务等API的完善 tomcat的学 ...
- 快速激活Navicat Premium 12
Navicat Premium 12是一套数据库开发管理工具,支持链家MySQL.Oracle.SQL server等多种数据库,快速便捷创建.管理和维护数据库 一.下载 https://www.na ...