针对stm32hal库超轻量化按钮代码,实现按钮的单击,双击,长按功能,如果使用的是标准库,仅需要改Button初始化函数

针对嵌入式领域竞赛需求,特设计一款超轻量化按钮模块方案。该方案具备高可复制性与易理解性,旨在为参赛者提供便捷高效的硬件接入解决方案,助力快速搭建嵌入式系统交互模块。

key.c

可以根据直接的需求来调整DEBOUNCE        LONG_PRESS        DOUBLE_CLICK

注意,DOUBLE_CLICK不要太长,因为这里采用了堵塞等待双击,如果不需要双击功能可以把DOUBLE_CLICK置0;

#include "key.h"

// 初始化按钮
void Button_Init(Button *btn, GPIO_TypeDef *port, uint16_t pin) {
    btn->port = port;
    btn->pin = pin;
    btn->state = 0;
    btn->click_cnt = 0;

    // 设置GPIO为输入模式,这里可以采用mubemx进行配置
    
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(port, &GPIO_InitStruct);
    // 设置GPIO为上拉模式
    
}

BtnEvent Button_Update(Button *btn) {
    static const uint16_t DEBOUNCE = 20, LONG_PRESS = 1000, DOUBLE_CLICK = 200;
    uint8_t pressed = (HAL_GPIO_ReadPin(btn->port, btn->pin) == GPIO_PIN_RESET);
    uint32_t now = HAL_GetTick();

    switch (btn->state) {
        case 0: // 空闲状态
            if (pressed) {
                btn->state = 1;         // 进入按下消抖
                btn->last_time = now;
            }
            break;

        case 1: // 按下消抖
            if (now - btn->last_time >= DEBOUNCE) {
                if (pressed) {
                    btn->state = 2;     // 确认按下
                    btn->last_time = now;
                } else {
                    btn->state = 0;     // 抖动,回到空闲
                }
            }
            break;

        case 2: // 按下状态
            if (!pressed&&now- btn->last_time < LONG_PRESS) {
                btn->state = 3;         // 进入松开消抖
                btn->last_time = now;
            } else if (!pressed&&now - btn->last_time >= LONG_PRESS) {
                btn->state = 0;
                return BTN_LONG_PRESS;  // 长按触发
            }
            break;

        case 3: // 松开消抖
            if (now - btn->last_time >= DEBOUNCE) {
                if (!pressed) {         // 确认松开
                    btn->click_cnt++;
                    btn->state = 4;     // 等待双击
                    btn->last_time = now;
                } else {
                    btn->state = 2;     // 抖动,回到按下状态
                }
            }
            break;

        case 4: // 等待双击
            if (now - btn->last_time > DOUBLE_CLICK) {
                BtnEvent event = (btn->click_cnt >= 2) ? BTN_DOUBLE_CLICK : BTN_CLICK;
                btn->click_cnt = 0;
                btn->state = 0;
                return event;
            } else if (pressed) {
                btn->state = 1;         // 再次按下,重新消抖
                btn->last_time = now;
            }
            break;
    }
    return BTN_NONE;
}

key.h

#ifndef KEY_H
#define KEY_H

#include "main.h"
#include "gpio.h"

// 按钮事件类型
typedef enum {
    BTN_NONE,
    BTN_CLICK,
    BTN_DOUBLE_CLICK,
    BTN_LONG_PRESS
} BtnEvent;

// 按钮状态结构体
typedef struct {
    GPIO_TypeDef *port;  // 按钮GPIO端口
    uint16_t pin;        // 按钮引脚
    uint32_t last_time;  // 上次时间戳
    uint8_t state;       // 当前状态
    uint8_t click_cnt;   // 点击计数
} Button;


// 初始化按钮
void Button_Init(Button *btn, GPIO_TypeDef *port, uint16_t pin);

// 更新按钮状态
// 返回按钮事件
BtnEvent Button_Update(Button *btn) ;



#endif // !KEY_H

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值