单片机按键长短按得识别原理

stm32f103

按键长短按得识别原理

需要一个定时器,用来计算按键按下的时间,可以一秒钟检测100次, 设置初始化为10ms的中断,比如使用定时4作为按键时间计算的定时器

比如我们需要4种模式,轻触,短按,长按,超级长按 

#define clickTypeTouch 1  //轻触
#define clickTypeShort 2 //短按
#define clickTypeLong 3 //长按
#define clickTypeVeryLong 4 //非常长的长按

#define timeCntClickTouch 500 //ms内为短按
#define timeCntClickShort 1000 //ms内为短按
#define timeCntClickLong  2000//ms内,且大于短按时间为长按
#define timeCntClickVeryLong 5000//ms的按键时间为非常长,用于进入高级模式
 
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器7
void TIM4_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能

    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值     
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
    TIM_ITConfig(  //使能或者失能指定的TIM中断
        TIM4, 
        TIM_IT_Update ,
        ENABLE  //使能
        );
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

    TIM_Cmd(TIM4, ENABLE);  //使能TIMx外设
                             
}
定时器的初始化

然后设置一个变量用来累计按键按下的时间,没按键按下的时候, 一直循环累计时间,从0到溢出,有按键按下的时候,立即清空,重新开始累计

首先初始化按键端口

void keyIOInit(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);     //使能PA
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;                 //LED0-->PA.8 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;          //推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);                     //根据设定参数初始化GPIOA
}
u16 timeKeyPressed; //按键按下的时间 10ms 步进

设置两个常量,用来区别按键的状态,是按下还是释放

#define keyStatusPressed 0
#define keyStatusReleased 1

定时器的中断,累计时间

    void TIM4_IRQHandler(void)   //中断
{
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
        {
          TIM_ClearITPendingBit(TIM4, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
          timeKeyPressed+=10; //10ms的中断
        }
}

这个键,我叫做设置键,什么时候开始给设置键开始计算按下时间呢?

设置键被按下 而且 按键状态还是释放

需要几个常量标志和几个变量

u8 statusCntingKeyTime; //是否开始计算按键时间
#define statusCnting 1
#define statusNotCnting 0

//设置键按下,且之前没开始计时的时候,开始计算按下时间
if(keySet==keyStatusPressed && statusCntingKeyTime==statusNotCnting )
{
    timeKeyPressed=0; //设置键按下后,重新开始计时
    statusCntingKeyTime=statusCnting;//开始计算按下时间
}

当按键松开后,统计一下,按下的时间为多长

//松手后统计按下时间
        if(keySet==keyStatusReleased && statusCntingKeyTime==statusCnting)
        {
            statusCntingKeyTime=statusNotCnting;//停止计时
            
            //轻触
            if(timeKeyPressed<=timeCntClickTouch )
            {                
            }
            //短按
            else if(timeKeyPressed>=timeCntClickShort &&timeKeyPressed<timeCntClickLong  )
            {
            }
            //长按
            else if(timeKeyPressed>=timeCntClickLong &&timeKeyPressed<timeCntClickVeryLong)
            {
            }
            //超级长按
            else if(timeKeyPressed>=timeCntClickVeryLong)
            {
            }
        }

猜你喜欢

转载自www.cnblogs.com/jnhs/p/10004509.html