背景
Adafruit Feather ESP32-S3 TFT 开发板板载两个按键:
- Reset 按键:按下就会导致开发板复位,无需检测;
- Boot 按键:连接到 GPIO0,程序可以检测到。

从下面的原理图得知,BOOT 按键没有按下时是高电平,按下时为低电平。

基础按键检测
按键对应的管脚配置为 INPUT_PULLUP;
按键检测通过读取管脚电平,如果是 LOW 表示按键按下,如果是 HIGH 表示按键释放;
高级按键检测
引用 Bounce2 按键检测库,可以实现消抖检测按键,并设置消抖时间。
一般的使用流程如下:
1. 初始化全局变量 Bounce boot_btn = Bounce() 创建一个按键对象;
2. 调用 boot_btn.attach(pin, mode) 绑定按键对应的管脚并设置管脚上下拉模式;
3. 调用 boot_btn.interval(ms) 设置消抖时间;
4. 在 loop() 中周期性调用 boot_btn.update() 更新按键状态;
5. 在需要读取按键状态的代码位置调用 boot_btn.chagned() 判断状态是否发生改变,调用 boot_btn.read() 读取按键状态,按下还是释放;
我的按键检测示例
检测 BOOT 按键状态,只有当按键释放时切换 LED 状态,即每释放一次按键点亮/熄灭一次 LED。
演示视频:
【电子测光笔DIY--板载BOOT按键检测】 https://www.bilibili.com/video/BV1g7DZYLEpK/?share_source=copy_web&vd_source=a96f26eed24136ca40c5afd28478f4f8
源码如下:
// SPDX-FileCopyrightText: 2022 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
/* Includes
* --------------------------------------------------------------------------------------*/
#include <Arduino.h>
#include "Adafruit_LC709203F.h" /* 电池管理 -- 未检测到 */
#include "Adafruit_MAX1704X.h" /* 电池管理 -- 当前板载的 */
#include <Adafruit_NeoPixel.h>
#include <Adafruit_ST7789.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Bounce2.h> /* 按键检测 */
/* Constants -------------------------------------------------------------------------------------*/
#define LCD_WIDTH 240 /* 显示屏宽度 240 像素 */
#define LCD_HEIGHT 135 /* 显示屏高度 135 像素 */
/**
* @brief boot 按键的管脚
*/
#define BOOT_BTN_PIN 0
/**
* @brief 内置的 LED 管脚
*/
#define LED_PIN LED_BUILTIN
/* Variables
* -------------------------------------------------------------------------------------*/
/* 电池管理器,硬件对象 */
Adafruit_LC709203F lc_bat;
bool lc_bat_found = false;
/* 电池管理器,硬件对象 */
Adafruit_MAX17048 max_bat;
bool max_bat_found = false;
/* 显示屏,硬件对象 */
Adafruit_ST7789 display = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
/* 软件对象,画布:现在画布绘画,最后必须刷新到显示屏对象上 */
GFXcanvas16 canvas(LCD_WIDTH, LCD_HEIGHT); /* 这里仅分配一块连续的内存地址 */
/**
* @brief 定义 Boot 按键对象
*/
Bounce boot_btn = Bounce();
uint8_t led_status = 0; /* LED 状态:点亮还是熄灭 */
uint8_t loop_cnt = 0;
/* Function Declarations
* -----------------------------------------------------------------------------------------------*/
/**
* @brief 按键硬件初始化、对象初始化
*/
void btn_init(void)
{
pinMode(BOOT_BTN_PIN, INPUT_PULLUP); /* 按键硬件初始化,输入上拉模式 */
boot_btn.attach(BOOT_BTN_PIN); /* 按键对象绑定到硬件 */
boot_btn.interval(10); /* 设置按键消抖时间 */
}
void led_init(void)
{
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, led_status);
pinMode(NEOPIXEL_POWER, OUTPUT);
digitalWrite(NEOPIXEL_POWER, HIGH);
}
/**
* @brief 显示屏初始化,整屏刷新为黑色
*
* @param
*/
void screen_init(void)
{
/* turn on the TFT / I2C power supply */
pinMode(TFT_I2C_POWER, OUTPUT); /* 这个管脚是必须拉高的 */
digitalWrite(TFT_I2C_POWER, HIGH);
/* 因为这里旋转了屏幕的方向,所以初始化的屏幕尺寸和实际使用的尺寸颠倒了 */
display.init(LCD_HEIGHT, LCD_WIDTH); // Init ST7789 240x135
display.setRotation(3);
canvas.setFont(&FreeSans12pt7b);
canvas.setTextColor(ST77XX_WHITE);
canvas.fillScreen(ST77XX_BLACK);
canvas.setCursor(0, 25);
canvas.setTextColor(ST77XX_RED);
canvas.println("Adafruit Feather");
canvas.setTextColor(ST77XX_YELLOW);
canvas.println("ESP32-S3 TFT Demo");
/* 最后必须调用 display.drawRGBBitmap() 方法来刷新屏幕 */
display.drawRGBBitmap(0, 0, canvas.getBuffer(), LCD_WIDTH, LCD_HEIGHT);
pinMode(TFT_BACKLITE, OUTPUT);
digitalWrite(TFT_BACKLITE, HIGH);
}
void battery_monitor_init(void)
{
/* 初始化电池检测 */
if (lc_bat.begin()) { /* LC709X not found */
Serial.println("Found LC709203F");
Serial.print("Version: 0x");
Serial.println(lc_bat.getICversion(), HEX);
lc_bat.setPackSize(LC709203F_APA_500MAH);
lc_bat_found = true;
} else {
Serial.println(F(
"Couldnt find Adafruit LC709203F?\nChecking for Adafruit MAX1704X.."));
delay(200);
if (!max_bat.begin()) {
Serial.println(F("Couldnt find Adafruit MAX1704X?\nMake sure a battery "
"is plugged in!"));
while (1)
delay(10);
}
Serial.print(F("Found MAX17048"));
Serial.print(F(" with Chip ID: 0x"));
Serial.println(max_bat.getChipID(), HEX);
max_bat_found = true;
}
canvas.setTextColor(ST77XX_GREEN);
canvas.print("Battery: ");
canvas.setTextColor(ST77XX_WHITE);
if (lc_bat_found == true) {
canvas.print(lc_bat.cellVoltage(), 1);
canvas.print(" V / ");
canvas.print(lc_bat.cellPercent(), 0);
canvas.println("%");
} else {
canvas.print(max_bat.cellVoltage(), 1);
canvas.print(" V / ");
canvas.print(max_bat.cellPercent(), 0);
canvas.println("%");
}
canvas.setTextColor(ST77XX_BLUE);
canvas.print("Battery: ");
canvas.setTextColor(ST77XX_WHITE);
if (lc_bat_found) {
canvas.println("LC709X");
} else if (max_bat_found) {
canvas.println("MAX170X");
} else {
canvas.println("unknown");
}
/* 最后必须调用 display.drawRGBBitmap() 方法来刷新屏幕 */
display.drawRGBBitmap(0, 0, canvas.getBuffer(), LCD_WIDTH, LCD_HEIGHT);
}
/**
* @brief 在新的界面上显示按键是否按下
*
* @param isPressed
*/
void screen_button_status(bool isPressed)
{
canvas.fillScreen(ST77XX_BLACK);
canvas.setCursor(0, 25);
canvas.setTextColor(ST77XX_BLUE);
canvas.print("Button: ");
canvas.setTextColor(ST77XX_YELLOW);
if(isPressed) {
canvas.println("Pressed");
} else {
canvas.println("Released");
}
display.drawRGBBitmap(0, 0, canvas.getBuffer(), LCD_WIDTH, LCD_HEIGHT);
}
/**
* @brief 在主循环中调用此函数
*
* @param
*/
void btn_process(void)
{
/* 在此更新所有的按键状态 */
boot_btn.update();
if (boot_btn.changed()) { /* 按键状态变化了 */
if (boot_btn.read()) { /* 高电平表示按键释放 */
led_status = !led_status;
screen_button_status(false);
} else { /* 低电平表示按键按下 */
screen_button_status(true);
}
}
digitalWrite(LED_PIN, led_status);
}
/* Function Implementations
* ----------------------------------------------------------------------*/
void setup()
{
Serial.begin(115200);
uint32_t wait_cnt = 5;
while (!Serial && (wait_cnt-- > 0)) { /* 等待串口软件连接 */
delay(1000);
}
// delay(3000);
Serial.println("Adafruit Feather ESP32-S3 TFT");
Serial.println("Build: " + String(__DATE__) + " " + String(__TIME__));
screen_init();
btn_init();
led_init();
battery_monitor_init();
delay(10);
}
void loop()
{
btn_process();
loop_cnt++;
delay(10);
}
我要赚赏金
