使用STM32定时器实现多按键短按检测

前言

由于最近做stm32项目用到按键的功能,目前常见的按键检测程序都是在主函数中使用delay延时来实现按键消抖的,但是这样简单粗暴的延时比较占用CPU的资源,影响主函数中其他的功能实现,经过这几天的搜索找到一种利用定时器来实现按键消抖扫描的方法。

实现思路

这篇文章实现的是多个按键(两个)短按功能,具体思路是在定时器中断中10ms扫描一下按键,实现不占CPU资源的按键消抖,主要参考了这篇文章【stm32单片机基础】按键状态机实现长按和短按,讲的很详细,感兴趣的可以去看下。

代码

下面直接贴出代码,bsp_key.c中的相关代码

按键扫描函数

typedef enum
{
    KEY_CHECK =0,//检测
    KEY_CONFIRM = 1,//确认
    KEY_RELEASE = 2//释放
}KEY_STATE;

KEY_STATE KeyState = KEY_CHECK;     //初始化按键状态为检测状态
uint8_t KeyFlag = 0;    //按键标志

void Key_Scan(void)
{
    switch(KeyState)
    {
        case KEY_CHECK:
            if(!KEY)//如果按键值为0,说明按键被按下,切换状态
            {
                KeyState = KEY_CONFIRM;
            }
            break;
        case KEY_CONFIRM:
            if(!KEY)//判断当前按键值是否为0,确认是否按下
            {
                KeyState = KEY_RELEASE;
                if(0 == KEY0)//KEY0被按下
                {
                    KeyFlag = KEY0_PRES;
                }
                if(0 == KEY1)//KEY1被按下
                {
                    KeyFlag = KEY1_PRES;
                }
            }
            else//按键没有被按下,返回上一状态
            {
                KeyState = KEY_CHECK;
            }
            break;
        case KEY_RELEASE:
            if(KEY)//当前按键值为1,说明按键已经释放,切换到开始状态
            {
                KeyState = KEY_CHECK;
            }
            break;
        default:
            break;
    }
}

定时器相关函数

主要包括通用定时器的配置(我这里使用了TIM2)和定时器中断10ms扫描一次按键状态

/*定时器配置*/
void TIMER_Config()
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    TIM_InternalClockConfig(TIM2);
    TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStruct;
    TIM_TimeBase_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBase_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
    /*定时10ms*/
    TIM_TimeBase_InitStruct.TIM_Period = 100 -1 ;
    TIM_TimeBase_InitStruct.TIM_Prescaler = 7200 - 1;
    TIM_TimeBase_InitStruct.TIM_RepetitionCounter = 0 ;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBase_InitStruct);
    
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    /*TIMER中断配置*/
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    
    NVIC_InitTypeDef Nvic_InitStruct;
    Nvic_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
    Nvic_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    Nvic_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    Nvic_InitStruct.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&Nvic_InitStruct);
    TIM_Cmd(TIM2, ENABLE);
}

/*定时器中断函数*/
void TIM2_IRQHandler()//10ms进入一次中断,按键扫描
{
    static uint8_t cnt;
    if(TIM_GetFlagStatus(TIM2, TIM_IT_Update) != RESET)//定时中断是否发生
    {   
        Key_Scan();
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中断标志
    }
}

bsp_key.h的相关代码

#define KEY0    GPIO_ReadInputDataBit(KEY0_GPIO_PORT, KEY0_GPIO_PIN)
#define KEY1    GPIO_ReadInputDataBit(KEY1_GPIO_PORT, KEY1_GPIO_PIN)
#define KEY     ((KEY0) && (KEY1))
#define KEY0_PRES 1
#define KEY1_PRES 2

void KEY_Init(void);    /*按键初始化函数*/
void Key_Scan(void);    /*按键扫描函数*/
void TIMER_Config();    /*定时器配置*/

main.c中的代码

while(1)
    {
        switch(KeyFlag)
        {
            case KEY0_PRES:
				/*
				*在这里插入自己的功能代码
				*/
                KeyFlag = 0;//注意按键标志清零,防止程序跑飞
                break;
            case KEY1_PRES:
                /*
				*在这里插入自己的功能代码
				*/
                KeyFlag = 0;
                break;
            default:
                break;
        }

作者:雾漫生

物联沃分享整理
物联沃-IOTWORD物联网 » 使用STM32定时器实现多按键短按检测

发表评论