打印
[应用相关]

32单片机按键扫描 实现长短按

[复制链接]
152|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-2-29 08:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
key.c

/**
****************************************************************************************************
* @file           key.c
* @author         Kyro Qu
* @brief          按键驱动代码
* 实验平台:       STM32G431RB开发板
****************************************************************************************************
*/

#include "key.h"
#include "lcd.h"
#include "stdio.h"


typedef struct
{
        GPIO_TypeDef *Key_Port;
        uint16_t Key_Pin;

}Key_GPIO_t;

static Key_GPIO_t g_KeyList[] =
{
        { KEY_B1_GPIO_Port, KEY_B1_Pin },
        { KEY_B2_GPIO_Port, KEY_B2_Pin },
        { KEY_B3_GPIO_Port, KEY_B3_Pin },
        { KEY_B4_GPIO_Port, KEY_B4_Pin }
    /* add other KEY, ... */
};

#define KEY_NUM_MAX  (sizeof(g_KeyList)/sizeof(g_KeyList[0]))


typedef enum
{
        KEY_RELEASE =0,                 /* 释放松开 */
        KEY_CONFIRM,                 /* 消抖确认 */
        KEY_SHORT_PRESS,         /* 短按 */
        KEY_LONG_PRESS,                 /* 长按 */

}KEY_STATE;


#define CONFIRM_TIME  10                     /* 消抖时间 ms */
#define LONG_PRESS_TIME  2000                 /* 长按时间窗 ms */


typedef struct
{
        KEY_STATE keyState;                         /* 按键状态 */
        uint32_t  prvTime;                         /* 按键时间 */       

}Key_Info_t;

static Key_Info_t g_Key_Info[KEY_NUM_MAX];


/**
* @brief       扫描单个按键不同状态函数
* @param       按键端口号
* @retval      键值
*/
static uint8_t keyScan(uint8_t keyIndex)
{
        uint8_t keyPress;

        keyPress=HAL_GPIO_ReadPin(g_KeyList[keyIndex].Key_Port,g_KeyList[keyIndex].Key_Pin);

        #if !ElECTRIC_LEVEL
        keyPress=!keyPress;
        #endif

        switch (g_Key_Info[keyIndex].keyState)                                                                    /* 按键状态机 */
        {
                case KEY_RELEASE :
                                if(keyPress )                                                                              /* 如果按下 */                                                                                                       
                                {
                                        g_Key_Info[keyIndex].keyState = KEY_CONFIRM;
                                        g_Key_Info[keyIndex].prvTime = HAL_GetTick();                        /* 获取按下起始时间 */
                                }
                                break;
                case KEY_CONFIRM :
                                if(keyPress )
                                {
                                        if(HAL_GetTick()-g_Key_Info[keyIndex].prvTime>CONFIRM_TIME )
                                        {
                                                g_Key_Info[keyIndex].keyState = KEY_SHORT_PRESS;
                                        }
                                }
                                else
                                {
                                        g_Key_Info[keyIndex].keyState = KEY_RELEASE;
                                }
                                break;
                case KEY_SHORT_PRESS :
                                if(keyPress )
                                {
                                        if(HAL_GetTick()-g_Key_Info[keyIndex].prvTime>LONG_PRESS_TIME )
                                        {
                                                g_Key_Info[keyIndex].keyState = KEY_LONG_PRESS;
                                        }
                                }
                                else                                                                                                    /* 如果松开 */
                                {
                                        g_Key_Info[keyIndex].keyState = KEY_RELEASE;
                                        return (keyIndex+0x01);                                                        /* 返回短按对应码值  0x01 0x02 0x03 .....    */                               
                                }
                                break;
                case KEY_LONG_PRESS :
                                if(!keyPress )                                                                                            /* 如果松开 */
                                {
                                        g_Key_Info[keyIndex].keyState = KEY_RELEASE;
                                        return (keyIndex+0x81);                                                                /* 返回短按对应码值  0x81 0x82 0x83 .....    */                               
                                }
                                break;
                default:
                                        g_Key_Info[keyIndex].keyState = KEY_RELEASE;
        }
                return 0;                                                       
}


/**
* @brief        扫描单个按键 按键的码值
* @param        无
* @retval       键值
*/
uint8_t GetKeyVal(void)
{
        uint8_t  res = 0;

        for(uint8_t i=0;i<KEY_NUM_MAX;i++)
        {
                res = keyScan(i);                                            /* 临时保存键值 */

                if(res!= 0)                                                        /* 返回键值不为0,则跳出 */
                {
                        break;
                }
        }
    return res;  /* 返回键值 */
}



/**
* @brief        按键处理函数
* @param        无
* @retval       无
*/

void KeyHandler(void)
{
        uint8_t KEY_STATE;

        KEY_STATE=GetKeyVal();
        switch(KEY_STATE)
        {
                case B1_SHORT_PRESS:
                                        break;
                case B1_LONG_PRESS:

                                        break;
                case B2_SHORT_PRESS:

                                        break;
                case B2_LONG_PRESS:

                                        break;
                case B3_SHORT_PRESS:

                                        break;
                case B3_LONG_PRESS:

                                        break;
                case B4_SHORT_PRESS:
       
                                        break;
                case B4_LONG_PRESS:
       
                                        break;
        }
}








key.h

/**
****************************************************************************************************
* @file           key.h
* @author         Kyro Qu
* @brief          按键驱动代码
* 实验平台:       STM32G431RB开发板
****************************************************************************************************
*/

#ifndef __KEY_H
#define __KEY_H

#include "main.h"

//按键另一端口的电平  1为高电平   0为低电平
#define   ElECTRIC_LEVEL   0

/* 键值 */
#define B1_SHORT_PRESS 0x01
#define B1_LONG_PRESS  0x81

#define B2_SHORT_PRESS 0x02
#define B2_LONG_PRESS  0x82

#define B3_SHORT_PRESS 0x03
#define B3_LONG_PRESS  0x83

#define B4_SHORT_PRESS 0x04
#define B4_LONG_PRESS  0x84


uint8_t keyScan(uint8_t mode);/* 按键扫描函数 */
uint8_t GetKeyVal(void);
void KeyHandler(void);


#endif












————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/JasonKyro/article/details/135261353

使用特权

评论回复
沙发
digit0| | 2024-2-29 13:35 | 只看该作者
在32位单片机(如STM32系列)中实现按键的长按和短按功能,通常需要通过定时器配合中断或软件延时的方式来判断按键按下时间的长短。

使用特权

评论回复
板凳
LinkMe| | 2024-2-29 13:36 | 只看该作者
配置一个定时器(例如TIMx),设定一个较短的时间间隔(如500ms,用于判断短按)和一个较长的时间间隔(如2000ms,用于判断长按)。

使用特权

评论回复
地板
理想阳| | 2024-2-29 13:36 | 只看该作者
当检测到按键按下(GPIO由高变低)时,启动定时器开始计时。
在定时器中断服务程序中,根据定时器溢出次数来判断是短按还是长按:
如果定时器到达短按时间阈值,执行短按操作并清零定时器。
如果定时器到达长按时间阈值,执行长按操作并清零定时器。
当检测到按键释放(GPIO由低变高)时,如果定时器仍在计数,则停止定时器,避免误判。

使用特权

评论回复
5
ClarkLLOTP| | 2024-2-29 17:08 | 只看该作者
长短按是根据进中断次数来的吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1364

主题

13994

帖子

8

粉丝