1、#define HAL_KEY_BIT3 0x08#define HAL_KEY_BIT4 0x10#define HAL_KEY_BIT5 0x20#define HAL_KEY_BIT6 0x40#define HAL_KEY_BIT7 0x80#if defined (HAL_BOARD_CC2430EB) | defined (HAL_BOARD_CC2430BB) #define HAL_KEY_SW_6_ENABLE #define HAL_KEY_SW_6_PORT P0 #define HAL_KEY_SW_6_BIT HAL_KEY_BIT1 #define HAL_KEY_
2、SW_6_SEL P0SEL #define HAL_KEY_SW_6_DIR P0DIR #define HAL_KEY_SW_6_IEN IEN1 #define HAL_KEY_SW_6_IENBIT HAL_KEY_BIT5 #define HAL_KEY_SW_6_EDGE HAL_KEY_RISING_EDGE #define HAL_KEY_SW_6_EDGEBIT HAL_KEY_BIT0 #define HAL_KEY_SW_6_ICTL PICTL #define HAL_KEY_SW_6_ICTLBIT HAL_KEY_BIT3 #define HAL_KEY_SW_6_
3、PXIFG P0IFG #define HAL_KEY_P0INT_LOW_USED HAL_KEY_SW_6_BIT #endif 、按键5(SW5)对应原理图的摇杆的确认按钮(中心按键),摇杆相关宏定义:#if defined (HAL_BOARD_CC2430EB) #define HAL_KEY_JOYSTICK_ENABLE #define HAL_KEY_JOY_CHN HAL_ADC_CHANNEL_6 #define HAL_KEY_SW_5_ENABLE #define HAL_KEY_SW_5_PORT P0 #define HAL_KEY_SW_5_BIT HAL_KEY
4、_BIT5 #define HAL_KEY_SW_5_SEL P0SEL #define HAL_KEY_SW_5_DIR P0DIR #define HAL_KEY_SW_5_INP P0INP #define HAL_KEY_SW_5_IEN IEN1 #define HAL_KEY_SW_5_IENBIT HAL_KEY_BIT5 #define HAL_KEY_SW_5_EDGE HAL_KEY_RISING_EDGE #define HAL_KEY_SW_5_EDGEBIT HAL_KEY_BIT2 #define HAL_KEY_SW_5_ICTL PICTL #define HA
5、L_KEY_SW_5_ICTLBIT HAL_KEY_BIT4 #define HAL_KEY_SW_5_PXIFG P0IFG #define HAL_KEY_POINT_HIGH_USED HAL_KEY_SW_5_BIT #endifB)、代码分析:按键的初始化属于硬件的初始化,在Zstack中硬件驱动在HalDriverInit()集中处理。在主函数Main中调用了函数HalDriverInit()进行硬件驱动的初始化,该函数根据编译选项对硬件逐个进行了初始化。HalDriverInit()代码如下:程序代码:void HalDriverInit (void) /* 定时器 */ Ha
6、lTimerInit();/* ADC */ #if (defined HAL_ADC) & (HAL_ADC = TRUE) HalAdcInit(); #endif /* LED 灯*/ #if (defined HAL_LED) & (HAL_LED = TRUE) HalLedInit(); /* 串口 */ #if (defined HAL_UART) & (HAL_UART = TRUE) HalUARTInit(); /* 按键 */ #if (defined HAL_KEY) & (HAL_KEY = TRUE) HalKeyInit(); 由上述代码可以看出除定时器以外其它初
7、始化都是根据条件进行初始化的,这里满足按键初始化条件。注:硬件驱动初始化没有完全列举,可以参见具体协议栈。/* Set to TRUE enable KEY usage, FALSE disable it Notes: On 2430EB/DB analog joystick is used to simulate keys. Keys wont work unless HAL_ADC is also set to TRUE*/#ifndef HAL_KEY#define HAL_KEY TRUE 上述代码摘自hal_board_cfg.h文件,从上述代码可以看出:TI的Zstack协议栈默认
8、是使用独立按键的。使用摇杆的时候还要确保HAL_ADC为真,即Zstack协议栈使用AD采集。关于HAL_ADC代码如下:/* Set to TRUE enable ADC usage, FALSE disable it */#ifndef HAL_ADC#define HAL_ADC TRUE 上述代码同样摘自hal_board_cfg.h文件,可以看出Zstack协议栈默认使用AD转换器。由上述#define HAL_KEY TRUE和#define HAL_ADC TRUE可以知道在TI的Zstack协议栈默认情况既可以使用普通的独立按键也可以使用模拟的摇杆。void HalKeyIni
9、t( void )#if (HAL_KEY = TRUE) halKeySavedKeys = 0;#if defined (HAL_KEY_SW_6_ENABLE) HAL_KEY_SW_6_SEL &= (HAL_KEY_SW_6_BIT); /设定为通用I/O口 HAL_KEY_SW_6_DIR & /设置为输入模式 #if defined (HAL_KEY_SW_5_ENABLE) HAL_KEY_SW_5_SEL &= (HAL_KEY_SW_5_BIT); /设定为通用I/O口 HAL_KEY_SW_5_DIR & /设置为输入模式 HAL_KEY_SW_5_INP |= HAL_
10、KEY_SW_5_BIT; /设置为三态模式 pHalKeyProcessFunction = NULL; HalKeyConfigured = FALSE;#endif /* HAL_KEY */按键驱动初始化函数HalKeyInit()说明: 、配置了三个全局变量。全局变量halKeySavedKeys是用来保存按键值的,初始化时将其初始化为0;pHalKeyProcessFunction为指向按键处理函数的指针,当有按键按下时调用按键处理函数对按键进行处理,初始化时将其初始化为NULL,在按键的配置函数中对其进行配置;全局变量HalKeyConfigured用来标示按键是否被配置,初始化
11、时没有配置按键,所以此时该变量被初始化为FALSE。、配置了两个按键的I/O口。函数中用条件语句判定是否使能了SW5和SW6,由前面的宏定义可以看出,如果使用的是TI的EB板,则SW5和SW6都将被使能。有上述代码可以看出按键驱动初始化函数HalKeyInit()将与SW5和SW6相连接的I/O设定通用I/O口,并都设置为输入模式。而且将SW5的输入模式设定为三态。4、按键的配置 按键的初始化只是简单的对按键进行了初始化与I/O的配置,如果要使用Zstack的按键仍需要进一步对按键进行配置,下面我们着重理清按键的配置。Zstack对按键处理提供了两种方法:轮询法和中断法。在配置按键时也是分为两
12、种情况与之对应。我们这里对两种配置模式逐一说明。Zstack默认使用轮询的方式处理,我们先以轮询入手。A)、配置轮询方式的按键 TI的Zstack为什么会默认使用轮询方式对按键进行处理?其实最重要的一点是因为TI的EB和ED板都有摇杆。因为摇杆的四个方向是以电压的大小区分的,是不能产生中断的。如果使用了中断方式对按键进行处理那么摇杆的四个方向键就是摆设了,所以TI的Zstack采取轮询的方式处理按键。为什么要使用摇杆?其实原因也很简单,为了节省I/O口资源,CC2430只有21个通用I/O口,如果使用一个摇杆就可以就可以节省使用三个独立I/O口。代码分析: 按键的配置函数在板载初始化函数Ini
13、tBoard()中被调用,函数InitBoard()负责板载的初始化与配置。HalKeyConfig()决定了将按键的处理方式为轮询方式或者是中断方式。#define HAL_KEY_INTERRUPT_DISABLE 0x00#define HAL_KEY_INTERRUPT_ENABLE 0x01void InitBoard( byte level ) OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;/使用轮询方式HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);板载初始化函数In
14、itBoard()说明:由代码 HAL_KEY_INTERRUPT_DISABLE得知处理方式被设置为轮询方式。如果我们要设置为中断方式,只需要给变量OnboardKeyIntEnable赋值HAL_KEY_INTERRUPT_ENABLE即可。另一个参数OnBoard_KeyCallback是按键处理的回调函数的函数名,如果有按键按下时将会调用这个回调函数进行处理。该按键回调函数会在按键处理详细说明。void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback) Hal_KeyIntEnable = interruptEnable;
15、/保存参数决定处理方式是轮询或是中断 pHalKeyProcessFunction = cback; /保存参数按键处理的回调函数 if (Hal_KeyIntEnable)/如果为真则配置为中断方式 else /否则配置为轮询方式HAL_KEY_SW_6_ICTL &= (HAL_KEY_SW_6_ICTLBIT); /清除中断 HAL_KEY_SW_6_IEN &= (HAL_KEY_SW_6_IENBIT);HAL_KEY_SW_5_ICTL &= (HAL_KEY_SW_5_ICTLBIT); HAL_KEY_SW_5_IEN &= (HAL_KEY_SW_5_IENBIT); osa
16、l_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, L_KEY_POLLING_VALUE); /定时触发事件HAL_KEY_EVENT,溢出时间为HAL_KEY_POLLING_VALUE。 HalKeyConfigured = TRUE;按键配置函数HalKeyConfig ()说明: 、配置三个全局变量。Hal_KeyIntEnable保存了按键处理方式,全局变量pHalKeyProcessFunction保存了按键处理的回调函数,在按键处理工程中将被调用。第三个变量仍是HalKeyConfigured用来标示按键是否配置,当按键配置完成将其设定为TR
17、UE。、配置两个按键。由于上述代码使用的是轮询方式对按键事件进行配置,就不允许按键产生中断。在配置按键SW5和SW6时将其对应的中断使能禁止。具体配置代码需参见按键相关宏定义和CC2340的datasheet进行理解。、事件HAL_KEY_EVENT,在将按键配置为轮询方式后,Zstack会定时触发事件HAL_KEY_EVENT检测是否有按键按下。定时器的溢出时长为HAL_KEY_POLLING_ VALUE。事件的处理我们后续讲解,这里完成了轮询方式的配置,接下来我们看如何将按键配置为中断方式。B)、配置中断方式的按键 为了让大家能更加深入了解Zstack中机制和数据流的传递。虽然TI的Zs
18、tack默认是以轮询方式处理按键,但其中断方式的代码都给我们准备好了,只需我们稍微改动一点即可。下面一起看如何将按键配置为中断方式。按键的配置函数在板载初始化函数InitBoard()中被调用,函数InitBoard()负责板载的初始化与配置。在函数InitBoard()调用按键配置函数HalKeyConfig()根据参数值对按键进行配置,决定了将按键的处理方式为轮询方式或者是中断方式。 OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;/使用中断方式if (Hal_KeyIntEnable)PICTL &= (HAL_KEY_SW_5_EDGEBI
19、T); /设定上升沿或者下降沿触发#if (HAL_KEY_SW_5_EDGE = HAL_KEY_FALLING_EDGE) PICTL |= HAL_KEY_SW_5_EDGEBIT; #endifHAL_KEY_SW_5_ICTL |= HAL_KEY_SW_5_ICTLBIT; /设定中断使能 HAL_KEY_SW_5_IEN |= HAL_KEY_SW_5_IENBIT;HAL_KEY_SW_5_PXIFG = (HAL_KEY_SW_5_BIT); /清除中断标志#if defined (HAL_KEY_SW_6_ENABLE) = (HAL_KEY_SW_6_EDGEBIT);
20、/设定上升沿或者下降沿触发 #if (HAL_KEY_SW_6_EDGE = HAL_KEY_FALLING_EDGE) PICTL |= HAL_KEY_SW_6_EDGEBIT;HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT; /设定中断使能HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT;HAL_KEY_SW_6_PXIFG = (HAL_KEY_SW_6_BIT); /清除中断标志 else HalKeyConfigured = TRUE;我们这里是要将按键配置为中断方式。需要将按键配置为上升沿或是下降沿触发,同时需要将
21、按键的对应I/O口配置为允许中断,即中断使能。在配置触发沿时首先默认配置为上升沿,然后检测按键相关宏定义决定是否需要配置为下降沿。在配置完中断使能后清除中断标志位允许按键中断。、将按键配置为中断方式,在程序中没有触发类似HAL_KEY_EVENT的事件,而是交由中断函数进行处理,当有按键按下时中断函数就会捕获中断,从而调用按键的处理函数进一步进行相关处理。关于中断方式的按键处理将在后面的进行梳理。5、按键的处理A)、轮询方式处理 轮询方式是TI的Zstack对按键默认的处理方式,Zstack会每隔100ms对按键检测一次,如果有按键按下就执行相关的处理。Zstack是以每隔100ms触发一次H
22、AL_KEY_EVENT事件实现的轮询的,定时器溢出时间HAL_KEY_POLLING_VALUE即为轮询的的间隔。 Zstack每次轮询按键都会与保存的按键值(halKeySavedKeys)进行对比,保存按键值在按键初始化函数被初始化为0。如果没有按下即与先前保存的按键值相等,Zstack不进行处理。如果有按键按下,那么按键值与保存的按键值(halKeySavedKeys)不同,将会调用按键处理回调处理函数进行处理,并将此时得到的按键值保存以便下次比较。 在轮询方式配置完成后,Zstack便触发了事件HAL_KEY_EVENT,其任务ID为Hal_TaskID,则对应的处理函数即为HAL层
23、的事件处理函数Hal_ProcessEvent()。触发了HAL层的HAL_KEY_EVENT标志着开始了按键的轮询。详细代码如下:uint16 Hal_ProcessEvent( uint8 task_id, uint16 events )if (events & HAL_KEY_EVENT)#if (defined HAL_KEY) & HalKeyPoll(); if (!Hal_KeyIntEnable) osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);#endif / HAL_KEY return events HAL_KEY_
24、EVENT; HAL_KEY_EVENT事件处理说明:、在处理HAL_KEY_EVENT事件时调用了函数HalKeyPoll(),函数HalKeyPoll()负责检测是否有按键按下,如果有按键按下会触发相应的回调函数。、在调用函数HalKeyPoll()检测完按键过后,用if条件判断语句检测按键是否是轮询方式处理,这里我们是以轮询方式处理按键,所以满足if条件判断语句的条件,即执行函数osal_start_timerEx()定时再次触发事件HAL_KEY_EVENT,定时长度为100ms,由此可以看出如此的循环的触发事件HAL_KEY_EVENT即完成了对按键的定时轮询。处理HAL_KEY_E
25、VENT事件时调用了函数HalKeyPoll(),HalKeyPoll()函数进一步来去检测是否有按键按下,其详细代码如下:#define HAL_KEY_STATE_NORMAL 0x00#define HAL_KEY_STATE_SHIFT 0x01void HalKeyPoll (void) uint8 keys = 0; /初始键值为0(HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT) /SW6低电平有效 keys |= HAL_KEY_SW_6; if (HAL_KEY_SW_5_PORT & HAL_KEY_SW_5_BIT) /SW5高电平有效 keys |= HAL_KEY_SW_5;Hal_KeyIntEnable) /轮询方式 if (keys = halKeySavedKeys) return;halKeySavedKeys = keys; /保存按键值下次比较 if (keys & (pHalKeyProcessFunction) /调用按键回调函数对按键进一步处理 (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);Ha
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1