在ESP32-C3上,你可以使用Arduino框架结合定时器中断来实现这样的按键状态机。
本例程实现按键消抖,单击,双击,多次,长按触发。
本例程使用库文件:
multi_button(核心按键库)
ESP32TimerInterrupt(定时器)
本例程编译环境:
board:airm2m_core_esp32c3
framework:arduino
IDE:vscode+platformio
仿真环境:New ESP32-C3 Project - Wokwi Simulator
/* ---------------- MAIN_CPP ---------------- */
#include "Arduino.h"
#include "multi_button.h"
#include "ESP32TimerInterrupt.h"
unsigned int SWPin = 3;
Button SWButton;
// Init ESP32 timer 1
ESP32Timer ITimer1(1);
uint8_t ReadSwButton()
{
return digitalRead(SWPin);
}
// 单击回调函数
void sigleClickCallback(void *)
{
Serial.println("Single Click");
}
// 双击回调函数
void doubleClickCallback(void *)
{
Serial.println("Double Click");
}
// 三连击回调函数
void tripClickCallback(void *)
{
Serial.println("Triple Click");
}
// 长按回调函数
void longClickCallback(void *)
{
Serial.println("Long Click");
}
// 定时器中断回调函数
bool TimerHandler1(void *timerNo)
{
// 按键核心函数
button_ticks();
return true;
}
void setup()
{
pinMode(SWPin, INPUT_PULLUP);
Serial.begin(115200);
button_init(&SWButton, ReadSwButton, 0);
button_attach(&SWButton, SINGLE_CLICK, sigleClickCallback);
button_attach(&SWButton, LONG_PRESS_HOLD, longClickCallback);
button_attach(&SWButton, DOUBLE_CLICK, doubleClickCallback);
// !TRIPLE_CLICK 触发事件 可自定义添加
button_attach(&SWButton, TRIPLE_CLICK, tripClickCallback);
button_start(&SWButton);
delay(500);
// Interval in microsecs
//! 此处5*1000 配置定时器5ms中断周期
if (ITimer1.attachInterruptInterval(TICKS_INTERVAL * 1000, TimerHandler1))
{
Serial.print(F("Starting ITimer1 OK, millis() = "));
Serial.println(millis());
}
else
Serial.println(F("Can't set ITimer1. Select another freq. or timer"));
}
void loop()
{
delay(500);
}
实现消抖部分的核心程序:
/* ------------- MULTI_BUTTON_H ------------- */
#ifndef _MULTI_BUTTON_H_
#define _MULTI_BUTTON_H_
#include "stdint.h"
#include "string.h"
// According to your need to modify the constants.
#define TICKS_INTERVAL 5 // ms
#define DEBOUNCE_TICKS 3 // MAX 8
#define SHORT_TICKS (300 / TICKS_INTERVAL) // 单击触发时间
#define LONG_TICKS (1000 / TICKS_INTERVAL) // 长按触发时间
typedef void (*BtnCallback)(void *);
typedef enum
{
PRESS_DOWN = 0,
PRESS_UP,
PRESS_REPEAT,
SINGLE_CLICK,
DOUBLE_CLICK,
//! 此处可添加自定义的按键事件
TRIPLE_CLICK,
LONG_RRESS_START,
LONG_PRESS_HOLD,
number_of_event,
NONE_PRESS
} PressEvent;
typedef struct Button
{
uint16_t ticks;
uint8_t repeat : 4;
uint8_t event : 4;
uint8_t state : 3;
uint8_t debounce_cnt : 3;
uint8_t active_level : 1;
uint8_t button_level : 1;
uint8_t (*hal_button_Level)(void);
BtnCallback cb[number_of_event];
struct Button *next;
} Button;
#ifdef __cplusplus
extern "C"
{
#endif
void button_init(struct Button *handle, uint8_t (*pin_level)(), uint8_t active_level);
void button_attach(struct Button *handle, PressEvent event, BtnCallback cb);
PressEvent get_button_event(struct Button *handle);
int button_start(struct Button *handle);
void button_stop(struct Button *handle);
void button_ticks(void);
#ifdef __cplusplus
}
#endif
#endif
演示:
ESP32按键demo