优化调试新增按键驱动
This commit is contained in:
351
BSP/Src/bsp_key.c
Normal file
351
BSP/Src/bsp_key.c
Normal file
@ -0,0 +1,351 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : bsp_key.c
|
||||
* @brief : Board support package key driver implementation
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
#include "bsp_key.h"
|
||||
#include "bsp_config.h"
|
||||
#include "hal_gpio.h"
|
||||
#include "bsp_board.h"
|
||||
#include "bsp_board_manager.h"
|
||||
#include "hal_delay.h"
|
||||
|
||||
/**
|
||||
* @brief Key debounce configuration
|
||||
*/
|
||||
#define KEY_DEBOUNCE_COUNT 5 /* Debounce count (each update is ~10ms, so 50ms debounce) */
|
||||
#define KEY_LONG_PRESS_TIME 1000 /* Long press time in ms */
|
||||
#define KEY_REPEAT_INTERVAL 200 /* Repeat interval in ms */
|
||||
#define KEY_SHORT_PRESS_TIME 200 /* Short press time in ms */
|
||||
#define KEY_UPDATE_INTERVAL 10 /* Update interval in ms */
|
||||
|
||||
/**
|
||||
* @brief Key configuration structure
|
||||
*/
|
||||
typedef struct {
|
||||
hal_gpio_port_t port;
|
||||
hal_gpio_pin_t pin;
|
||||
uint8_t active_high;
|
||||
} bsp_key_config_t;
|
||||
|
||||
/**
|
||||
* @brief Key state structure for debouncing and event detection
|
||||
*/
|
||||
typedef struct {
|
||||
/* Debounce state */
|
||||
bsp_key_state_t current_state; /* Current debounced state */
|
||||
bsp_key_state_t previous_state; /* Previous debounced state */
|
||||
uint8_t debounce_counter; /* Debounce counter */
|
||||
|
||||
/* Event flags */
|
||||
uint8_t press_event; /* Press event flag */
|
||||
uint8_t release_event; /* Release event flag */
|
||||
uint8_t long_press_event; /* Long press event flag */
|
||||
uint8_t repeat_event; /* Repeat event flag */
|
||||
uint8_t short_press_event; /* Short press event flag */
|
||||
|
||||
/* Timing variables */
|
||||
uint32_t press_start_time; /* Press start time in ms */
|
||||
uint32_t last_repeat_time; /* Last repeat event time in ms */
|
||||
uint32_t current_time; /* Current time in ms */
|
||||
|
||||
/* Configuration */
|
||||
uint16_t long_press_time; /* Long press time in ms */
|
||||
uint16_t repeat_interval; /* Repeat interval in ms */
|
||||
uint16_t short_press_time; /* Short press time in ms */
|
||||
|
||||
/* Key configuration */
|
||||
const bsp_button_config_t* button_config;
|
||||
} bsp_key_internal_state_t;
|
||||
|
||||
/**
|
||||
* @brief Key state table for debouncing and event detection
|
||||
*/
|
||||
static bsp_key_internal_state_t key_state_table[BSP_KEY_ID_MAX] = {0};
|
||||
|
||||
/**
|
||||
* @brief Get current board button configuration
|
||||
*/
|
||||
static const bsp_button_config_t* bsp_key_get_button_config(bsp_key_id_t key_id) {
|
||||
const bsp_board_config_t* board_config = bsp_board_get_config();
|
||||
if (board_config && key_id < board_config->buttons.count) {
|
||||
return &board_config->buttons.buttons[key_id];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read raw key state (without debounce)
|
||||
* @param key_id: Key ID
|
||||
* @retval Raw key state
|
||||
*/
|
||||
static bsp_key_state_t bsp_key_read_raw(bsp_key_id_t key_id) {
|
||||
bsp_key_state_t state;
|
||||
|
||||
const bsp_button_config_t* button_config = bsp_key_get_button_config(key_id);
|
||||
if (button_config) {
|
||||
hal_gpio_pin_state_t gpio_state;
|
||||
|
||||
/* Read GPIO pin state */
|
||||
gpio_state = hal_gpio_read_pin(button_config->port, button_config->pin);
|
||||
|
||||
/* Convert to key state based on active level */
|
||||
if (button_config->active_high) {
|
||||
state = (gpio_state == HAL_GPIO_PIN_SET) ? BSP_KEY_STATE_PRESSED : BSP_KEY_STATE_RELEASED;
|
||||
} else {
|
||||
state = (gpio_state == HAL_GPIO_PIN_RESET) ? BSP_KEY_STATE_PRESSED : BSP_KEY_STATE_RELEASED;
|
||||
}
|
||||
} else {
|
||||
state = BSP_KEY_STATE_RELEASED;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current system time in milliseconds
|
||||
* @retval Current time in ms
|
||||
*/
|
||||
static uint32_t bsp_key_get_time_ms(void) {
|
||||
/* Use HAL tick function */
|
||||
return hal_get_tick();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize all keys
|
||||
*/
|
||||
void bsp_key_init(void) {
|
||||
uint8_t i;
|
||||
|
||||
/* Get current board configuration */
|
||||
const bsp_board_config_t* board_config = bsp_board_get_config();
|
||||
|
||||
/* Initialize key state table */
|
||||
for (i = 0; i < BSP_KEY_ID_MAX; i++) {
|
||||
/* Get button configuration for this key */
|
||||
const bsp_button_config_t* button_config = bsp_key_get_button_config((bsp_key_id_t)i);
|
||||
|
||||
/* Initialize with current state */
|
||||
key_state_table[i].current_state = bsp_key_read_raw((bsp_key_id_t)i);
|
||||
key_state_table[i].previous_state = key_state_table[i].current_state;
|
||||
key_state_table[i].debounce_counter = 0;
|
||||
|
||||
/* Clear event flags */
|
||||
key_state_table[i].press_event = 0;
|
||||
key_state_table[i].release_event = 0;
|
||||
key_state_table[i].long_press_event = 0;
|
||||
key_state_table[i].repeat_event = 0;
|
||||
key_state_table[i].short_press_event = 0;
|
||||
|
||||
/* Initialize timing variables */
|
||||
key_state_table[i].press_start_time = 0;
|
||||
key_state_table[i].last_repeat_time = 0;
|
||||
key_state_table[i].current_time = 0;
|
||||
|
||||
/* Set default configuration */
|
||||
key_state_table[i].long_press_time = KEY_LONG_PRESS_TIME;
|
||||
key_state_table[i].repeat_interval = KEY_REPEAT_INTERVAL;
|
||||
key_state_table[i].short_press_time = KEY_SHORT_PRESS_TIME;
|
||||
|
||||
/* Store button configuration */
|
||||
key_state_table[i].button_config = button_config;
|
||||
}
|
||||
|
||||
/* Call board-specific button initialization if available */
|
||||
if (board_config && board_config->button_init) {
|
||||
board_config->button_init(&board_config->buttons);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update key state (call this function periodically, e.g. every 10ms)
|
||||
*/
|
||||
void bsp_key_update(void) {
|
||||
uint8_t i;
|
||||
uint32_t current_time = bsp_key_get_time_ms();
|
||||
|
||||
for (i = 0; i < BSP_KEY_ID_MAX; i++) {
|
||||
/* Skip if button configuration is not available */
|
||||
if (!key_state_table[i].button_config) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bsp_key_state_t raw_state = bsp_key_read_raw((bsp_key_id_t)i);
|
||||
bsp_key_internal_state_t* key_state = &key_state_table[i];
|
||||
|
||||
/* Update current time */
|
||||
key_state->current_time = current_time;
|
||||
|
||||
/* Debounce logic - optimized version */
|
||||
if (raw_state != key_state->current_state) {
|
||||
/* State is changing, increment counter */
|
||||
if (++key_state->debounce_counter >= KEY_DEBOUNCE_COUNT) {
|
||||
/* Debounce count reached, update state */
|
||||
key_state->previous_state = key_state->current_state;
|
||||
key_state->current_state = raw_state;
|
||||
key_state->debounce_counter = 0;
|
||||
|
||||
if (raw_state == BSP_KEY_STATE_PRESSED) {
|
||||
/* Key pressed event */
|
||||
key_state->press_event = 1;
|
||||
key_state->release_event = 0;
|
||||
key_state->short_press_event = 0;
|
||||
|
||||
/* Reset timing variables */
|
||||
key_state->press_start_time = current_time;
|
||||
key_state->last_repeat_time = current_time;
|
||||
key_state->long_press_event = 0;
|
||||
key_state->repeat_event = 0;
|
||||
} else {
|
||||
/* Key released event */
|
||||
key_state->release_event = 1;
|
||||
key_state->press_event = 0;
|
||||
|
||||
/* Check for short press event */
|
||||
uint32_t press_duration = current_time - key_state->press_start_time;
|
||||
if (press_duration < key_state->long_press_time) {
|
||||
key_state->short_press_event = 1;
|
||||
}
|
||||
|
||||
/* Reset long press and repeat flags */
|
||||
key_state->long_press_event = 0;
|
||||
key_state->repeat_event = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* State is stable, reset counter */
|
||||
key_state->debounce_counter = 0;
|
||||
|
||||
/* Handle timing-based events if key is pressed */
|
||||
if (raw_state == BSP_KEY_STATE_PRESSED) {
|
||||
uint32_t press_duration = current_time - key_state->press_start_time;
|
||||
|
||||
/* Check for long press event - only set once */
|
||||
if (press_duration >= key_state->long_press_time && !key_state->long_press_event) {
|
||||
key_state->long_press_event = 1;
|
||||
}
|
||||
|
||||
/* Check for repeat event - only after long press */
|
||||
if (key_state->long_press_event &&
|
||||
(current_time - key_state->last_repeat_time >= key_state->repeat_interval)) {
|
||||
key_state->repeat_event = 1;
|
||||
key_state->last_repeat_time = current_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read debounced key state
|
||||
* @param key_id: Key ID
|
||||
* @retval Key state
|
||||
*/
|
||||
bsp_key_state_t bsp_key_read(bsp_key_id_t key_id) {
|
||||
if (key_id < BSP_KEY_ID_MAX) {
|
||||
return key_state_table[key_id].current_state;
|
||||
}
|
||||
return BSP_KEY_STATE_RELEASED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if key is pressed
|
||||
* @param key_id: Key ID
|
||||
* @retval 1 if pressed, 0 otherwise
|
||||
*/
|
||||
uint8_t bsp_key_is_pressed(bsp_key_id_t key_id) {
|
||||
return (bsp_key_read(key_id) == BSP_KEY_STATE_PRESSED) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if key is released
|
||||
* @param key_id: Key ID
|
||||
* @retval 1 if released, 0 otherwise
|
||||
*/
|
||||
uint8_t bsp_key_is_released(bsp_key_id_t key_id) {
|
||||
return (bsp_key_read(key_id) == BSP_KEY_STATE_RELEASED) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for key press event (edge detection)
|
||||
* @param key_id: Key ID
|
||||
* @retval 1 if key was pressed, 0 otherwise
|
||||
*/
|
||||
uint8_t bsp_key_get_press_event(bsp_key_id_t key_id) {
|
||||
uint8_t event = 0;
|
||||
|
||||
if (key_id < BSP_KEY_ID_MAX) {
|
||||
event = key_state_table[key_id].press_event;
|
||||
key_state_table[key_id].press_event = 0; /* Clear event flag */
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for key release event (edge detection)
|
||||
* @param key_id: Key ID
|
||||
* @retval 1 if key was released, 0 otherwise
|
||||
*/
|
||||
uint8_t bsp_key_get_release_event(bsp_key_id_t key_id) {
|
||||
uint8_t event = 0;
|
||||
|
||||
if (key_id < BSP_KEY_ID_MAX) {
|
||||
event = key_state_table[key_id].release_event;
|
||||
key_state_table[key_id].release_event = 0; /* Clear event flag */
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for key long pressed event
|
||||
* @param key_id: Key ID
|
||||
* @retval 1 if key was long pressed, 0 otherwise
|
||||
*/
|
||||
uint8_t bsp_key_get_long_press_event(bsp_key_id_t key_id) {
|
||||
uint8_t event = 0;
|
||||
|
||||
if (key_id < BSP_KEY_ID_MAX) {
|
||||
event = key_state_table[key_id].long_press_event;
|
||||
/* Long press event is only reported once */
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for key repeat event
|
||||
* @param key_id: Key ID
|
||||
* @retval 1 if key repeat event occurred, 0 otherwise
|
||||
*/
|
||||
uint8_t bsp_key_get_repeat_event(bsp_key_id_t key_id) {
|
||||
uint8_t event = 0;
|
||||
|
||||
if (key_id < BSP_KEY_ID_MAX) {
|
||||
event = key_state_table[key_id].repeat_event;
|
||||
key_state_table[key_id].repeat_event = 0; /* Clear event flag */
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for key short pressed event
|
||||
* @param key_id: Key ID
|
||||
* @retval 1 if key was short pressed, 0 otherwise
|
||||
*/
|
||||
uint8_t bsp_key_get_short_press_event(bsp_key_id_t key_id) {
|
||||
uint8_t event = 0;
|
||||
|
||||
if (key_id < BSP_KEY_ID_MAX) {
|
||||
event = key_state_table[key_id].short_press_event;
|
||||
key_state_table[key_id].short_press_event = 0; /* Clear event flag */
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
Reference in New Issue
Block a user