zstack中按键复用的三种方式(纯应用层面)上

来源:互联网 发布:mac 弱网络工具 编辑:程序博客网 时间:2024/05/29 19:18
应用平台:stack-2007 版本:ZStack-CC2530-2.3.0-1.4.0
我们都知道cc2530中的可用I/O资源比较少,尤其在实际应用中,如果添加lcd显示等占用I/O 较多的外设时,I/O资源更是稀少;另一种情况是将ZigBee开发成一个小配件时不会添加太多外设,此时可能会用到按键的复用。
话不多说,本文结合自己的开发实例,仅在应用层面介绍三种按键复用方式:
(1)传统的按键延时计数的方式。
(2)按键轮询计数方式。
(3)AD按键方式。
下面逐一介绍实现方法:
(1)延时计数方式
实现:同一个按键按下不同的时间,可以赋予不同的标志,进而可以进行不同的处理操作。
原理:即是在按下时消抖后,进行while循环检测按键是否松开,然后在循环体中添加计数累加,跳出循环后判断计数值,即可进行不同按键的标志。
优点:修改简单,应用快捷
缺点:延时函数会导致这个协议栈的运行堵塞,直到松手才恢复正常。如果使能看门狗,会造成看门口复位。
实现:
1. 在 hal_key.c 添加自己的1ms的延时函数:
void Halkey_delayms(uint16 ms)//按键延时函数
{
int8 i;
for(i=0;i<ms;i++)
{Onboard_wait(1000);}
}
记得要在 hal_key.h 中进行函数声明:
extern void Halkey_delayms(uint16 ms);
2.找到 hal_key.c 中的 void HalKeyPoll (void) 函数,此函数即是在HAL层轮询时,不断检测按键是否改变的函数,在里面添加自己的延时按键处理:
void HalKeyPoll (void)
{
uint8 keys = 0;
uint16 key_counter=0;
//加入长短按键延时检测
if (!P0_1)
{
Halkey_delayms(10);//松手检测
if (!P0_1)
{
while(!P0_1) //松手后跳出
{
key_counter++; //按下计数
Halkey_delayms(100); //每次循环延时100ms
}
if ( key_counter <= KEY_HOLD_LONG_INTERVAL )
{
keys |= HAL_KEY_SW_6_1;//正常按键
}
else if ( key_counter > KEY_HOLD_LONG_INTERVAL )
{
keys |= HAL_KEY_SW_6_2;//特殊功能按键
}
else
{
keys = 0;
}
}
}
// if (HAL_PUSH_BUTTON3())
if (!P1_3)
{
keys |= HAL_KEY_SW_7;
}
if (!Hal_KeyIntEnable)
{
if (keys == halKeySavedKeys)
{
return;
}
/* Store the current keys for comparation next time */
halKeySavedKeys = keys;
}
else
{
}
/* Invoke Callback if new keys were depressed */
if (keys && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
}
}
说明:如红色部分为按键循环,跳出后进行数值判断,再赋予不同的按键标志。
数值阈值是在 hal_key.h 中进行宏定义 (多定义几组,可以实现更多的区分标志)
#define KEY_HOLD_SHORT_INTERVAL 10 //10*100 ms
#define KEY_HOLD_LONG_INTERVAL 15 //15*100 ms
按键标记则是改写了原来按键的宏定义
/* Switches (keys) */
#define HAL_KEY_SW_3 0x10 // Joystick down
#define HAL_KEY_SW_6_2 0x10 // Joystick down
#define HAL_KEY_SW_6_1 0x20 // Button S1 if available
#define HAL_KEY_SW_7 0x40 // Button S2 if available
3) 按键标志会自发发送到应用层,此时在SampleApp_HandleKeys( uint8 shift, uint8 keys )中进行对应的处理就好。
if ( keys & HAL_KEY_SW_6_1 ) //P0_1
{
uint8 buff[30]={0};
sprintf(buff, "按键SW_6短按\r\n");
HalUARTWrite ( 0, (uint8*)buff, strlen(buff));
}
if ( keys & HAL_KEY_SW_6_2 ) //P0_2
{
uint8 buff[30]={0};
sprintf(buff, "按键SW_6长按\r\n");
HalUARTWrite ( 0, (uint8*)buff, strlen(buff));
}
下面介绍第二种方法:
(2)轮询计数方式
实现:同一个按键按下不同的时间,可以赋予不同的标志,进而可以进行不同的处理操作。
原理:在按下时消抖后,开启HAL层的按键轮询,在轮询体中添加计数累加,并检测按键是否松开,松开后结束轮询,并对按键进行区分处理。
优点:不造成协议栈堵塞,可以在需要用看门狗时,很方便的使用按键复用。
缺点:修改稍微复杂。
实现:
1.在 hal_drivers.c 的 uint16 Hal_ProcessEvent( uint8 task_id, uint16 events )
的函数中,添加自己定义的轮询及处理事件
if (events & HAL_KEY_EVENT)
{

#if (defined HAL_KEY) && (HAL_KEY == TRUE)
/* Check for keys */
HalKeyPoll();

/* if interrupt disabled, do next polling */
if (!Hal_KeyIntEnable)
{
osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);
}
#endif // HAL_KEY

return events ^ HAL_KEY_EVENT;
}
///////////////////////////////////////////////////////
if (events & HAL_KEY_TIME_COUNT_EVENT)
{

#if (defined HAL_KEY) && (HAL_KEY == TRUE)
//按键轮询计数
if(!P0_1)
{
key_Counter ++;
/* if interrupt disabled, do next polling */
if (!Hal_KeyIntEnable)
{
osal_start_timerEx( Hal_TaskID, HAL_KEY_TIME_COUNT_EVENT, 100);
}
}
else
{
HalKeyPoll_Timer_Dell (key_Counter);
key_Counter=0;
osal_stop_timerEx( Hal_TaskID, HAL_KEY_TIME_COUNT_EVENT);
}
#endif // HAL_KEY
return events ^ HAL_KEY_TIME_COUNT_EVENT;
}
///////////////////////////////////////////////////////////
其中 HAL_KEY_TIME_COUNT_EVENT 为在 hal_drivers.h 中宏定义的自己的按键事件
#define HAL_SLEEP_TIMER_EVENT 0x0004
#define PERIOD_RSSI_RESET_EVT 0x0008
#define HAL_KEY_TIME_COUNT_EVENT 0x0010 //自定义按键轮询事件
函数 HalKeyPoll_Timer_Dell (key_Counter); 是轮询结束后的处理函数,在hal_key.c中定义和实现。
2. 按键开启轮询及按键处理函数
在hal_key.c中void HalKeyPoll (void)函数中修改
if (!P0_1)
{
Halkey_delayms(10);//松手检测
if (!P0_1)
{
//开启Driver层按键计数轮询
osal_start_timerEx( Hal_TaskID, HAL_KEY_TIME_COUNT_EVENT, 10);
}
}
其他部分未改变
在void HalKeyPoll (void) 函数下添加按键处理函数
//Driver层按键计数轮询结束处理函数
void HalKeyPoll_Timer_Dell (uint16 key_counter)
{
uint8 keys = 0;
//加入长短按键延时检测
if ( key_counter <= KEY_HOLD_SHORT_INTERVAL )
{
keys |= HAL_KEY_SW_6_1;//正常按键
}
else if ( key_counter <= KEY_HOLD_LONG_INTERVAL )
{
keys |= HAL_KEY_SW_6_2;//特殊功能按键
}
else if ( key_counter > KEY_HOLD_LONG_INTERVAL )
{
keys |= HAL_KEY_SW_6_3;//特殊功能按键
}
else
{
keys = 0;
}
if (!Hal_KeyIntEnable)
{
if (keys == halKeySavedKeys)
{
/* Exit - since no keys have changed */
return;
}
/* Store the current keys for comparation next time */
halKeySavedKeys = keys;
}
else
{
/* Key interrupt handled here */
}
/* Invoke Callback if new keys were depressed */
if (keys && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
}
}
可以看到按键处理和方法一类似,其他部分和HalKeyPoll (void)一致。
记得在在hal_key.h 中添加函数声明:
extern void HalKeyPoll_Timer_Dell (uint16 key_counter);
3.最后不要忘记在 hal_key.c 添加按键计数全局变量的定义
uint16 key_Counter = 0 ;并在hal_key.h中声明 extern uint16 key_Counter ;



原创粉丝点击