Support 3-pin button module (VCC/GND/OUT) with auto polarity.

Sample idle level at boot; OUT on GPIO22, no internal pull fight.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-23 12:48:45 +08:00
parent 280c5ea97c
commit 7459f9bde1
9 changed files with 62 additions and 48 deletions

View File

@@ -3,27 +3,44 @@
#include <Arduino.h>
// 轻触开关:一端 → GPIO22,另一端 → GND(内部上拉,按下=LOW)
// 三脚按键模块:VCC→3.3V,GND→GND,OUT/S→GPIO22
// 开机采样空闲电平,反相即为“按下”(兼容按下拉高 / 按下拉低两种模块)
static uint32_t g_count = 0;
static bool g_stable_down = false;
static int g_stable_raw = HIGH;
static int g_stable_raw = LOW;
static int g_active_level = HIGH; // 按下时期望电平
static uint32_t g_change_ms = 0;
static int g_pending_raw = HIGH;
static int g_pending_raw = LOW;
static bool g_pending = false;
static constexpr uint32_t DEBOUNCE_MS = 25;
static constexpr uint32_t DEBOUNCE_MS = 30;
static bool raw_is_down(int raw) { return raw == g_active_level; }
void button_init() {
pinMode(BTN_PIN, INPUT_PULLUP);
delay(5);
g_count = 0;
g_stable_raw = digitalRead(BTN_PIN);
g_stable_down = (g_stable_raw == LOW);
// 模块自带上下拉,不要用内部上拉去顶它
pinMode(BTN_PIN, INPUT);
delay(30);
int high_n = 0;
for (int i = 0; i < 20; i++) {
if (digitalRead(BTN_PIN) == HIGH) {
high_n++;
}
delay(2);
}
const int idle = (high_n >= 10) ? HIGH : LOW;
g_active_level = (idle == HIGH) ? LOW : HIGH;
g_stable_raw = idle;
g_stable_down = false;
g_pending = false;
g_pending_raw = g_stable_raw;
g_pending_raw = idle;
g_change_ms = millis();
Serial.printf("Button tactile GPIO%d pullup, idle=%s (wire other side to GND)\n",
BTN_PIN, g_stable_raw == HIGH ? "HIGH" : "LOW");
g_count = 0;
Serial.printf(
"Button module GPIO%d INPUT idle=%s active=%s (VCC/GND/OUT)\n", BTN_PIN,
idle == HIGH ? "HIGH" : "LOW", g_active_level == HIGH ? "HIGH" : "LOW");
}
bool button_poll_press() {
@@ -38,12 +55,12 @@ bool button_poll_press() {
} else if ((now - g_change_ms) >= DEBOUNCE_MS) {
g_stable_raw = g_pending_raw;
g_pending = false;
const bool down = (g_stable_raw == LOW);
const bool down = raw_is_down(g_stable_raw);
if (down && !g_stable_down) {
g_stable_down = true;
g_count++;
Serial.printf("Button press count=%lu raw=%d\n", (unsigned long)g_count,
g_stable_raw);
Serial.printf("Button press count=%lu raw=%s\n", (unsigned long)g_count,
g_stable_raw == HIGH ? "HIGH" : "LOW");
return true;
}
g_stable_down = down;
@@ -65,3 +82,5 @@ void button_reset_count() {
bool button_is_down() { return g_stable_down; }
int button_raw_level() { return digitalRead(BTN_PIN); }
int button_active_level() { return g_active_level; }

View File

@@ -42,9 +42,10 @@ void ui_refresh_count() {
}
if (lbl_raw) {
const int lv = button_raw_level();
lv_label_set_text_fmt(lbl_raw, "GPIO%d: %s", BTN_PIN, lv ? "HIGH" : "LOW");
lv_label_set_text_fmt(lbl_raw, "OUT %s act=%s", lv ? "HIGH" : "LOW",
button_active_level() ? "HIGH" : "LOW");
lv_obj_set_style_text_color(lbl_raw,
lv_color_hex(lv ? COL_MUTED : 0x3DDC97), 0);
lv_color_hex(lv ? 0x3DDC97 : COL_MUTED), 0);
}
}
@@ -68,7 +69,7 @@ void ui_create() {
lv_obj_align(lbl_title, LV_ALIGN_TOP_MID, 0, 4);
lbl_pin = lv_label_create(scr);
lv_label_set_text_fmt(lbl_pin, "IO%d <-> switch <-> GND", BTN_PIN);
lv_label_set_text_fmt(lbl_pin, "OUT->GPIO%d VCC 3.3V", BTN_PIN);
lv_obj_set_style_text_color(lbl_pin, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lbl_pin, &lv_font_montserrat_14, 0);
lv_obj_align(lbl_pin, LV_ALIGN_TOP_MID, 0, 36);
@@ -92,7 +93,7 @@ void ui_create() {
lv_obj_align(lbl_state, LV_ALIGN_TOP_MID, 0, 126);
lbl_raw = lv_label_create(scr);
lv_label_set_text(lbl_raw, "GPIO22: HIGH");
lv_label_set_text(lbl_raw, "OUT --");
lv_obj_set_style_text_color(lbl_raw, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lbl_raw, &lv_font_montserrat_14, 0);
lv_obj_align(lbl_raw, LV_ALIGN_TOP_MID, 0, 152);