登录/注册

多功能按键怎么做STM32

多功能按键怎么做STM32

更多

在STM32上实现多功能按键(如短按、长按、双击等),需要结合按键扫描、状态机、定时器和事件处理。以下是详细步骤和代码示例:


1. 硬件连接


2. 软件设计思路


3. 代码实现

(1) 初始化按键和定时器

#include "stm32f1xx_hal.h"

// 按键定义
#define KEY_PIN          GPIO_PIN_0
#define KEY_PORT         GPIOA
#define KEY_PRESSED      0  // 低电平表示按下
#define KEY_RELEASED     1  // 高电平表示释放

// 时间阈值(单位:10ms)
#define DEBOUNCE_TIME    2   // 消抖时间20ms
#define LONG_PRESS_TIME  100 // 长按1秒(100×10ms)
#define DOUBLE_CLICK_GAP 20  // 双击间隔200ms

// 按键状态机
typedef enum {
    KEY_IDLE,
    KEY_DEBOUNCE,
    KEY_PRESS,
    KEY_LONG_PRESS,
    KEY_RELEASE
} KeyState;

// 按键事件
typedef enum {
    EVENT_NONE,
    EVENT_SHORT_PRESS,
    EVENT_LONG_PRESS,
    EVENT_DOUBLE_CLICK
} KeyEvent;

volatile KeyState key_state = KEY_IDLE;
volatile uint32_t key_press_duration = 0;
volatile uint8_t click_count = 0;
volatile uint32_t last_release_time = 0;
KeyEvent key_event = EVENT_NONE;

// 初始化GPIO
void Key_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = KEY_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉输入
    HAL_GPIO_Init(KEY_PORT, &GPIO_InitStruct);
}

// 初始化定时器(10ms中断)
void Timer_Init(void) {
    TIM_HandleTypeDef htim2;
    __HAL_RCC_TIM2_CLK_ENABLE();
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 7200 - 1;  // 72MHz/7200 = 10kHz
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 100 - 1;      // 10kHz/100 = 100Hz (10ms)
    HAL_TIM_Base_Init(&htim2);
    HAL_TIM_Base_Start_IT(&htim2);
    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
}

(2) 定时器中断处理(按键状态机)

// TIM2中断服务函数
void TIM2_IRQHandler(void) {
    if (__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_UPDATE)) {
        __HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);
        uint8_t key_current = HAL_GPIO_ReadPin(KEY_PORT, KEY_PIN);

        switch (key_state) {
            case KEY_IDLE:
                if (key_current == KEY_PRESSED) {
                    key_state = KEY_DEBOUNCE;
                    key_press_duration = 0;
                }
                // 双击检测:记录两次释放的时间差
                if (click_count > 0 && (++last_release_time > DOUBLE_CLICK_GAP)) {
                    if (click_count == 1) key_event = EVENT_SHORT_PRESS;
                    click_count = 0;
                }
                break;

            case KEY_DEBOUNCE:
                if (key_current == KEY_PRESSED) {
                    if (++key_press_duration >= DEBOUNCE_TIME) {
                        key_state = KEY_PRESS;
                        key_press_duration = 0;
                    }
                } else {
                    key_state = KEY_IDLE;
                }
                break;

            case KEY_PRESS:
                if (key_current == KEY_RELEASED) {
                    key_state = KEY_RELEASE;
                } else {
                    if (++key_press_duration >= LONG_PRESS_TIME) {
                        key_state = KEY_LONG_PRESS;
                        key_event = EVENT_LONG_PRESS;
                        click_count = 0; // 长按清零单击计数
                    }
                }
                break;

            case KEY_LONG_PRESS:
                if (key_current == KEY_RELEASED) {
                    key_state = KEY_IDLE;
                }
                break;

            case KEY_RELEASE:
                if (key_current == KEY_RELEASED) {
                    key_state = KEY_IDLE;
                    click_count++;
                    last_release_time = 0;
                    // 双击判断:第一次释放后开始计时
                    if (click_count == 2) {
                        key_event = EVENT_DOUBLE_CLICK;
                        click_count = 0;
                    }
                }
                break;
        }
    }
}

(3) 主循环中处理按键事件

int main(void) {
    HAL_Init();
    Key_Init();
    Timer_Init();

    while (1) {
        switch (key_event) {
            case EVENT_SHORT_PRESS:
                key_event = EVENT_NONE;
                // 执行短按操作
                break;
            case EVENT_LONG_PRESS:
                key_event = EVENT_NONE;
                // 执行长按操作
                break;
            case EVENT_DOUBLE_CLICK:
                key_event = EVENT_NONE;
                // 执行双击操作
                break;
            default:
                break;
        }
        HAL_Delay(10); // 主循环延时
    }
}

4. 关键点说明


5. 优化建议

通过以上设计,可实现稳定的多功能按键检测,适用于复杂交互场景。

企业AI模型托管怎么做

当下,越来越多的企业选择将AI模型托管给专业的第三方平台,以实现高效、灵活和安全的模型运行。下面,AI部落小编为您介绍企业AI模型托管是怎么做的。

2025-01-15 10:10:47

stm8要做单按键触摸怎么做,需要关注哪个参量?

stm8 触摸 单按键 实现状态翻转功能(按下开,再按下关)问题 做单按键

2024-05-09 07:59:37

怎么做按键消抖?

大家是怎么做按键消抖的 我是用一定时器做20ms定时,定时到在中断里设专门标志(20ms是否到,初始化为0),在主循环里当

2024-04-28 07:39:07

STM32——不同的按键对应实现不同功能的灯闪烁

STM32——不同的按键对应实现不同功能的灯闪烁功能介绍程序解读总结

资料下载 张览秀 2022-01-13 12:44:10

冷油器管板渗漏修补怎么做

冷油器管板渗漏修补怎么做

资料下载 h1654156043.7003 2022-01-11 11:38:56

STM32F103的按键控制数码管加减仿真

STM32F103的按键控制数码管加减仿真

资料下载 Gd12 2021-06-21 09:12:50

多功能按键嵌入式程序设计资料下载

电子发烧友网为你提供多功能按键嵌入式程序设计资料下载的电子资料下载,更有其他相关的电路图、源代码、课件教程、中文资料、英文资料、参考设计、用户指南、解决方案等资料,希望可以帮助到广大的电子工程师们。

资料下载 张国厚 2021-04-23 08:40:30

怎么做APQP/FMEA相关资源下载

怎么做APQP/FMEA相关资源下载

资料下载 Judy_Yu 2021-04-06 14:51:20

消除VCR电阻电压系数影响,你该怎么做

消除VCR电阻电压系数影响,你该怎么做?

2023-12-15 16:40:51

STM32怎么实现按键开关机

STM32怎么实现按键开关机 STM32是一种嵌入式系统,可以编程实现按键

2023-12-07 15:17:44

说说51单片机的多功能按键程序怎么写

我们的DIY电子时钟上有三个按键,而这三个按键需要完成整个时钟的参数设置,所以就需要用到复用功能的

2023-06-13 15:04:21

电子地磅的称重仪表出现老化该怎么做

电子地磅的称重仪表出现老化该怎么做

2022-03-11 13:24:10

STM32按键都有哪些功能

STM32——不同的按键对应实现不同功能的灯闪烁功能介绍程序解读总结

2022-02-25 07:27:17

如何实现基于STM32多功能GSM通讯系统设计?

如何实现基于STM32的多功能GSM通讯系统设计?

2022-02-17 08:03:10

使用多功能按键时需要注意哪些事项呢

使用多功能按键时需要注意哪些事项呢?

2022-01-18 07:39:20
7天热门专题 换一换
相关标签