【STM32】使用TIM内部计数器(CNT)实现按键长、短按

8 篇文章 1 订阅
6 篇文章 1 订阅
本文介绍了如何在STM32F411VET6上使用TIM3内部计数器(CNT)来区分按键的长按和短按。通过设置TIM3的预分频和溢出值,实现了每1ms计一个数,以此判断按键按下和释放之间的时间差,从而实现2s以上的长按和1s以内的短按功能。案例中,长按会翻转LED15,短按则翻转LED12。此外,还提到了使用定时器+中断+计数器的优化方法,以减少按键抖动并提高检测精度。
摘要由CSDN通过智能技术生成

STM32使用TIM内部计数器(CNT)实现按键长、短按

1.工具

  • STM32CUBE、IAR
  • STM32F411VET6

2.实现

2.1案例说明

  • 按键:本案例使用PA0,高电平有效(按下引脚电平为1,未按下为0)
  • 长按: 按键从按下到释放时间 > 2s
  • 短按: 按键从按下到释放时间 < 1s
  • 长按功能:LED15翻转1次,调用HAL_GPIO_TogglePin( GPIOD, GPIO_PIN_15);
  • 短按功能:LED12翻转1次,调用HAL_GPIO_TogglePin( GPIOD, GPIO_PIN_12);

2.2 方法

  • 一般按键短按一次用时100ms,因此对TIM进行预分频,使其内部CNT每计一个数用时为1ms。当按键按下时将TIM内部的CNT进行保存,释放时再保存一次,计算2次CNT的差值,从而进行长按、短按判定

  • F411VET6定时器TIM3内部CNT是32bit的,可以计时达到us级别,这里设置溢出值为60000即60ms,(没有打开中断,只是利用CNT计1个数用时1ms),另外也可利用定时器+中断+计数器实现长、短按,大概思路这样,设置TIM短长时间进入中断1次,进入中断后计数器累加,判断计数器从而实现长短按(文章后边有该方法实现的结果(5ms进入1次中断))

  • main

#include "main.h"
#include "tim.h"
#include "gpio.h"

uint8_t tim_flag = 0;
uint8_t key_flag = 0;
#define key_null     0
#define key_long     1
#define key_short    2

void SystemClock_Config(void);

void KeyScan(void);

uint32_t tmpbuf[4] = {0, 0, 0, 0};

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM3_Init();
  HAL_TIM_Base_Start(&htim3);//在按键扫描之前开启定时器

  while (1)
  {
    
     KeyScan();
     switch(tim_flag)
     {
       
     case key_null:
           break;

     case key_short:
          HAL_GPIO_TogglePin( GPIOD, GPIO_PIN_12);
         break;
         
     case key_long:
          HAL_GPIO_TogglePin( GPIOD, GPIO_PIN_15);
         break;
         
     default:
         break;
     
     }
  }

}
  • keyscan

void KeyScan(void)
{

     uint8_t key_states = 0; 
     key_states = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);

     if(key_flag == 0)
     {
         
         tmpbuf[0] = TIM3->CNT;
         key_flag = 1;
         tim_flag = key_null;
     }
      else
    {
         if( 0 == key_states)
         {
             tmpbuf[1] = TIM3->CNT;
             key_flag = 0;
             
             if( tmpbuf[1] < tmpbuf[0] )//CNT判断
             {
             
                  tmpbuf[2] = (60000 + tmpbuf[1])  - tmpbuf[0];
             
             }
             else if(tmpbuf[1] > tmpbuf[0])
             {
             
                  tmpbuf[2] =  tmpbuf[1]  - tmpbuf[0];
             
             }
             
             if(tmpbuf[2] > 2000 )
             {
                  tim_flag = key_long;
               
                  tmpbuf[2] = 0;
             }
             else if((tmpbuf[2] > 20 ) && (tmpbuf[2] < 1000))
             {
                   tim_flag = key_short;
                 
                   tmpbuf[2] = 0;
             }
   
         }
             
      }
         
}
  • TIM配置

      htim3.Instance = TIM3;
      htim3.Init.Prescaler = 15999;//CNT计一个数1ms
      htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim3.Init.Period = 60000;//溢出值
      htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    

利用CNT实现长短按的结果:
在这里插入图片描述
定时器+中断+计数器实现结果:
在这里插入图片描述

​ 可见利用CNT实现的长短按效果更高些,按键抖动处理的时间相对较少,当然定时器+中断+计数器的方法还可以在优化

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值