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实现的长短按效果更高些,按键抖动处理的时间相对较少,当然定时器+中断+计数器的方法还可以在优化