esp: button component

button组件

ESP 按键:https://docs.espressif.com/projects/esp-iot-solution/zh_CN/latest/input_device/button.html

按键组件实现了 GPIO 和 ADC 两种按键,并允许同时创建两种不同的按键。

注意:

*1、GPIO 按键需注意上下拉问题,组件内部会启用芯片内部的上下拉电阻,但是在仅支持输入的 IO 内部没有电阻, 需要外部连接。*

2、ADC 按键需注意电压不能超过 ADC 量程。

按键事件

每个按键拥有下表的 8 个事件:

事件 触发条件
BUTTON_PRESS_DOWN 按下
BUTTON_PRESS_UP 弹起
BUTTON_PRESS_REPEAT 按下弹起次数 >= 2次
BUTTON_PRESS_REPEAT_DONE 重复按下结束
BUTTON_SINGLE_CLICK 按下弹起 1 次
BUTTON_DOUBLE_CLICK 按下弹起 2 次
BUTTON_MULTIPLE_CLICK 指定重复按下次数 N 次,达成时触发
BUTTON_LONG_PRESS_START 按下时间达到阈值的瞬间
BUTTON_LONG_PRESS_HOLD 长按期间一直触发
BUTTON_LONG_PRESS_UP 长按弹起
BUTTON_PRESS_REPEAT_DONE 多次按下弹起结束
BUTTON_PRESS_END 表示 button 此次检测已结束

esp组件仓库

如何将button组件添加到目标项目?

Please use the component manager command add-dependency to add the button to your project’s dependency, during the CMake step the component will be downloaded automatically

释义:请使用 add-dependency 组件管理命令将 button 添加到目标项目依赖,在执行 CMake 步骤时,button 组件将会被自动下载到目标项目。

组件管理命令添加button组件:

1
2
3
4
5
# 添加指定button最新版本依赖
idf.py add-dependency "espressif/button=*"

# 添加指定button指定版本组件依赖
idf.py add-dependency "espressif/button^3.4.0"

组件管理命令执行后,在项目的 main 文件夹下将出现 idf_component.yml 文件,文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
## IDF Component Manager Manifest File
dependencies:
espressif/button: "^3.4.0"
## Required IDF version
idf:
version: ">=4.1.0"
# # Put list of dependencies here
# # For components maintained by Espressif:
# component: "~1.0.0"
# # For 3rd party components:
# username/component: ">=1.0.0,<2.0.0"
# username2/component2:
# version: "~1.0.0"
# # For transient dependencies `public` flag can be set.
# # `public` flag doesn't have an effect dependencies of the `main` component.
# # All dependencies of `main` are public by default.
# public: true

执行 idf.py build 完成后,在项目下创建了 managed_components 文件夹,该文件夹有下载的组件:espressif__buttonespressif__cmake_utilities

同时发现还有其他文件被新建:

1
2
3
4
5
6
7
8
9
10
pi@pi-NMH-WCX9:~/esp/app-example/get-started/button$ ls -al
total 84
drwxrwxr-x 5 pi pi 4096 11月 26 14:39 .
drwxrwxr-x 16 pi pi 4096 11月 20 14:18 ..
drwxrwxr-x 8 pi pi 4096 11月 26 14:39 build
-rw-rw-r-- 1 pi pi 244 11月 26 14:36 CMakeLists.txt
-rw-rw-r-- 1 pi pi 637 11月 26 14:39 dependencies.lock
drwxrwxr-x 2 pi pi 4096 11月 26 14:12 main
drwxrwxr-x 4 pi pi 4096 11月 26 14:39 managed_components
-rw-rw-r-- 1 pi pi 56876 11月 26 14:39 sdkconfig

很明显,dependencies.lock、sdkconfig文件是自动新建的,managed_components文件夹也是自动被新建的。

验证

源码地址:https://github.com/eiSouthBoy/esp-idf-example/tree/main/002-button

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

#include "iot_button.h"

#define BUTTON_ACTIVE_LEVEL 0 // 低电平有效

#define BUTTON_GPIO_0 CONFIG_BUTTON_GPIO_NUM
#define LED_GPIO_4 CONFIG_LED_GPIO_NUM

static const char *TAG = "button-example";
static uint8_t g_led_state = 0;

/* 按键事件类型表 */
const char *button_event_table[] = {
"BUTTON_PRESS_DOWN", // 按下
"BUTTON_PRESS_UP", // 弹起
"BUTTON_PRESS_REPEAT", // 按下弹起次数 >= 2次
"BUTTON_PRESS_REPEAT_DONE", // 重复按下结束
"BUTTON_SINGLE_CLICK", // 按下弹起一次
"BUTTON_DOUBLE_CLICK", // 按下弹起两次
"BUTTON_MULTIPLE_CLICK", // 指定重复按下次数 N 次,达成时触发
"BUTTON_LONG_PRESS_START", // 按下时间达到阈值的瞬间
"BUTTON_LONG_PRESS_HOLD", // 长按期间一直触发
"BUTTON_LONG_PRESS_UP", // 长按弹起
"BUTTON_PRESS_REPEAT_DONE", // 多次按下弹起结束
"BUTTON_PRESS_END" // 表示button此次检测已结束
};

/* 按键事件回调函数 */
static void button_event_cb(void *arg, void *data)
{
char btn_event[64] = {0};
snprintf(btn_event, 64, "%s", button_event_table[(button_event_t)data]);
ESP_LOGI(TAG, "Button event %s", btn_event);
iot_button_print_event((button_handle_t)arg);

if (0 == strcmp(btn_event, "BUTTON_PRESS_DOWN"))
{
g_led_state = !g_led_state;
ESP_LOGI(TAG, "Turning the LED %s!", g_led_state == true ? "ON" : "OFF");

/* Set the GPIO level according to the state (LOW or HIGH)*/
gpio_set_level(LED_GPIO_4, g_led_state);
}
}

/* 按键初始化操作 */
static void app_driver_button_init(uint32_t button_num)
{
esp_err_t err;
button_config_t btn_cfg = {
.type = BUTTON_TYPE_GPIO,
.gpio_button_config = {
.gpio_num = button_num,
.active_level = BUTTON_ACTIVE_LEVEL,
},
};
button_handle_t btn = iot_button_create(&btn_cfg);
assert(btn);
/* 根据不同的按键事件注册回调 */
err = iot_button_register_cb(btn, BUTTON_PRESS_DOWN, button_event_cb, NULL);
// err |= iot_button_register_cb(btn, BUTTON_PRESS_UP, button_event_cb, NULL);
// err |= iot_button_register_cb(btn, BUTTON_PRESS_REPEAT, button_event_cb, NULL);
// err |= iot_button_register_cb(btn, BUTTON_PRESS_REPEAT_DONE, button_event_cb, NULL);
// err |= iot_button_register_cb(btn, BUTTON_SINGLE_CLICK, button_event_cb, NULL);
// err |= iot_button_register_cb(btn, BUTTON_DOUBLE_CLICK, button_event_cb, NULL);
// err |= iot_button_register_cb(btn, BUTTON_LONG_PRESS_START, button_event_cb, NULL);
// err |= iot_button_register_cb(btn, BUTTON_LONG_PRESS_HOLD, button_event_cb, NULL);
// err |= iot_button_register_cb(btn, BUTTON_LONG_PRESS_UP, button_event_cb, NULL);
// err |= iot_button_register_cb(btn, BUTTON_PRESS_END, button_event_cb, NULL);

ESP_ERROR_CHECK(err);
}

/* LED灯初始化 */
static void app_driver_led_init(void)
{
ESP_LOGI(TAG, "Example configured to GPIO LED(GPIO %d)!", LED_GPIO_4);
gpio_reset_pin(LED_GPIO_4);
gpio_set_direction(LED_GPIO_4, GPIO_MODE_OUTPUT); /* Set the GPIO as a push/pull output */
gpio_set_level(LED_GPIO_4, 0);
}

void app_main(void)
{
app_driver_led_init();
app_driver_button_init(BUTTON_GPIO_0);
}

当 ESP32-DevKitC 开发板上的 Boot 按键被按下后,外接 GPIO4 的LED灯将会点亮,再次按下,LED灯熄灭。