当前位置: 首页 > 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.jsqmd.com/news/48298/

相关文章:

  • 2025年11月留学生回国求职机构避坑指南:五家主流机构横向对比
  • 2025年高价值专利申请专业团队推荐榜
  • 2025年11月留学生回国求职机构市场报告:高性价比解决方案深度剖析
  • informix数据库怎样优化存储
  • 2025年11月留学生回国求职机构排行榜:五家主流服务机构深度对比
  • 2025年本地装修最新TOP实力榜
  • 2025年可靠的装修半包综合实力评选排行榜
  • 2025年可靠的工厂环保咨询行业专家权威推荐榜
  • 2025年质量好的酒会活动策划专业技术口碑榜
  • 实用指南:JavaEE:知识总结(一)
  • 2025年靠谱的国际空运管理服务权威榜
  • 2025年知名的赣州装修公司原创设计施工
  • 2025年热门的高压控制盒高压直流接触器TOP品牌厂家排行榜
  • 2025年11月主流留学生求职专家对比排行榜
  • 2025年比较好的私有化视频会议优质服务榜
  • 2025年11月国内整合营销公司推荐榜单与选择指南
  • 2025年评价高的艺术IP授权机构综合实力排行榜
  • 2025年11月留学生国内求职专家推荐:榜单解析与权威选择指南
  • 2025年11月留学生求职服务机构推荐:多维度对比与实用选择建议
  • 2025年知名的中亚获客企业数字化获客解决方案
  • 2025年11月主流留学生海外找工作平台口碑排行榜解析
  • 2025年质量好的不锈钢二段力铰链TOP实力厂家推荐榜
  • 2025年11月海外就业机构市场报告:知名平台服务特色与选择策略
  • KEYDIY PAK01-ZB Phone As Key: Secure Easy Smartphone Car Access
  • 2025年评价高的园区目视化规划最新用户好评榜机构
  • 2025年热门的高性价比全屋定制五金厂家推荐及选购参考榜
  • 淘宝闪购红包怎么领?淘宝闪购全部红包/优惠券领取方式汇总! - 指南
  • 2025年知名的窖藏坛装涪陵榨菜地道美味特产推荐榜
  • 2025年知名的平面VI设计创意视觉识别方案榜
  • 2025年机械密封厂家最新十大推荐榜,机械密封,机械密封件,釜用机械密封,机械密封维修,双端面机械密封公司行业口碑优选指南