基于Freertos的ESP-IDF开发——5.使用按键[不带消抖、带消抖、长按短按识别]

news/2024/11/26 9:18:10/

基于Freertos的ESP-IDF开发——5.使用按键[不带消抖、带消抖、长按短按识别]

  • 0. 前言
  • 1. 确定GPIO引脚
  • 2. 触发函数(不带消抖)
  • 3. 触发函数(带消抖)
  • 4. 长按和短按识别
  • 5.其他FreeRtos文章

0. 前言

这一节我们来学习使用按键操作。包括带消抖和不带消抖。

由于之前已经学习过FreeRtos使用任务的方式,所以不再过多赘述、
如果你对使用任务存有疑惑,你可以跳转到文章末尾学习第三节

开发环境:ESP-IDF 4.3
操作系统:Windows10 专业版
开发板:自制的ESP32-WROOM-32E

1. 确定GPIO引脚

查看原理图,发现GPIO引脚是连接在GPIO0引脚,也就是我们的 boot 按键上
在这里插入图片描述
先把前期要准备的工作先准备好,如下:

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/gpio.h>
#include "esp_log.h"#define BUTTON_PIN  GPIO_NUM_0
static const char *TAG = "Key_Input";

2. 触发函数(不带消抖)

不带消抖的按键触发很简单:在一个死循环中,只要连接在 IO0 上的按键按下(IO0 接收到低电平),那么就视为触发了按键,演示代码如下:

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/gpio.h>
#include "esp_log.h"#define BUTTON_PIN  GPIO_NUM_0
static const char *TAG = "Key_Input";void button_task(void *arg)
{gpio_pad_select_gpio(BUTTON_PIN);gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);gpio_set_pull_mode(BUTTON_PIN, GPIO_PULLUP_ONLY);while (1) {if (gpio_get_level(BUTTON_PIN) == 0) {ESP_LOGI(TAG,"Button Pressed!\n");}vTaskDelay(10 / portTICK_PERIOD_MS);}
}void app_main()
{xTaskCreate(button_task, "button_task", 2048, NULL, 10, NULL);
}

效果如下,只要按下去了就会检测到很多次触发:
在这里插入图片描述

3. 触发函数(带消抖)

上面的示例你可以看到每隔10ms就触发了一次函数,这样的高频操作甚至让我触发了堆栈空间溢出导致重启,所以我们使用按键还是需要使用消抖的,代码如下:

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/gpio.h>
#include "esp_log.h"#define BUTTON_PIN  GPIO_NUM_0
static const char *TAG = "Key_Input";void button_task(void *arg)
{int button_state = 0;int button_debounce = 0;int button_pressed = 0;while (1) {button_state = gpio_get_level(BUTTON_PIN);if (button_state == 0) {button_debounce++;if (button_debounce >= 10) {if (!button_pressed) {ESP_LOGI(TAG,"Button Pressed!\n");button_pressed = 1;}}} else {button_debounce = 0;button_pressed = 0;}vTaskDelay(10 / portTICK_PERIOD_MS);}
}void app_main()
{gpio_pad_select_gpio(BUTTON_PIN);gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);gpio_set_pull_mode(BUTTON_PIN, GPIO_PULLUP_ONLY);xTaskCreate(button_task, "button_task", 2048, NULL, 10, NULL);
}

演示效果如下,我连续按动,触发的间隔变短,也没有出现持续触发的情况,所以我们的按键消抖代码就写好了
在这里插入图片描述

4. 长按和短按识别

长按和短按的识别就是根据低电平的持续时间来判断是低电平还是高电平:

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/gpio.h>
#include "esp_log.h"#define BUTTON_PIN  GPIO_NUM_0
static const char *TAG = "Key_Input";#define LONG_PRESS_TIME_MS  1000static void button_task(void *arg)
{gpio_pad_select_gpio(BUTTON_PIN);gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);gpio_set_pull_mode(BUTTON_PIN, GPIO_PULLUP_ONLY);TickType_t press_start_time = 0;bool is_button_pressed = false;while (1) {bool button_state = gpio_get_level(BUTTON_PIN);if (button_state && !is_button_pressed) {// Button is pressedis_button_pressed = true;press_start_time = xTaskGetTickCount();} else if (!button_state && is_button_pressed) {// Button is releasedis_button_pressed = false;TickType_t press_duration = xTaskGetTickCount() - press_start_time;if (press_duration >= pdMS_TO_TICKS(LONG_PRESS_TIME_MS)) {// 长按ESP_LOGI(TAG,"长按");} else {// 短按ESP_LOGI(TAG,"短按");}}vTaskDelay(pdMS_TO_TICKS(10));}
}void app_main()
{xTaskCreate(button_task, "button_task", 2048, NULL, 10, NULL);
}

经过测试发现如果按键比较小不太好按的话,会容易出现抖动导致识别错误:
在这里插入图片描述

5.其他FreeRtos文章

还有以上文章值得你一览
基于Freertos的ESP-IDF开发——0.Windows下espidf的环境搭建
基于Freertos的ESP-IDF开发——1.HelloWorld
基于Freertos的ESP-IDF开发——2.点亮一颗LED
基于Freertos的ESP-IDF开发——3.使用任务(上)
基于Freertos的ESP-IDF开发——3.使用任务(中)
基于Freertos的ESP-IDF开发——3.使用任务(下)
基于Freertos的ESP-IDF开发——4.使用任务的方式来点亮LED灯


http://www.ppmy.cn/news/74461.html

相关文章

HTML+CSS实训——Day01——安装好环境+写一个简单的应用启动页面

前言 学校最近开始实训周了&#xff0c;一上就是一个月&#xff0c;本来想在课上学点考研的东西的&#xff0c;但是无奈任务重&#xff0c;而且最后还能有点小奖励&#xff0c;就认真学了&#xff0c;再者说&#xff0c;html也挺重要的&#xff0c;学一学也不算浪费时间。 软…

【机器学习】 - 作业5: 基于Kmeans算法的AAAI会议论文聚类分析

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

C++ -- 存储类型说明

存储类型说明 提前说明&#xff1a; 存储持续性 &#xff1a; C使用三种不同的方案来存储诗句&#xff08;区别&#xff1a;数据保留在内存中的时间&#xff09; 自动存储持续性&#xff1a;在函数定义中声明的变量&#xff08;包含函数参数&#xff09;的存储持续性是自动的…

[Nacos] Nacos Client获取调用服务的提供者列表 (四)

文章目录 1.Nacos Client获取调用服务的提供者列表1.1 从Ribbon的负载均衡入手到Nacos Client获取调用服务的提高者列表1.2 getServers方法返回分析1.3 通过selectInstances方法查找Instances实例1.4 获取到要调用服务的serviceInfo Nacos Client 从Ribbon负载均衡调用服务。 …

【大数据】Presto(Trino)REST API 与执行计划介绍

文章目录 一、概述二、环境准备三、常用 REST API1&#xff09;worker 节点优雅退出2&#xff09;提交SQL查询请求3&#xff09;获取查询状态4&#xff09;获取查询结果5&#xff09;取消查询请求6&#xff09;获取Presto 节点信息7&#xff09;获取Presto服务器使用统计信息8&…

单模光纤二维模场分布的MATLAB仿真

在上一篇文章中&#xff0c;我们介绍了单模光纤的一维模场分布&#xff0c;能看出沿着径向的光场分布情况&#xff0c;并分析能量的分布 这一篇中&#xff0c;我们绘制光纤横截面上的二维光场分布&#xff1a;代码如下&#xff1a; clear close all V 2.4000; U 1.6453; W …

NC高频问题

1、在数据权限节点新增授权规则&#xff0c;规则明细需要增加一个查询条件。 答&#xff1a;使用系统管理员登录&#xff0c;在元数据过滤管理节点场景选择数据权限&#xff0c;将需要的字段勾选启用。 2、收款分析明细查询不到期初的应收数据。 答&#xff1a;该报表是查询收…

【Linux之IO系统编程学习】01.open函数使用 代码实现touch命令效果

【Linux之IO系统编程学习】 项目代码获取&#xff1a;https://gitee.com/chenshao777/linux_-io.git &#xff08;麻烦点个免费的Star哦&#xff0c;您的Star就是我的写作动力&#xff01;&#xff09; 01.open函数使用 & 代码实现touch命令 一、open函数&#xff08;ma…