添加按键功能
This commit is contained in:
@@ -29,10 +29,13 @@ list(APPEND srcs "utils/sb_aes.c")
|
||||
|
||||
list(APPEND srcs "drivers/sertrf/sertrf.c")
|
||||
list(APPEND srcs "drivers/sertrf/device.c")
|
||||
list(APPEND srcs "drivers/sertrf/key.c")
|
||||
|
||||
list(APPEND srcs "drivers/led_strip/led_strip.c")
|
||||
list(APPEND srcs "drivers/led_strip/led_strip_encoder.c")
|
||||
|
||||
list(APPEND srcs "drivers/pin_io/pin_io.c")
|
||||
|
||||
if(CONFIG_BUILD_BLE)
|
||||
list(APPEND srcs "drivers/data_port/ble_spp/ble_spp_server.c")
|
||||
list(APPEND srcs "drivers/data_port/ble_spp/ble_spp_server_shell.c")
|
||||
|
||||
102
app/drivers/pin_io/pin_io.c
Normal file
102
app/drivers/pin_io/pin_io.c
Normal file
@@ -0,0 +1,102 @@
|
||||
#include "pin_io.h"
|
||||
|
||||
/* 配置 */
|
||||
#include "config/board_config.h"
|
||||
#include "config/app_config.h"
|
||||
#include "config/app_log.h"
|
||||
|
||||
#if defined(CONFIG_CAP_LED_STRIP)
|
||||
#include "led_strip/config/led_strip_config.h"
|
||||
#endif
|
||||
|
||||
/* SDK */
|
||||
#include "driver/gpio.h"
|
||||
|
||||
/* 通用模块 */
|
||||
#include "button/button.h"
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
|
||||
#define SYS_LOG_DOMAIN "PIN"
|
||||
#include "sys_log.h"
|
||||
|
||||
/**
|
||||
* @brief IO 基本操作:配置为通用输入
|
||||
*
|
||||
* @param pin 0..n
|
||||
*/
|
||||
void pin_cfg_input(const cfg_board_pin_io_t *pin)
|
||||
{
|
||||
if (GPIO_USED(pin->pin) == false)
|
||||
{
|
||||
SYS_LOG_WRN("pin %d not used", pin->pin);
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_config_t io_conf;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pull_up_en = (pin->en_lev == 0 ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE);
|
||||
io_conf.pull_down_en = (pin->en_lev ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE);
|
||||
io_conf.pin_bit_mask = 1ULL << pin->pin;
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IO 基本操作:获取当前输入电平是否为有效的电平
|
||||
*
|
||||
* @param pin 0..n
|
||||
* @retval true 对应预设为有效的电平
|
||||
* @retval false 对应预设为非有效的电平
|
||||
*/
|
||||
bool pin_get_valid(const cfg_board_pin_io_t *pin)
|
||||
{
|
||||
if (GPIO_USED(pin->pin) == false)
|
||||
{
|
||||
SYS_LOG_WRN("pin %d not used", pin->pin);
|
||||
return false;
|
||||
}
|
||||
|
||||
return gpio_get_level(pin->pin) ^ !pin->en_lev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IO 基本操作:配置为通用输出
|
||||
*
|
||||
* @param pin 0..n
|
||||
*/
|
||||
void pin_cfg_output(const cfg_board_pin_io_t *pin)
|
||||
{
|
||||
if (GPIO_USED(pin->pin) == false)
|
||||
{
|
||||
SYS_LOG_WRN("pin %d not used", pin->pin);
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_config_t io_conf;
|
||||
io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
||||
io_conf.pin_bit_mask = 1ULL << pin->pin;
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IO 基本操作:设置使输出是否为有效的电平
|
||||
*
|
||||
* @param pin 0..n
|
||||
* @param en false: 使输出为对应预设为非有效的电平; true: 使输出为对应预设为有效的电平
|
||||
*/
|
||||
void pin_set_valid(const cfg_board_pin_io_t *pin, bool en)
|
||||
{
|
||||
if (GPIO_USED(pin->pin) == false)
|
||||
{
|
||||
SYS_LOG_WRN("pin %d not used", pin->pin);
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_set_level((gpio_num_t)pin->pin, !pin->en_lev ^ !!en);
|
||||
}
|
||||
|
||||
23
app/drivers/pin_io/pin_io.h
Normal file
23
app/drivers/pin_io/pin_io.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @file pin_io.h
|
||||
* @author LokLiang
|
||||
* @brief 1. GPIO 的基本驱动, 2. 控制板载电压的开关
|
||||
* @version 0.1
|
||||
* @date 2024-04-16
|
||||
*
|
||||
* @copyright Copyright (c) 2024
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sys_types.h"
|
||||
#include "config/board_config.h"
|
||||
|
||||
void pin_cfg_input(const cfg_board_pin_io_t *pin);
|
||||
bool pin_get_valid(const cfg_board_pin_io_t *pin);
|
||||
|
||||
void pin_cfg_output(const cfg_board_pin_io_t *pin);
|
||||
void pin_set_valid(const cfg_board_pin_io_t *pin, bool en);
|
||||
|
||||
|
||||
162
app/drivers/sertrf/key.c
Normal file
162
app/drivers/sertrf/key.c
Normal file
@@ -0,0 +1,162 @@
|
||||
#include "key.h"
|
||||
|
||||
button_t btn;
|
||||
|
||||
cfg_board_pin_io_t key_switch = {
|
||||
.pin = 9,
|
||||
.en_lev = 0,};
|
||||
// 新增事件类型
|
||||
// EVT_DOUBLE_CLICK: 双击
|
||||
// EVT_SINGLE_LONG_PRESS: 单击后长按
|
||||
|
||||
bool key_single_click = 0,key_press_down = 0,key_press_up = 0;
|
||||
|
||||
|
||||
// 用户在此处理按键事件
|
||||
static void my_button_handler(button_event_t evt) {
|
||||
switch (evt) {
|
||||
case EVT_PRESS_DOWN: //按下
|
||||
// SYS_LOG_INF("[Event] PRESS_DOWN");
|
||||
key_press_down = true;
|
||||
key_press_up = false;
|
||||
break;
|
||||
case EVT_PRESS_UP: //松开
|
||||
// SYS_LOG_INF("[Event] PRESS_UP");
|
||||
key_press_up = true;
|
||||
key_press_down = false;
|
||||
break;
|
||||
case EVT_SINGLE_CLICK: //单击
|
||||
key_single_click = true;
|
||||
// SYS_LOG_INF("[Event] SINGLE_CLICK");
|
||||
break;
|
||||
case EVT_DOUBLE_CLICK: //双击
|
||||
// SYS_LOG_INF("[Event] DOUBLE_CLICK");
|
||||
break;
|
||||
case EVT_LONG_PRESS: //长按
|
||||
// SYS_LOG_INF("[Event] LONG_PRESS");
|
||||
break;
|
||||
case EVT_SINGLE_LONG_PRESS: //单击后长按
|
||||
wifi_mode_switch(NULL);
|
||||
SYS_LOG_INF("[Event] SINGLE_LONG_PRESS");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化按键
|
||||
static void button_init(button_t *btn, bool (*read_pin)(void), button_cb_t cb) {
|
||||
btn->read_pin = read_pin;
|
||||
btn->callback = cb;
|
||||
btn->stable_state = read_pin() ? 1 : 0;
|
||||
btn->debounce_cnt = 0;
|
||||
btn->tick_cnt = 0;
|
||||
btn->state = 0;
|
||||
btn->click_count = 0; // 新增计数
|
||||
}
|
||||
|
||||
// 每次调用间隔 5ms (os_work_later 参数)
|
||||
static void button_scan(button_t *btn) {
|
||||
bool level = btn->read_pin();
|
||||
|
||||
// 防抖
|
||||
if (level != btn->stable_state) {
|
||||
if (++btn->debounce_cnt >= DEBOUNCE_TICKS) {
|
||||
btn->stable_state = level;
|
||||
btn->debounce_cnt = 0;
|
||||
}
|
||||
} else {
|
||||
btn->debounce_cnt = 0;
|
||||
}
|
||||
|
||||
switch (btn->state) {
|
||||
case 0: // 空闲->按下
|
||||
if (btn->stable_state) {
|
||||
btn->callback(EVT_PRESS_DOWN);
|
||||
btn->tick_cnt = 0;
|
||||
btn->state = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // 按下计时
|
||||
btn->tick_cnt++;
|
||||
if (!btn->stable_state) {
|
||||
// 松开
|
||||
btn->callback(EVT_PRESS_UP);
|
||||
if (btn->tick_cnt < LONG_PRESS_TICKS) {
|
||||
// 短按,统计点击次数
|
||||
btn->click_count++;
|
||||
btn->tick_cnt = 0;
|
||||
btn->state = 2; // 等待双击
|
||||
} else {
|
||||
// 长按释放
|
||||
btn->callback(EVT_LONG_PRESS);
|
||||
btn->click_count = 0;
|
||||
btn->state = 0;
|
||||
}
|
||||
} else if (btn->tick_cnt >= LONG_PRESS_TICKS) {
|
||||
// 长按开始
|
||||
// 可加 EVT_LONG_PRESS_START 如需区分开始和持续
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // 等待双击或单击后长按
|
||||
btn->tick_cnt++;
|
||||
if (btn->stable_state) {
|
||||
// 再次按下
|
||||
if (btn->click_count == 1) {
|
||||
btn->callback(EVT_PRESS_DOWN);
|
||||
btn->state = 3; // 第二次按下
|
||||
btn->tick_cnt = 0;
|
||||
}
|
||||
} else if (btn->tick_cnt > DOUBLE_CLICK_WINDOW) {
|
||||
// 超过双击时间窗口
|
||||
if (btn->click_count == 1) {
|
||||
btn->callback(EVT_SINGLE_CLICK);
|
||||
}
|
||||
btn->click_count = 0;
|
||||
btn->state = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // 第二次按下状态
|
||||
btn->tick_cnt++;
|
||||
if (!btn->stable_state) {
|
||||
// 第二次松开 -> 双击
|
||||
btn->callback(EVT_PRESS_UP);
|
||||
if (btn->tick_cnt < LONG_PRESS_TICKS) {
|
||||
btn->callback(EVT_DOUBLE_CLICK);
|
||||
} else {
|
||||
// 单击后长按
|
||||
btn->callback(EVT_SINGLE_LONG_PRESS);
|
||||
}
|
||||
btn->click_count = 0;
|
||||
btn->state = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
btn->state = 0;
|
||||
btn->click_count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool read_button_pin(void) {
|
||||
// HAL_GPIO_ReadPin == GPIO_PIN_SET(1) 时,表示松开
|
||||
// return pin_get_valid(&g_cfg_board->key_switch_mode);
|
||||
return pin_get_valid(&key_switch);
|
||||
}
|
||||
|
||||
//添加自定义初始化
|
||||
void _work_button(void *arg) {
|
||||
button_scan(&btn);
|
||||
os_work_later(10);
|
||||
}
|
||||
|
||||
void button_work_init() {
|
||||
button_init(&btn, read_button_pin, my_button_handler);
|
||||
|
||||
static os_work_t work_handler_button;
|
||||
os_work_create(&work_handler_button, "work-button", _work_button, NULL, OS_PRIORITY_NORMAL);
|
||||
os_work_submit(default_os_work_q_hdl, &work_handler_button, 10);
|
||||
}
|
||||
48
app/drivers/sertrf/key.h
Normal file
48
app/drivers/sertrf/key.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h> // 如果在裸机下,用平台自带的延时函数替代
|
||||
#include "../pin_io/pin_io.h"
|
||||
#include "../../config/board_config.h"
|
||||
#include "../../config/app_config.h"
|
||||
#include "sys_log.h"
|
||||
#include "os/os.h"
|
||||
#include "device.h"
|
||||
|
||||
// 按键事件类型
|
||||
typedef enum {
|
||||
EVT_NONE = 0, // 无事件
|
||||
EVT_PRESS_DOWN, // 按下
|
||||
EVT_PRESS_UP, // 松开
|
||||
EVT_SINGLE_CLICK, // 单击
|
||||
EVT_DOUBLE_CLICK, // 双击
|
||||
EVT_LONG_PRESS, // 长按释放
|
||||
EVT_SINGLE_LONG_PRESS // 单击后长按
|
||||
} button_event_t;
|
||||
|
||||
// 回调函数原型
|
||||
typedef void (*button_cb_t)(button_event_t evt);
|
||||
|
||||
// 配置参数
|
||||
#define DEBOUNCE_TICKS 3 // 连续3次读到新值才确认变化
|
||||
#define LONG_PRESS_TICKS 100 // 100*SCAN_INTERVAL_US >=1s 触发长按阈值
|
||||
#define DOUBLE_CLICK_WINDOW 30 // 30*SCAN_INTERVAL_US <=300ms 双击间隔窗口
|
||||
#define SCAN_INTERVAL_US 10000 // 10ms 扫描一次
|
||||
|
||||
// 按键处理结构体
|
||||
typedef struct {
|
||||
bool (*read_pin)(void); // 读取 GPIO,按下返回 true
|
||||
button_cb_t callback; // 事件回调
|
||||
|
||||
uint8_t stable_state; // 去抖后稳定状态
|
||||
uint8_t debounce_cnt; // 去抖计数
|
||||
uint16_t tick_cnt; // 持续按下或间隔计数
|
||||
uint8_t state; // 状态机状态
|
||||
uint8_t click_count; // 短按计数
|
||||
} button_t;
|
||||
|
||||
extern bool key_single_click,key_press_down,key_press_up;
|
||||
void _work_button(void *arg);
|
||||
void button_work_init();
|
||||
Reference in New Issue
Block a user