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;
        }
  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,使用定时器也是一种实现按键长按短按双击的方法。 具体实现方法可以参考以下步骤: 1. 初始化定时器。选择合适的定时器,并设置定时器的时钟源、计数模式、计数周期等参数。一般推荐使用定时器的计数模式为向上计数,并且设置一个合适的计数周期。 2. 初始化按键。选择合适的引脚作为按键输入,配置引脚的输入模式和上拉/下拉电阻。一般推荐使用上拉电阻,使按键默认为高电平。 3. 在定时器中断服务函数中实现按键状态检测和处理。在定时器中断服务函数中,读取按键状态,并根据当前状态和前一次状态的变化,判断按键事件的类型。如果按键被按下,则记录按下时间;如果按键被释放,则记录释放时间,并根据时间间隔判断按键事件的类型。 4. 根据按键事件的类型,执行相应的操作。例如,长按事件可以用于开启或关闭某个功能;短按事件可以用于切换不同的模式;双击事件可以用于执行快速操作。 注意事项: 1. 在定时器中断服务函数中,需要注意防抖处理。对于按键输入信号,由于存在抖动现象,因此需要使用软件或硬件方式进行防抖处理,以确保检测到的按键状态是稳定的。 2. 在定时器中断服务函数中,需要注意按键状态检测间隔。检测间隔过短会导致系统负载过高,检测间隔过长会影响按键检测的灵敏度,因此需要选择一个合适的检测间隔。 3. 在定时器中断服务函数中,需要注意定时器的溢出问题。如果定时器的计数周期比较短,容易出现定时器溢出的情况,需要进行相应的处理。 总之,使用定时器实现按键长按短按双击需要结合具体的硬件平台和软件环境进行综合考虑,根据实际需求选择合适的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值