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

应用平台: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 ;

 

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值