148 lines
4.7 KiB
C
148 lines
4.7 KiB
C
/**
|
||
******************************************************************************
|
||
* @文件 key.c
|
||
* @作者 阜阳师范大学物电学院
|
||
* @版本 V0.1
|
||
* @日期 2026-01-15
|
||
* @简介 按键驱动 - 基于 MultiButton 的高可移植性实现
|
||
* @说明
|
||
*
|
||
****
|
||
*/
|
||
|
||
#include "key.h"
|
||
|
||
|
||
// 按键配置结构体
|
||
typedef struct {
|
||
uint16_t pin; // GPIO引脚
|
||
GPIO_TypeDef* port; // GPIO端口
|
||
KEY_TYPE key_type; // 按键ID
|
||
} KeyConfig_t;
|
||
|
||
/*
|
||
*******************详细引脚映射*****************************
|
||
| 按键名称 | 端口 | 引脚 | 位定义 | 功能说明 |
|
||
|---------|------|------|--------|----------|
|
||
| KEY_ENTER | GPIOB | PB15 | KEY_ENTER_BIT | 确认键 |
|
||
| KEY_UP | GPIOD | PD11 | KEY_UP_BIT | 上键 |
|
||
| KEY_DOWN | GPIOD | PD10 | KET_DOWN_BIT | 下键 |
|
||
| KEY_LEFT | GPIOD | PD13 | KET_LEFT_BIT | 左键 |
|
||
| KEY_RIGHT | GPIOD | PD8 | KET_RIGHT_BIT | 右键 |
|
||
| KEY_ESC | GPIOD | PD12 | KET_ESC_BIT | 取消键 |
|
||
| KEY_ADD | GPIOD | PD14 | KET_ADD_BIT | 加键 |
|
||
| KEY_DEC | GPIOD | PD9 | KET_DEC_BIT | 减键 |
|
||
| KEY_RESET | GPIOD | PD15 | KET_RESET_BIT | 复位键 |
|
||
***************************************************************
|
||
*/
|
||
// 按键配置表
|
||
static const KeyConfig_t key_configs[] = {
|
||
{15, GPIOB, KEY_ENTER},
|
||
{11, GPIOD, KEY_UP},
|
||
{10, GPIOD, KEY_DOWN},
|
||
{13, GPIOD, KEY_LEFT},
|
||
{8, GPIOD, KEY_RIGHT},
|
||
{12, GPIOD, KEY_ESC},
|
||
{14, GPIOD, KEY_ADD},
|
||
{9, GPIOD, KEY_DEC},
|
||
{15, GPIOD, KEY_RESET},
|
||
};
|
||
#define KEY_COUNT (sizeof(key_configs) / sizeof(key_configs[0]))
|
||
|
||
// 按键句柄数组
|
||
static Button btn_handles[KEY_COUNT];
|
||
// 业务逻辑回调函数指针(由main.c注册)
|
||
static KeyCallback key_callback = NULL;
|
||
|
||
|
||
/**
|
||
* @brief 读取按键GPIO电平
|
||
* @param button_id 按键ID
|
||
* @retval 0:按下, 1:释放
|
||
*/
|
||
static uint8_t button_read_level(uint8_t button_id)
|
||
{
|
||
uint16_t pin_bit = HAL_GPIO_ReadPin(key_configs[button_id].port, key_configs[button_id].pin);
|
||
return pin_bit;
|
||
}
|
||
|
||
/**
|
||
* @brief 统一的按键回调函数(内部使用,调用业务逻辑回调)
|
||
* @param btn 按键句柄指针
|
||
*/
|
||
static void button_callback(Button* btn)
|
||
{
|
||
if (btn != NULL && key_callback != NULL)
|
||
{
|
||
// 通过button_id获取对应的按键类型
|
||
uint8_t button_id = btn->button_id;
|
||
if (button_id < KEY_COUNT)
|
||
{
|
||
// 调用业务逻辑层注册的回调函数
|
||
key_callback(key_configs[button_id].key_type);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* @brief 注册按键回调函数(供业务逻辑层调用)
|
||
* @param callback 回调函数指针
|
||
*/
|
||
void Key_RegisterCallback(KeyCallback callback)
|
||
{
|
||
key_callback = callback;
|
||
}
|
||
/**
|
||
* @brief 使能GPIO时钟
|
||
* @param port: GPIO端口
|
||
* @retval 无
|
||
* @note 使用switch-case结构,代码更简洁清晰,支持所有GPIO端口(A-G)
|
||
*/
|
||
static void KEY_GPIO_ClockEnable(GPIO_TypeDef *port)
|
||
{
|
||
switch ((uint32_t)port) {
|
||
case (uint32_t)GPIOA: __HAL_RCC_GPIOA_CLK_ENABLE(); break;
|
||
case (uint32_t)GPIOB: __HAL_RCC_GPIOB_CLK_ENABLE(); break;
|
||
case (uint32_t)GPIOC: __HAL_RCC_GPIOC_CLK_ENABLE(); break;
|
||
case (uint32_t)GPIOD: __HAL_RCC_GPIOD_CLK_ENABLE(); break;
|
||
case (uint32_t)GPIOE: __HAL_RCC_GPIOE_CLK_ENABLE(); break;
|
||
case (uint32_t)GPIOF: __HAL_RCC_GPIOF_CLK_ENABLE(); break;
|
||
case (uint32_t)GPIOG: __HAL_RCC_GPIOG_CLK_ENABLE(); break;
|
||
default: break;
|
||
}
|
||
}
|
||
/**************************************************************************************
|
||
* FunctionName : Key_Init()
|
||
* Description : 按键硬件初始化(使用MultiButton库)
|
||
* EntryParameter : none
|
||
* ReturnValue : none
|
||
**************************************************************************************/
|
||
void Key_Init(void)
|
||
{
|
||
GPIO_InitTypeDef gpio_init_struct;
|
||
|
||
// 统一配置GPIO参数
|
||
gpio_init_struct.Mode = GPIO_MODE_INPUT;
|
||
gpio_init_struct.Pull = GPIO_PULLUP;
|
||
gpio_init_struct.Speed = GPIO_SPEED_HIGH;
|
||
|
||
// 批量初始化GPIO
|
||
for (uint8_t i = 0; i < KEY_COUNT; i++)
|
||
{
|
||
/* 使能对应GPIO时钟 */
|
||
KEY_GPIO_ClockEnable(key_configs[i].port);
|
||
|
||
// 配置并初始化引脚
|
||
gpio_init_struct.Pin = key_configs[i].pin;
|
||
HAL_GPIO_Init(key_configs[i].port, &gpio_init_struct);
|
||
}
|
||
|
||
// 批量初始化MultiButton按键(active_level=0表示低电平有效)
|
||
for (uint8_t button_id = 0; button_id < KEY_COUNT; button_id++)
|
||
{
|
||
button_init(&btn_handles[button_id], button_read_level, 0, button_id);
|
||
button_attach(&btn_handles[button_id], BTN_SINGLE_CLICK, button_callback);
|
||
button_start(&btn_handles[button_id]);
|
||
}
|
||
}
|
||
|