在我们的电子时钟设计里,通常会用到2-3个地理按键来完成对时间等其他信息的设置,在《Arduino入门教程》中我们已经详细讲解了独立按键模块的使用。在教程中我们是通过分析独立按键的电路,再到按键产出的信号,最终我们自己通过程序方式来获取到按键的信号,从而判断独立按键是否按下,最终实现了按键模块的使用。其实在Arduino强大的开源库中已经有一个库文件,可以很方便的实现独立按键的一次按下(单击),两次快速按下(双击)以及长按(长时间按下)等的按键检测了。使用这个库我们可以快速的完成按键的检测,快速的实现我们的任务功能,这个库文件就是“OneButton”库。可以直接在Arduino IDE的库管理中直接搜索,搜索结果只有一个,直接下载既可以。也可通过下方连接直接下载。
OneButton.zip
在OneButton库中有多个示例文件,大家可以自行查看,因为我们的电子使用需要使用3个独立按键,在示例程序中有个“TwoButton”的示例,其中有两个按键检测的程序,我就以此为例作简要说明。因为例程中所有注释都为英文,为方便大家查看,在此做了简单的中文化注释。
/*
This is a sample sketch to show how to use the OneButtonLibrary
to detect click events on 2 buttons in parallel.
The library internals are explained at
http://www.mathertel.de/Arduino/OneButtonLibrary.aspx
Setup a test circuit:
* Connect a pushbutton to pin A1 (ButtonPin) and ground.
* Connect a pushbutton to pin A2 (ButtonPin) and ground.
* The Serial interface is used for output the detected button events.
The Sketch shows how to setup the library and bind 2 buttons to their functions.
In the loop function the button1.tick and button2.tick functions have to be called as often as you like.
*/
// 01.03.2014 created by Matthias Hertel
// ... and working.
/* 一个输出示例:
Starting TwoButtons... //按键按下后的输出明细
Button 1 click. //按键 1 单击
Button 2 click. //按键 2 单击
Button 1 doubleclick. //按键 1 双击
Button 2 doubleclick. //按键 2 双击
Button 1 longPress start //按键 1 长按开始
Button 1 longPress... //按键 1 长按。。。
Button 1 longPress...
Button 1 longPress...
Button 1 longPress stop //按键 1 长按结束
Button 2 longPress start //按键 2 长按开始
Button 2 longPress... //按键 1 长按。。。
Button 2 longPress...
Button 2 longPress stop //按键 1 长按结束
*/
#include "OneButton.h"
// 设置按键引脚
OneButton button1(11, true); //key1
OneButton button2(10, true); //key2
// setup 函数
void setup() {
Serial.begin(9600); //设置串口波特率
while (!Serial) {
; // 等待串行端口连接。仅Leonardo需要,此处可以不用
}
Serial.println("Starting TwoButtons..."); //串口输出:Starting TwoButtons...
// 注册按钮 1 的功能函数
button1.attachClick(click1); //按键1单击
button1.attachDoubleClick(doubleclick1); //按键1双击
button1.attachLongPressStart(longPressStart1); //按键1长按开始
button1.attachLongPressStop(longPressStop1); //按钮1长按停止
button1.attachDuringLongPress(longPress1); //按钮1长按中。。。
// 注册按钮 2 的功能函数
button2.attachClick(click2);
button2.attachDoubleClick(doubleclick2);
button2.attachLongPressStart(longPressStart2);
button2.attachLongPressStop(longPressStop2);
button2.attachDuringLongPress(longPress2);
} // setup
// loop循环函数
void loop() {
// 按键执行函数,这个必须在loop中不断的检测
button1.tick();
button2.tick();
// 你可以在此处实现其他代码,也可以稍等片刻
delay(10);
}
// ----- 按键 1 的回调函数
// 按下button1 1次(然后不按2.按钮)将调用此函数。
void click1() {
Serial.println("按键 1 单击");
} // click1
// 如果在短时间内两次按下button1,则将调用此函数。
void doubleclick1() {
Serial.println("按钮1双击。");
} // doubleclick1
// 长时间按下button1时,将调用一次此函数,长按开始
void longPressStart1() {
Serial.println("Button 1 longPress start");
} // longPressStart1
//长时间按下按钮1时,会周期性的调用此函数。
void longPress1() {
Serial.println("Button 1 longPress...");
} // longPress1
//长时间按下按钮1后松开时,此函数将被调用一次。长按停止
void longPressStop1() {
Serial.println("Button 1 longPress stop");
} // longPressStop1
// ----- 按键 2 的回调函数
//按键2所有函数和按键1功能相同
void click2() {
Serial.println("Button 2 click.");
} // click2
void doubleclick2() {
Serial.println("Button 2 doubleclick.");
} // doubleclick2
void longPressStart2() {
Serial.println("Button 2 longPress start");
} // longPressStart2
void longPress2() {
Serial.println("Button 2 longPress...");
} // longPress2
void longPressStop2() {
Serial.println("Button 2 longPress stop");
} // longPressStop2
// End
以上是对示例程序TwoButtons程序的简要中文注释,下面对部分程序做必要解释。
#include "OneButton.h"
// 设置按键引脚
OneButton button1(11, true); //key1
OneButton button2(10, true); //key2
第一行是引用了OneButton的库文件,第二第三行是对独立按键的硬件连接做设置,参数1是按键连接的实际用引脚,在以上例程中使用得是数字引脚11和10号;第二个参数(true or false),默认是true,表示按键按下是低电平有效,若按键按下是高电平,需要设置为false;此函数其实还有第三个参数(true or false),表示按键引脚的工作模式是“输入上拉”还是“输入”模式。默认为输入上拉模式(true),通常情况下这个参数可以不用修改。
// 注册按钮 1 的功能函数
button1.attachClick(click1); //按键1单击
button1.attachDoubleClick(doubleclick1); //按键1双击
button1.attachLongPressStart(longPressStart1); //按键1长按开始
button1.attachLongPressStop(longPressStop1); //按钮1长按停止
button1.attachDuringLongPress(longPress1); //按钮1长按中。。。
在setup中注册的按键函数名称一定要和后续的按键回调函数的函数名一致。
// ----- 按键 1 的回调函数
// 按下button1 1次(然后不按2.按钮)将调用此函数。
void click1() {
Serial.println("按键 1 单击");
} // click1
// 如果在短时间内两次按下button1,则将调用此函数。
void doubleclick1() {
Serial.println("按钮1双击。");
} // doubleclick1
// 长时间按下button1时,将调用一次此函数,长按开始
void longPressStart1() {
Serial.println("Button 1 longPress start");
} // longPressStart1
//长时间按下按钮1时,会周期性的调用此函数。
void longPress1() {
Serial.println("Button 1 longPress...");
} // longPress1
//长时间按下按钮1后松开时,此函数将被调用一次。长按停止
void longPressStop1() {
Serial.println("Button 1 longPress stop");
} // longPressStop1
函数名需要和按键函数注册中的一致,不然无法调用到。这里的按键按下后,我们只是通过发送一条信息到串口监视器,在实际的按键使用中,通常在按键按下后都是需要有处理其他任务的,我们可以在按键按下的回调函数中对某个变量进行操作,再在loop中去判断变量的值,从而识别是哪个按键按下,做出相应的处理。下面就来完成一个简单的实例。
实例要求:创建一个变量,采用两个按键对变量进行加一和减一的操作。
#include "OneButton.h"
// 设置按键引脚
OneButton button1(11, true); //key1
OneButton button2(10, true); //key2
byte count_key=10;
// setup 函数
void setup() {
Serial.begin(9600); //设置串口波特率
// 注册按钮 1 的功能函数
button1.attachClick(click1); //按键1单击
button1.attachDoubleClick(doubleclick1); //按键1双击
button1.attachLongPressStart(longPressStart1); //按键1长按开始
button1.attachLongPressStop(longPressStop1); //按钮1长按停止
button1.attachDuringLongPress(longPress1); //按钮1长按中。。。
// 注册按钮 2 的功能函数
button2.attachClick(click2);
button2.attachDoubleClick(doubleclick2);
button2.attachLongPressStart(longPressStart2);
button2.attachLongPressStop(longPressStop2);
button2.attachDuringLongPress(longPress2);
} // setup
// loop循环函数
void loop() {
// 按键执行函数,这个必须在loop中不断的检测
button1.tick();
button2.tick();
// 你可以在此处实现其他代码,也可以稍等片刻
delay(10);
}
// ----- 按键 1 的回调函数
// 按下button1 1次(然后不按2.按钮)将调用此函数。
void click1() {
Serial.println("按键 1 单击");
count_key++; //对变量加一
Serial.println(count_key); //变量发送串口监视器
} // click1
// 如果在短时间内两次按下button1,则将调用此函数。
void doubleclick1() {
Serial.println("按钮1双击。");
}
// 长时间按下button1时,将调用一次此函数,长按开始
void longPressStart1() {
Serial.println("Button 1 longPress start");
} // longPressStart1
//长时间按下按钮1时,会周期性的调用此函数。
void longPress1() {
Serial.println("Button 1 longPress...");
} // longPress1
//长时间按下按钮1后松开时,此函数将被调用一次。长按停止
void longPressStop1() {
Serial.println("Button 1 longPress stop");
} // longPressStop1
// ----- 按键 2 的回调函数
//按键2所有函数和按键1功能相同
void click2() {
Serial.println("Button 2 click.");
count_key--; //对变量减一
Serial.println(count_key);//变量发送串口监视器
}
void doubleclick2() {
Serial.println("Button 2 doubleclick.");
}
void longPressStart2() {
Serial.println("Button 2 longPress start");
}
void longPress2() {
Serial.println("Button 2 longPress...");
}
void longPressStop2() {
Serial.println("Button 2 longPress stop");
}
// End
因为以上实例任务简单,可以直接在按键回调函数中直接处理,如果按键任务比较复杂,需要占用时间长,那么可以在创建一个变量,在按键回调函数中只对这个变量进行赋值,比如加一按键赋值变量为1,减一按键变量赋值为2,这样赋值以后,在loop循环中在去判断是等于1还是等于2,如果等于1则去处理加一按键的任务。通过这样的处理,可以让按键回调函数变得简洁,并且不会占用按键的调用时间,提高按键的时效性。在复杂的任务中通常会采用这样的方式去处理按键,大家可以在自己的程序中进行尝试。