以STM32为例,实现按键的短按和长按

本文详细介绍了如何在STM32中通过定时器和GPIO控制实现按键的短按和长按功能,包括硬件连接、代码示例和测试过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以STM32为例,实现按键的短按和长按

1 实现原理

简单来说就是通过设置一个定时器来定时扫描几个按键的状态,并分别记录按键按下的持续时间,通过时间的长短就可以判断出是长按还是短按。

本文硬件接线图如下:
在这里插入图片描述
在这里插入图片描述

2 实现代码

1、key.h
主要是一些按键引脚以及后面需要使用的变量定义。

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"

#define KEY1_PORT  GPIOE
#define KEY1_PIN   GPIO_Pin_4
#define KEY2_PORT  GPIOE
#define KEY2_PIN   GPIO_Pin_3
#define KEY3_PORT  GPIOE
#define KEY3_PIN   GPIO_Pin_2
#define KEY4_PORT  GPIOA
#define KEY4_PIN   GPIO_Pin_0

// 按键引脚定义
typedef struct
{
   
    GPIO_TypeDef* port;          // GPIOx
    uint16_t      pin;           // GPIO PINx
    uint16_t      pressed_state; // 按键按下时的状态,0:按下时为低电平,1:按下时为高电平
}key_gpio_t;

// 按键状态
typedef enum
{
   
    KEY_RELEASE,         // 释放松开
    KEY_CONFIRM,         // 消抖确认
    KEY_SHORT_PRESSED,   // 短按
    KEY_LONG_PRESSED,    // 长按
}key_status_t;

// 按键事件
typedef enum
{
   
    EVENT_NULL,
    EVENT_SHORT_PRESSED,
    EVENT_LONG_PRESSED,
}key_event_t;

typedef struct
{
   
    key_status_t current_state; // 按键当前状态
    uint32_t  pressed_time;     // 按下时间    
    key_event_t key_event;      // 按键事件
}key_param_t;

uint8_t read_key_state(uint8_t index);
uint8_t key_scan(void);
void key_handle(void);
void key_timer_init(void);
void key_gpio_init(void);
void key_init(void);

#endif

2、key.c
按键的实现代码,包括定时器和引脚的初始化,按键的扫描和处理函数,等等。

/**
 ********************************************************************************************************
 * @file           key.c
 * @author         qiyiqi
 * @brief          按键驱动代码
 * MCU:            STM32F103ZE开发板
 * 按键原理:       设置一个1ms定时器定时扫描几个按键的状态,并分别记录按下的持续时间,通过时间可以判断是长按还是
 *                 短按。    
 * 注意事项:       此代码只是作为一个参考例程,如果不使用STM32的标准库,移植到其他MCU或者HAL库之类的,主要修改的
 *                 地方在初始化函数key_init(),按键读取函数read_key_state(),定时器初始化以及中断服务函数等。
 ********************************************************************************************************
 */
#include "key.h"
#include "stdio.h"

// 按键列表
key_gpio_t key_list[] =
{
   // 端口号,引脚号,有效电平
    {
   KEY1_PORT, KEY1_PIN, 0},  // 按下为0,松开为1
    {
   KEY2_PORT, KEY2_PIN, 0},
    {
   KEY3_PORT, KEY3_PIN, 0},  // 按下为1,松开为0
    {
   KEY4_PORT
STM32开发中,实现按键短按功能通常需要使用中断处理机制。以下是一个基本的步骤: 1. **初始化硬件**: 首先,你需要配置相应的GPIO口为输入模式,并使能中断。如,如果你的按键连接到PA0引脚: ```c GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // PA0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 输入上拉或下拉 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); ``` 2. **中断配置**: 将GPIO的中断请求连接到你的中断服务函数(ISERREN位设置),并开启中断: ```c EXTI_InitStructure EXTI_Line = EXTI_Line0; // 对应于PA0 EXTI_InitStructure EXTI_Mode = EXTI_Mode Falling; // 增加下降沿检测 EXTI_InitStructure EXTI_Trigger = EXTI_Trigger_Rising_Falling; // 上升或下降触发 EXTI_InitStructure EXTI_Intensity = EXTI_Intesity_High; EXTI_Init(&EXTI_InitStructure); EXTI_Cmd(EXTI_Line0, ENABLE); // 开启中断 // 如果你使用中断优先级组: NVIC_SetPriority(EXTI0_IRQn, YOUR_INTERRUPT_PRIORITY_LEVEL); // 设置中断优先级 NVIC_EnableIRQ(EXTI0_IRQn); // 启动中断 ``` 3. **中断服务函数** (`EXTI0_IRQHandler` 或者自定义的名字): 这里你可以检查按键状态是否改变,并根据状态判断是按还是短按。比如,可以计数连续的上升沿次数: ```c uint8_t pressCount = 0; void EXTI0_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line0) != RESET) { // 检查是否有中断发生 if (GPIO_ReadPin(GPIOA, GPIO_Pin_0)) { // 当按键按下时 pressCount++; if (pressCount == LONG_PRESS_THRESHOLD) { // 按阈值达到 // 执行按时的操作,如延时、记录事件等 } } else { // 松开时 if (pressCount > SHORT_PRESS_THRESHOLD) { // 如果超过短按阈值,则视为短按 // 执行短按时的操作,如发送数据或弹窗提示 pressCount = 0; // 重置计数器 } } EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志 } } ``` 记得设置适当的按(`LONG_PRESS_THRESHOLD`)短按(`SHORT_PRESS_THRESHOLD`)阈值。 4. **短按的逻辑**: 根据具体需求调整这些阈值。如果希望立即响应松开就结束按,可将`pressCount`清零放到`else`分支内;如果要保持按持续一段时间,直到检测到松开。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值