转:Stm32学习笔记:按键单击、双击、长按功能实现

由于项目产品的需要,只能设置一个按键,但是需要实现短按(即单击)切换工作模式、长按开关机、双击暂停等复用功能。下图是三种情况下的按键波形。按键未按下时是高电平,按下去是低电平。按键单击时,判断时间门槛设置为50~2000ms;长按门槛为持续按下2000ms。双击可以视为时间间隔很短的俩次有效单击,从第一次单击上升沿到第二次单击上升沿延时门槛为100~500ms。 
这里写图片描述

//按键按下去会出现下降沿,设置按键IO口所在的外部端口为下降沿触发中断。
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
KEY_Init(); //①按键端口初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //②开启 AFIO 时钟 //GPIOE.2 中断线以及中断初始化配置,下降沿触发 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);//③ EXTI_InitStructure.EXTI_Line=EXTI_Line2; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //④初始化中断线参数 NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure);//⑤初始化 NVIC }

中断服务函数

//⑥外部中断 2 服务程序
void EXTI2_IRQHandler(void)
{
    if(GPIO_ReadInputPin(GPIOE,GPIO_PIN_2)==0) //按键 KEY2 { key_fall_flag = 1;//生成按键按下标志 } EXTI_ClearITPendingBit(EXTI_Line2); //清除 LINE2 上的中断标志位 }

1ms定时器中断服务函数

void TIM3_IRQHandler(void) //TIM3 中断
{
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否 { if(key_fall_flag==1)//发生按键按下事件 { if(GPIO_ReadInputPin(GPIOB,GPIO_PIN_4)==0)//按键持续按下 { if(key_holdon_ms <= 2000) { key_holdon_ms++; } else //按键按下到2000ms就判断长按时间成立,生成长按标志 { key_holdon_ms = 0; short_key_flag=0;//清短按键标志 key_long_down = 1;//长按键标志置位 key_fall_flag = 0;//清按键按下标志 } } else //按键抬起 { if(key_holdon_ms>50)//按下时间大于50ms,生成单击标志 { key_holdon_ms=0; short_key_flag=1; key_long_down =0; key_fall_flag=0; //距离上次单击时间在100~500ms之间,则认为发生连击事件 if(keyupCnt>100 && keyupCnt<500) { doubleClick = TRUE; short_key_flag=0; } keyUpFlag = TRUE;//单击抬起按键后,生成按键抬起标志 } else //按键持续时间小于50ms,忽略 { key_holdon_ms=0; short_key_flag=0; long_key_flag=0; key_fall_flag=0; } } } if(keyUpFlag)//单击抬起后,启动计数,计数到500ms keyupCnt++; if(keyupCnt>500) { keyupCnt = 0; keyUpFlag = FALSE; } } TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除 TIM3 更新中断标志 } }

转载于:https://www.cnblogs.com/killer-xc/p/6868497.html

你可能感兴趣的:(嵌入式)