外部中断
- 此方法需注意Timer base(也就是HAL_Delay)的优先级,要低于外部中断的优先级,否则会卡死,推荐下面状态机实现的方法。
- if (HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_SET) { // 按下
- OSTimeDly(20,OS_OPT_TIME_DLY,&err); // 去抖
- if (HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_SET) {
- /* 用户代码 */
- }
- }
复制代码- if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == GPIO_PIN_RESET) { // 按下
- HAL_Delay(20); // 去抖
- if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == GPIO_PIN_RESET) {
- HAL_Delay(500); // 判断长按
- if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == GPIO_PIN_RESET) {
- /* 长按 */
- }
- else {
- /* 短按 */
- }
- }
- }
复制代码 状态机实现多按键短按长按
key.ckey.h- #ifndef __KEY_H
- #define __KEY_H
- #include "main.h"
- #include <stdbool.h>
- // 按键状态枚举
- typedef enum {
- KEY_IDLE, // 空闲
- KEY_PRESSED, // 按下(去抖中)
- KEY_HOLD, // 持续按下
- KEY_RELEASED // 释放(去抖中)
- } KeyState;
- // 按键事件枚举
- typedef enum {
- KEY_EVENT_NONE, // 无事件
- KEY_EVENT_SHORT, // 短按
- KEY_EVENT_LONG // 长按
- } KeyEvent;
- // 按键事件返回结构体
- typedef struct {
- uint8_t key_id; // 按键ID
- KeyEvent event; // 事件类型
- } KeyEvent_t;
- // 按键结构体
- typedef struct {
- GPIO_TypeDef* port; // GPIO端口
- uint16_t pin; // GPIO引脚
- bool active_level; // 按下时的有效电平(true: 高电平, false: 低电平)
- KeyState state; // 当前状态
- uint32_t timer; // 计时器
- bool last_level; // 上次电平
- } Key_t;
- void Key_Init(void);
- KeyEvent_t Key_Scan(void);
- #endif
复制代码 实现方法
在main.c文件中:- #include "key.h"
- KeyEvent_t key;
- void main(void)
- {
- Key_Init();
- while (1)
- {
- key = Key_Scan();
- if (key.event != KEY_EVENT_NONE)
- {
- switch (key.event)
- {
- case KEY_EVENT_SHORT:
- printf("key %d short press\n", key.key_id);
- break;
- case KEY_EVENT_LONG:
- printf("key %d long press\n", key.key_id);
- break;
- default:
- break;
- }
- }
- }
- }
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |