Fix tactile switch wiring: GPIO22 to GND, show live pin level.

Clarify 4-pin foot pairing and debounce for bare pushbutton.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-23 12:46:31 +08:00
parent 2d1d49c038
commit 280c5ea97c
8 changed files with 94 additions and 60 deletions

View File

@@ -1,22 +1,32 @@
# 按钮计数(CYD)
# 轻触开关计数(CYD)
触控 + LVGL 参考 `hw269test` / `tftest`。GPIO22 读按钮:每按一次,屏幕计数 +1。
触控 + LVGL 参考 `hw269test`。GPIO22 读 **轻触带帽开关**:每按一次,屏幕计数 +1。
## 硬件
| 项目 | 说明 |
|------|------|
| 板子 | CYD ESP32-2432S028R |
| 模块 | 轻触按钮 / 按键传感器(SIG 输出) |
| 信号 | **GPIO22**(内部上拉,按下为 LOW) |
| 开关 | 轻触开关(带帽),瞬时闭合 |
| 引脚 | **GPIO22** |
接线:`VCC→3.3V`,`GND→GND`,`SIG→GPIO22`。
### 接线(重要)
```
GPIO22 ── 开关一脚
GND ── 开关另一脚
```
- 不要接 3.3V / VCC
- **四脚轻触**:矩形四脚中,同侧两脚内部常通;要接 **对角** 或 **能通断的一对**,不要接已经常通的那一对
- 固件内部上拉:松开=HIGH,按下=LOW
屏上会显示 `GPIO22: HIGH/LOW`:按下应变为 **LOW**;若一直 HIGH,多半是接线或脚对选错。
## 操作
- 按一下物理按钮:计数 +1
- 屏幕显示当前计数与 PRESSED / IDLE
- 触控 **Reset**:计数清零
- 按一下开关:计数 +1
- 触控 **Reset**:清零
## 构建
@@ -24,12 +34,9 @@
pio run -e cyd -t upload
```
预编译包:
预编译:
```powershell
cd firmware\cyd
.\flash.ps1
# 或 .\flash.ps1 -Port COMx
```
更新预编译包:`.\firmware\export_from_build.ps1`

View File

@@ -1,5 +1,5 @@
name: CYD Button (cyd)
git: 22a3c46
git: 2d1d49c
date: 2026-10-23
board: ESP32-2432S028R (ILI9341)
features: SoftSPI touch, LVGL, button SIG on GPIO22 count+1
@@ -12,5 +12,5 @@ offsets:
sha256:
bootloader.bin 3D234A7471F67B013686DABD4DEE7C1FA915C9928463616A94BC9297ACF1ABF8
boot_app0.bin F94C5D786A7A8FAB06AC5D10E33BF37711A6697636DC037559EA19CC410A17F0
firmware.bin 66E2CE73AA8F010E314CE1B9664106250DD07D92B726DEF592FE123C5FC2F88A
firmware.bin B57118B1598F34B9737625C04E1EEB6C88395C639017288D69A6AB1BEC0C633C
partitions.bin 148B959CBFF1C38AA8E1D5C0BA9D612C54997B945E56A63F41223EEF650653A1

Binary file not shown.

View File

@@ -8,3 +8,5 @@ bool button_poll_press();
uint32_t button_count();
void button_reset_count();
bool button_is_down();
/** 原始电平:1=HIGH,0=LOW(便于接线排查) */
int button_raw_level();

View File

@@ -10,7 +10,7 @@
#define CYD_TOUCH_CLK 25
#define CYD_TOUCH_CS 33
// 按钮传感器 SIG → GPIO22(内部上拉,按下为 LOW)
// 轻触开关:一脚 → GPIO22,另一脚 → GND(内部上拉,按下为 LOW)
#define BTN_PIN 22
#define SCREEN_WIDTH 240

View File

@@ -3,46 +3,56 @@
#include <Arduino.h>
// 轻触开关:一端 → GPIO22,另一端 → GND(内部上拉,按下=LOW)
static uint32_t g_count = 0;
static bool g_stable_down = false;
static bool g_last_raw = false;
static uint32_t g_last_change_ms = 0;
static constexpr uint32_t DEBOUNCE_MS = 40;
static int g_stable_raw = HIGH;
static uint32_t g_change_ms = 0;
static int g_pending_raw = HIGH;
static bool g_pending = false;
static constexpr uint32_t DEBOUNCE_MS = 25;
void button_init() {
pinMode(BTN_PIN, INPUT_PULLUP);
delay(5);
g_count = 0;
g_stable_down = false;
g_last_raw = (digitalRead(BTN_PIN) == LOW);
g_last_change_ms = millis();
Serial.printf("Button GPIO%d INPUT_PULLUP (press=LOW)\n", BTN_PIN);
g_stable_raw = digitalRead(BTN_PIN);
g_stable_down = (g_stable_raw == LOW);
g_pending = false;
g_pending_raw = g_stable_raw;
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");
}
bool button_poll_press() {
const bool raw_down = (digitalRead(BTN_PIN) == LOW);
const int raw = digitalRead(BTN_PIN);
const uint32_t now = millis();
if (raw_down != g_last_raw) {
g_last_raw = raw_down;
g_last_change_ms = now;
if (raw != g_stable_raw) {
if (!g_pending || raw != g_pending_raw) {
g_pending = true;
g_pending_raw = raw;
g_change_ms = now;
} else if ((now - g_change_ms) >= DEBOUNCE_MS) {
g_stable_raw = g_pending_raw;
g_pending = false;
const bool down = (g_stable_raw == LOW);
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);
return true;
}
g_stable_down = down;
}
} else {
g_pending = false;
}
if ((now - g_last_change_ms) < DEBOUNCE_MS) {
return false;
}
if (raw_down == g_stable_down) {
return false;
}
g_stable_down = raw_down;
if (!g_stable_down) {
return false; // 只计按下边沿
}
g_count++;
Serial.printf("Button press count=%lu\n", (unsigned long)g_count);
return true;
return false;
}
uint32_t button_count() { return g_count; }
@@ -53,3 +63,5 @@ void button_reset_count() {
}
bool button_is_down() { return g_stable_down; }
int button_raw_level() { return digitalRead(BTN_PIN); }

View File

@@ -14,7 +14,7 @@ void setup() {
Serial.begin(460800);
delay(200);
Serial.println();
Serial.printf("LVGL %d.%d.%d | Button sensor GPIO%d\n", lv_version_major(),
Serial.printf("LVGL %d.%d.%d | Tactile button GPIO%d\n", lv_version_major(),
lv_version_minor(), lv_version_patch(), BTN_PIN);
Serial.println("BOOT_OK");
@@ -39,16 +39,16 @@ void setup() {
}
void loop() {
if (button_poll_press()) {
const bool pressed = button_poll_press();
static bool last_down = false;
static int last_raw = -1;
const bool down = button_is_down();
const int raw = button_raw_level();
if (pressed || down != last_down || raw != last_raw) {
last_down = down;
last_raw = raw;
ui_refresh_count();
} else {
// 按下/松开时刷新状态字,但不重复计数
static bool last_down = false;
const bool down = button_is_down();
if (down != last_down) {
last_down = down;
ui_refresh_count();
}
}
lv_timer_handler();

View File

@@ -17,6 +17,7 @@ static lv_obj_t *lbl_pin;
static lv_obj_t *lbl_count;
static lv_obj_t *lbl_hint;
static lv_obj_t *lbl_state;
static lv_obj_t *lbl_raw;
static lv_obj_t *btn_reset;
static lv_obj_t *lbl_reset;
@@ -39,6 +40,12 @@ void ui_refresh_count() {
lv_obj_set_style_text_color(lbl_state,
lv_color_hex(down ? 0x3DDC97 : COL_MUTED), 0);
}
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_obj_set_style_text_color(lbl_raw,
lv_color_hex(lv ? COL_MUTED : 0x3DDC97), 0);
}
}
static void on_reset(lv_event_t *e) {
@@ -58,35 +65,41 @@ void ui_create() {
lv_label_set_text(lbl_title, "Button");
lv_obj_set_style_text_color(lbl_title, lv_color_hex(COL_INK), 0);
lv_obj_set_style_text_font(lbl_title, &lv_font_montserrat_28, 0);
lv_obj_align(lbl_title, LV_ALIGN_TOP_MID, 0, 6);
lv_obj_align(lbl_title, LV_ALIGN_TOP_MID, 0, 4);
lbl_pin = lv_label_create(scr);
lv_label_set_text_fmt(lbl_pin, "SIG -> GPIO%d (press +1)", BTN_PIN);
lv_label_set_text_fmt(lbl_pin, "IO%d <-> switch <-> GND", 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, 40);
lv_obj_align(lbl_pin, LV_ALIGN_TOP_MID, 0, 36);
lbl_count = lv_label_create(scr);
lv_label_set_text(lbl_count, "0");
lv_obj_set_style_text_color(lbl_count, lv_color_hex(COL_ACCENT), 0);
lv_obj_set_style_text_font(lbl_count, &lv_font_montserrat_28, 0);
lv_obj_align(lbl_count, LV_ALIGN_TOP_MID, 0, 78);
lv_obj_align(lbl_count, LV_ALIGN_TOP_MID, 0, 68);
lbl_hint = lv_label_create(scr);
lv_label_set_text(lbl_hint, "count");
lv_obj_set_style_text_color(lbl_hint, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lbl_hint, &lv_font_montserrat_14, 0);
lv_obj_align(lbl_hint, LV_ALIGN_TOP_MID, 0, 116);
lv_obj_align(lbl_hint, LV_ALIGN_TOP_MID, 0, 104);
lbl_state = lv_label_create(scr);
lv_label_set_text(lbl_state, "IDLE");
lv_obj_set_style_text_color(lbl_state, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lbl_state, &lv_font_montserrat_20, 0);
lv_obj_align(lbl_state, LV_ALIGN_TOP_MID, 0, 142);
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_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);
btn_reset = lv_button_create(scr);
lv_obj_set_size(btn_reset, UI_HOR_RES - 48, 48);
lv_obj_align(btn_reset, LV_ALIGN_TOP_MID, 0, 180);
lv_obj_set_size(btn_reset, UI_HOR_RES - 48, 44);
lv_obj_align(btn_reset, LV_ALIGN_TOP_MID, 0, 184);
style_btn(btn_reset, COL_BTN);
lv_obj_add_event_cb(btn_reset, on_reset, LV_EVENT_CLICKED, nullptr);
lbl_reset = lv_label_create(btn_reset);