(配套源码、软件、开发板等资源,可移步博客同名QQ群/TB店铺:拿破仑940911)
上一节中,我们详细讲述了Z-Stack中按键检测的两种机制——“轮询模式”和“中断模式”。从实现原理来看,“中断模式”比“轮询模式”更加灵敏;更重要的是,在低功耗模式下,“中断模式”功耗更低!因此,在实际应用中,我们更多的是选用“中断模式”来进行按键检测。
这里我们就一起从以下4部分,来实现在Z-Stack协议栈中通过“中断模式”进行按键检测。
1、Z-Stack中原本的按键布局
2、本次实验开发板按键布局
3、“中断模式”按键驱动移植
4、“轮询模式”按键驱动移植
1、Z-Stack中原本的按键布局
详见下表(整理自《Z-Stack User's Guide - CC2530DB.pdf》):
由上表可以看出,TI的官方评估板上除了普通按键之外,还使用了一个五向按键(摇杆joystick)。利用ADC采样实现了一个多功能按键,由于具体实现代码相对较复杂,而在实际应用中很少使用五向按键,所以这里就不详细说明了。如果感兴趣的话,可以使用微雪ZigBee开发板的ZB600底板,上面就有一个五向按键,如下图所示:
Software Mapping
Joystick/Button
Description
IO
HAL_KEY_SW_1
UP
Joystick UP
P0_6
基于模拟量
判断键值
HAL_KEY_SW_2
RIGHT
Joystick RIGHT
HAL_KEY_SW_3
DOWN
Joystick DOWN
HAL_KEY_SW_4
LEFT
Joystick LEFT
HAL_KEY_SW_5
PRESS
Joystick CENTER
P2_0
HAL_KEY_SW_6
S1
Button 1
P0_1
HAL_KEY_SW_7
S2
Button 2
未定义
可以用来做相关实验,此处就不再赘述~
2、本次实验开发板按键布局
本次实验使用的开发板,依旧是微雪的ZigBee开发板(底板为ZB502),对应按键部分原理图如下:
我们将实现的两个按键:
(1)KEY1,P0_1,低电平有效(下降沿触发),对应HAL_KEY_SW_1;
(2)KEY2,P2_0,高电平有效(上升沿触发),对应HAL_KEY_SW_2;
其实也就是对Z-Stack中的按键进行重新布局:
Software Mapping
Button
Description
IO
HAL_KEY_SW_1
S1
Button 1
P0_1
HAL_KEY_SW_2
S2
Button 2
P2_0
HAL_KEY_SW_3
未定义
未定义
未定义
HAL_KEY_SW_4
未定义
未定义
未定义
HAL_KEY_SW_5
未定义
未定义
未定义
HAL_KEY_SW_6
未定义
未定义
未定义
HAL_KEY_SW_7
未定义
未定义
未定义
(以下步骤按程序运行流程进行)
3、“中断模式”按键驱动移植
本次移植会改动到的文件有:OnBoard.c、hal_key.c、hal_key.h、hal_board_cfg.h、ProjectApp.c;除了hal_key.c和hal_key.h之外,其余文件改动都非常少,所以这边仅给出其余文件的改动说明,hal_key.c和hal_key.h两个文件请直接从网盘链接下载查看;
(1)进入OnBoard.c文件,找到InitBoard( )函数中的下面这行代码:
HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);改为如下:
HalKeyConfig(HAL_KEY_INTERRUPT_ENABLE, OnBoard_KeyCallback);即可将按键检测模式选为“中断模式”;(2)进入hal_board_cfg.h文件,找到如下这段宏定义:
/* S1 */ #define PUSH1_BV BV(1) #define PUSH1_SBIT P0_1 #if defined (HAL_BOARD_CC2530EB_REV17) #define PUSH1_POLARITY ACTIVE_HIGH #elif defined (HAL_BOARD_CC2530EB_REV13) #define PUSH1_POLARITY ACTIVE_LOW #else #error Unknown Board Indentifier #endif /* Joystick Center Press */ #define PUSH2_BV BV(0) #define PUSH2_SBIT P2_0 #define PUSH2_POLARITY ACTIVE_HIGH精简修改为:
/* S1 */ #define PUSH1_BV BV(1) #define PUSH1_SBIT P0_1 #define PUSH1_POLARITY ACTIVE_LOW /* S2 */ #define PUSH2_BV BV(0) #define PUSH2_SBIT P2_0 #define PUSH2_POLARITY ACTIVE_HIGH(3)修改hal_key.c文件
此文件中修改较多,此处就不一一说明了,请直接从网盘链接下载查看;此处只着重强调一下两个函数:
a、HalKeyInit( )
该函数中实现的功能,就是对所有使用的按键对应的IO口做普通IO输入的初始化,具体到本次实验中为:i、 配置P0_1为:普通IO、输入、上拉(上电默认高电平);
ii、配置P2_0为:普通IO、输入、下拉(上电默认低电平);
仔细阅读原版代码会发现,协议栈中定义的变量“halKeySavedKeys”对我们的应用并无实际用处,故删除或注释;请仔细阅读修改后的HalKeyInit( )函数,并与原版代码对照;
b、HalKeyConfig( )
该函数在《ZigBee CC2530 Z-Stack 15 按键驱动移植及使用1-检测机制(轮询模式与中断模式)》中已经详细解释过了,我们需要修改的只有该函数中的if( ){ }else{ }条件判断语句这部分代码:
/* Determine if interrupt is enable or not */ if (Hal_KeyIntEnable) { ...... } else /* Interrupts NOT enabled */ { ...... }(4)修改hal_key.h文件
该文件中只是对键值的定义做了修改,以及删除了我们实际应用中并不会用到的五向按键(摇杆joystick)相关的代码,更加精炼;代码详情也请直接从网盘链接下载查看;
(5)实验验证
亲测成功,按键检测非常灵敏!
4、“轮询模式”按键驱动移植
如果连相对复杂的“中断模式”都完全OK了的话,那“轮询模式”再看起来就要简单的多了。从“中断模式”切换到“轮询模式”,仅需做一步修改:进入OnBoard.c文件,找到InitBoard( )函数中的下面这行代码:
HalKeyConfig(HAL_KEY_INTERRUPT_ENABLE, OnBoard_KeyCallback);改为如下:
HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);即可将按键检测模式重新选为“轮询模式”!“轮询模式”的按键检测时间间隔为100ms(即频率为10次/秒),由hal_drivers.c文件中下面这段代码决定:
uint16 Hal_ProcessEvent( uint8 task_id, uint16 events ) { ...... if (!Hal_KeyIntEnable) { osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100); } ...... }
实验验证发现,在按键操作频率较低的情况下,“轮询模式”按键检测几乎没有任何问题。但是当按键操作频率加快后,就会开始出问题了(请亲自实验感受)!“中断模式”自然是不存在这种问题。为了检测更准确,可以适当提高“轮询模式”下检测频率。比如将100ms改为50ms,但是这种改动很有可能又会产生新的问题,如:CPU负载提升、功耗提升等等。
(配套源码、软件、开发板等资源,可移步博客同名QQ群/TB店铺:拿破仑940911)