使用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;
}
作者:雾漫生