Z-Stack通过按键中断实现长按功能

一、功能介绍

项目需要实现长按功能,实现按键有2种方式,一种是通过中断、一种KEY_CHANGE事件轮询的方式。由于中断更加的灵敏,这里选择中断的方式。意外的发现,如果开启了中断,那么按键就不会触发KEY_CHANGE事件了。下面说下按键中断实现长按功能的思路:
1. 按下按键 下降沿触发中断(记录触发时间)
2. 更改触发方式为上升沿触发(这样释放按键的时候就会触发中断了)
3. 上升沿触发中断(记录触发时间)
4. 计算时间差,满足条件执行相应功能
5. 别忘了,将触发方式改回来,改成下降沿触发

二、代码实现

我们用的是Z-Stack Home 1.2版本的协议栈。在hal_key.c中已经给出中断处理服务函数

/***************************************************************************************************
 *                                    INTERRUPT SERVICE ROUTINE
 ***************************************************************************************************/

/**************************************************************************************************
 * @fn      halKeyPort0Isr
 *
 * @brief   Port0 ISR
 *
 * @param
 *
 * @return
 **************************************************************************************************/
HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR )
{
  HAL_ENTER_ISR();

  if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)
  {
    halProcessKeyInterrupt();
  }

  /*
    Clear the CPU interrupt flag for Port_0
    PxIFG has to be cleared before PxIF
  */
  HAL_KEY_SW_6_PXIFG = 0;
  HAL_KEY_CPU_PORT_0_IF = 0;

  CLEAR_SLEEP_MODE();
  HAL_EXIT_ISR();
}

我们只需要实现halProcessKeyInterrupt方法就行了。我这里的按键是P0_5。

/**************************************************************************************************
 * @fn      halProcessKeyInterrupt
 *
 * @brief   p0端口中断回到函数
 *
 *
 * @param
 *
 * @return
 **************************************************************************************************/
void halProcessKeyInterrupt( void )
{
    bool valid = FALSE;
    uint32 HAL_KEY_interval_time;
    if( HAL_KEY_PXIFG & HAL_KEY_BIT5 ) /* Interrupt Flag has been set */
    {
        HAL_KEY_PXIFG &= ~HAL_KEY_BIT5;          
        if(PICTL & 1) //当前下降沿触发(按下按键),记录初始时间
        {
            Onboard_wait(50);//消除抖动
            if(P0_5==1)
              return;

            HAL_KEY_starting_time = HAL_KEY_starting_time == 0 ? osal_GetSystemClock():HAL_KEY_starting_time ; 
        }else         //当前上升沿触发(释放按键),计算时间
        {
            HAL_KEY_interval_time = osal_GetSystemClock()-HAL_KEY_starting_time;
            if(HAL_KEY_interval_time > HAL_KEY_FILTER_TIME)//小于HAL_KEY_FILTER_TIME ms的电平变化都会被过滤掉
            {
                valid = TRUE;
            }
            if(valid)
            {
                osal_set_event(PersonalEmergencyDev_TaskID,Motion_RESET_TIMEOUT_EVT);//触发事件执行自己的业务逻辑
            }

        }
        PICTL ^= 1; //p0触发方式<--取反
    }
}

最后别忘了,开启按键中断,通过宏变量。下面是添加的一些全局变量和宏定义。

#define ISR_KEYINTERRUPT 1
#define HAL_KEY TRUE
//按键长按5s 设置
static uint32 HAL_KEY_starting_time = 0;
#define HAL_KEY_FILTER_TIME 4950

猜你喜欢

转载自blog.csdn.net/qq_29542611/article/details/81544984