一、功能介绍
项目需要实现长按功能,实现按键有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