上一篇教程中我们学习了如何读取按键状态。而按键的动作,比如单击,至少需要两个状态才能判定,长按、双击的判定更加复杂。今天我们来学习如何使用库函数判断按键单击,以及其实现原理。
我们要实现的是:当一个按键被单击时,一个LED的状态改变(即亮变暗,暗变亮);4个按键对应4个LED。利用库提供的 button_pressed 函数,很容易就能实现这个功能。
1 #include 2 #include 3 #include 4 5 int main() 6 { 7 led_init(); 8 button_init(PIN_0, PIN_1); 9 while (1) 10 { 11 for (uint8_t i = 0; i != BUTTON_COUNT; ++i) 12 if (button_pressed(i)) 13 led_flip(i); 14 delay(40); 15 } 16 } 在主循环中,程序对每个按键调用 button_pressed ,若返回真,则用 led_flip 将LED状态反转。 按键动作需要两个状态来判断,而函数在当下是无法从按键读取到以前的信息的,只能在本次调用时保存状态以供下次使用。自动变量保存的内容无法保留到下一次调用,可选的有全局变量与静态变量。由于此状态只被这一个函数使用,可以把它定义成静态变量。 button_pressed 函数可以判断4个按键的动作,每个按键需要一个 bool 变量,即一个bit的存储空间。为了节省空间,我使用了位操作,这里先不讲,把重心放在按键动作判断逻辑上。以下是判断一个按键动作的函数。 1 bool pressed() 2 { 3 static bool status = true; 4 bool pre = status; 5 status = button_down(BUTTON_0); 6 return !pre && status; 7 } 静态变量 status 用于保存按键在上一次调用时的状态。函数体中,先用自动变量 pre 临时保存了 status ,然后将 status 更新为当前的状态。return 语句返回的是 !pre && status ,即仅当 pre 为假且 status 为真时返回 true 。其逻辑为,如果上一次按键没有被按下而这一次被按下,则按键被单击了。 想一想,为什么 status 的初值要设置成 true ? 另外,上面的代码开头处的蓝色 bool 特别醒目,因为博客园代码着色是按照C#的规则,bool 是其中一个关键字。但是应当注意,C语言中没有 bool 这个关键字,而是 _Bool ;bool 与 true 和 false 都在 我们还没有解释过第一段代码中的 delay(40) 。如果你把它去掉,你会发现判定经常出错,往往在抬起的时候被多判定了一次,在按得不是很用力时很不稳定。这是按键内部的机械结构决定的,当处于连通和不连通位置的交界处时,单片机检测到的电平会迅速跳变(按键的原理,以及单片机如何检测按键状态,将在几篇后介绍),而一段延时就可以让这些跳变的电平被 button_down 函数忽略。这里的40是根据经验选取的。其实把40换成10到100之间的数,手感基本没有差别。 然而,即使有这句延时,单击判定还是有出错的时候。如果不能允许这样的错误,就需要“消抖”上场了,我们以后再讲。
上一篇:AVR单片机教程——拨动开关
下一篇:AVR单片机教程——按键状态
推荐阅读最新更新时间:2024-11-10 14:00
设计资源 培训 开发板 精华推荐
- 使用具有 B 类 EMI 滤波(单输出)的 RP10-2412SA DC/DC 转换器的典型应用
- NCV2575延迟启动电路典型应用电路
- DC2229A-B,基于 LTC3877/LTC3874 的演示板,具有 VID 输入的 4 相降压控制器,DCR 检测,6V = VIN = 14V,Vout = 0.6V 至 1.23V,120A
- APX1117 1A 低压差正可调或固定模式稳压器的典型应用
- RREF02 +5V 精密电压基准堆栈的典型应用
- LTC3646EDE-1 5V、1A 同步降压转换器的典型应用电路
- IP5389-3S
- MC78M15ABDTG 15V 电流调节器的典型应用
- 使用 Diodes Incorporated 的 AZ7027ZTR-E1 的参考设计
- 80V 热插拔控制器驱动大型 MOSFET,使用 LT4256-1 提高准确度和折返电流限制