当前位置: 首页 > news >正文

STM32按键扫描

外部中断

  • 此方法需注意Timer base(也就是HAL_Delay)的优先级,要低于外部中断的优先级,否则会卡死,推荐下面状态机实现的方法。
  1. 上拉输入:
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) {/* 用户代码 */}}
  1. 长按短按:
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.c

#include "key.h"#define KEY_NUM 3
#define LONG_PRESS_TIME 1000
#define DEBOUNCE_TIME 20Key_t keys[KEY_NUM];/*** @brief 初始化按键接口参数*/
void Key_Init(void)
{keys[0].port = KEY_L_GPIO_Port;keys[0].pin = KEY_L_Pin;keys[0].active_level = 1;keys[0].state = KEY_IDLE;keys[0].last_level = 0;keys[1].port = KEY_M_GPIO_Port;keys[1].pin = KEY_M_Pin;keys[1].active_level = 0;keys[1].state = KEY_IDLE;keys[1].last_level = 1;keys[2].port = KEY_R_GPIO_Port;keys[2].pin = KEY_R_Pin;keys[2].active_level = 0;keys[2].state = KEY_IDLE;keys[2].last_level = 1;
}/*** @brief 按键扫描函数* @retval result.key_id    按键id* @retval result.event     事件类型*/
KeyEvent_t Key_Scan(void)
{KeyEvent_t result = {0, KEY_EVENT_NONE};for(uint8_t i = 0; i < KEY_NUM; i++){bool current_level;if (HAL_GPIO_ReadPin(keys[i].port, keys[i].pin) == keys[i].active_level){current_level = 1;}else current_level = 0;switch (keys[i].state){case KEY_IDLE:if (current_level && !keys[i].last_level){keys[i].state = KEY_PRESSED;keys[i].timer = HAL_GetTick();}break;case KEY_PRESSED:if (current_level){if (HAL_GetTick() - keys[i].timer >= DEBOUNCE_TIME){keys[i].state = KEY_HOLD;} }else keys[i].state = KEY_IDLE;break;case KEY_HOLD:if (current_level){if (HAL_GetTick() - keys[i].timer >= LONG_PRESS_TIME){result.key_id = i;result.event = KEY_EVENT_LONG;keys[i].state = KEY_RELEASED;keys[i].last_level = current_level;return result;  // 长按事件}}else{if (HAL_GetTick() - keys[i].timer >= DEBOUNCE_TIME){result.key_id = i;result.event = KEY_EVENT_SHORT;keys[i].state = KEY_IDLE;keys[i].last_level = current_level;return result;  // 短按事件}else keys[i].state = KEY_RELEASED;}break;case KEY_RELEASED:if (!current_level && (HAL_GetTick() - keys[i].timer >= DEBOUNCE_TIME)){keys[i].state = KEY_IDLE;}break;default:break;}keys[i].last_level = current_level;}return result;
}

key.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;   // 按键IDKeyEvent 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;}}}
}
http://www.gsyq.cn/news/58075.html

相关文章:

  • 2025年11月留学生回国求职机构市场报告:高性价比解决方案深度剖析
  • 2025年高价值专利申请专业团队推荐榜
  • 2025年11月留学生回国求职机构排行榜:五家主流服务机构深度对比
  • 2025年本地装修最新TOP实力榜
  • 2025年可靠的装修半包综合实力评选排行榜
  • 2025年靠谱的国际空运管理服务权威榜
  • 2025年知名的赣州装修公司原创设计施工
  • 2025年11月国内整合营销公司推荐榜单与选择指南
  • 2025年评价高的艺术IP授权机构综合实力排行榜
  • 2025年11月主流留学生海外找工作平台口碑排行榜解析
  • 2025年热门的高性价比全屋定制五金厂家推荐及选购参考榜
  • 2025年质量好的学校团餐配送最新用户口碑榜供应公司
  • 可重入程序是通过 减少对换数量 来改善系统性能的
  • 2025年靠谱的履带旋喷钻机厂家最新用户好评榜
  • 2025年热门的热电偶温度计行业内口碑厂家排行榜
  • 2025年热门的新疆长绒棉棉被厂家推荐及采购指南
  • 2025年靠谱的新能源设备固态继电器实力厂家TOP推荐榜
  • 2025年热门的南网机构限位防水微动开关行业内知名厂家排行榜
  • 2025年知名的热镀锌电缆桥架厂家最新用户好评榜
  • 2025年靠谱的凹油墨厂家推荐及选购参考榜
  • 文章归档代码
  • 2025年口碑好的方管阳光房厂家推荐及选择指南
  • 2025年口碑好的定制系统门窗厂家最新实力排行
  • windows迁移C盘内容
  • 2025年评价高的半圆形电梯品牌厂家排行榜
  • 2025年靠谱的十级净化工程品牌厂家排行榜
  • 2025年有实力的环保胶面墙布厂家推荐及选购参考榜
  • 2025年11月国内高新企业申请公司推荐榜单与选择指南
  • 2025年11月国内高新企业申请公司推荐榜单及选择指南
  • 2025年热门的气动密闭阀厂家选购指南与推荐