按键机制教学内容.docx
- 文档编号:5043244
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:21
- 大小:82.01KB
按键机制教学内容.docx
《按键机制教学内容.docx》由会员分享,可在线阅读,更多相关《按键机制教学内容.docx(21页珍藏版)》请在冰豆网上搜索。
按键机制教学内容
按键机制
Zstack的按键机制
这一节我们看按键机制,后续会陆续看UART机制和绑定机制,通过这三大机制深入学习Zstack消息的传递机制,掌握Zstack开发流程。
1、了解TI的EB板按键
TI的EB板按键资源有一个独立按键和一个摇杆。
独立按键连接到P0_1,摇杆四个方向串联电阻连接到P0_6,摇杆的确认按钮(中心按键)连接到P0_5,类似与独立按键。
TI的EB板按键部分原理图:
A)独立按键原理图:
图1:
EB板独立按键原理图
由原理图可以看出按键为低电平有效。
B)摇杆按键原理图
图1:
EB板摇杆按键原理图(这个图想横着占一页)
由原理图可以看出摇杆的确认按钮(中心按键)是高电平有效。
2、轮询与中断
Zstack中提供了两种方式采集按键数据:
轮询方式和中断方式。
轮询方式:
中断方式:
3、按键的初始化
A)、相关宏定义
在key.c文件中定义了关于按键的宏。
注意按键初始化配置属于底层驱动的配置,在涉及到底层时会遇到大量的CC2430寄存器,要养成查看datasheet的好习惯。
①、按键6(SW6)对应原理图的独立按键S1,按键6(SW6)相关的宏定义:
#defineHAL_KEY_BIT00x01
#defineHAL_KEY_BIT10x02
#defineHAL_KEY_BIT20x04
#defineHAL_KEY_BIT30x08
#defineHAL_KEY_BIT40x10
#defineHAL_KEY_BIT50x20
#defineHAL_KEY_BIT60x40
#defineHAL_KEY_BIT70x80
#ifdefined(HAL_BOARD_CC2430EB)||defined(HAL_BOARD_CC2430BB)
#defineHAL_KEY_SW_6_ENABLE
#defineHAL_KEY_SW_6_PORTP0
#defineHAL_KEY_SW_6_BITHAL_KEY_BIT1
#defineHAL_KEY_SW_6_SELP0SEL
#defineHAL_KEY_SW_6_DIRP0DIR
#defineHAL_KEY_SW_6_IENIEN1
#defineHAL_KEY_SW_6_IENBITHAL_KEY_BIT5
#defineHAL_KEY_SW_6_EDGEHAL_KEY_RISING_EDGE
#defineHAL_KEY_SW_6_EDGEBITHAL_KEY_BIT0
#defineHAL_KEY_SW_6_ICTLPICTL
#defineHAL_KEY_SW_6_ICTLBITHAL_KEY_BIT3
#defineHAL_KEY_SW_6_PXIFGP0IFG
#defineHAL_KEY_P0INT_LOW_USEDHAL_KEY_SW_6_BIT
#endif
②、按键5(SW5)对应原理图的摇杆的确认按钮(中心按键),摇杆相关宏定义:
#ifdefined(HAL_BOARD_CC2430EB)
#defineHAL_KEY_JOYSTICK_ENABLE
#defineHAL_KEY_JOY_CHNHAL_ADC_CHANNEL_6
#defineHAL_KEY_SW_5_ENABLE
#defineHAL_KEY_SW_5_PORTP0
#defineHAL_KEY_SW_5_BITHAL_KEY_BIT5
#defineHAL_KEY_SW_5_SELP0SEL
#defineHAL_KEY_SW_5_DIRP0DIR
#defineHAL_KEY_SW_5_INPP0INP
#defineHAL_KEY_SW_5_IENIEN1
#defineHAL_KEY_SW_5_IENBITHAL_KEY_BIT5
#defineHAL_KEY_SW_5_EDGEHAL_KEY_RISING_EDGE
#defineHAL_KEY_SW_5_EDGEBITHAL_KEY_BIT2
#defineHAL_KEY_SW_5_ICTLPICTL
#defineHAL_KEY_SW_5_ICTLBITHAL_KEY_BIT4
#defineHAL_KEY_SW_5_PXIFGP0IFG
#defineHAL_KEY_POINT_HIGH_USEDHAL_KEY_SW_5_BIT
#endif
B)、代码分析:
按键的初始化属于硬件的初始化,在Zstack中硬件驱动在HalDriverInit()集中处理。
在主函数Main中调用了函数HalDriverInit()进行硬件驱动的初始化,该函数根据编译选项对硬件逐个进行了初始化。
HalDriverInit()代码如下:
程序代码:
voidHalDriverInit(void)
{
/*定时器*/
HalTimerInit();
/*ADC*/
#if(definedHAL_ADC)&&(HAL_ADC==TRUE)
HalAdcInit();
#endif
……
/*LED灯*/
#if(definedHAL_LED)&&(HAL_LED==TRUE)
HalLedInit();
#endif
/*串口*/
#if(definedHAL_UART)&&(HAL_UART==TRUE)
HalUARTInit();
#endif
/*按键*/
#if(definedHAL_KEY)&&(HAL_KEY==TRUE)
HalKeyInit();
#endif
}
由上述代码可以看出除定时器以外其它初始化都是根据条件进行初始化的,这里满足按键初始化条件。
注:
硬件驱动初始化没有完全列举,可以参见具体协议栈。
程序代码:
/*
SettoTRUEenableKEYusage,FALSEdisableit
Notes:
On2430EB/DBanalogjoystickisusedtosimulate
keys.Keyswon'tworkunlessHAL_ADCisalsoset
toTRUE
*/
#ifndefHAL_KEY
#defineHAL_KEYTRUE
#endif
上述代码摘自hal_board_cfg.h文件,从上述代码可以看出:
TI的Zstack协议栈默认是使用独立按键的。
使用摇杆的时候还要确保HAL_ADC为真,即Zstack协议栈使用AD采集。
关于HAL_ADC代码如下:
程序代码:
/*SettoTRUEenableADCusage,FALSEdisableit*/
#ifndefHAL_ADC
#defineHAL_ADCTRUE
#endif
上述代码同样摘自hal_board_cfg.h文件,可以看出Zstack协议栈默认使用AD转换器。
由上述#defineHAL_KEYTRUE和#defineHAL_ADCTRUE可以知道在TI的Zstack协议栈默认情况既可以使用普通的独立按键也可以使用模拟的摇杆。
voidHalKeyInit(void)
{
#if(HAL_KEY==TRUE)
halKeySavedKeys=0;
#ifdefined(HAL_KEY_SW_6_ENABLE)
HAL_KEY_SW_6_SEL&=~(HAL_KEY_SW_6_BIT);//设定为通用I/O口
HAL_KEY_SW_6_DIR&=~(HAL_KEY_SW_6_BIT);//设置为输入模式
#endif
#ifdefined(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_BIT);//设置为输入模式
HAL_KEY_SW_5_INP|=HAL_KEY_SW_5_BIT;//设置为三态模式
#endif
pHalKeyProcessFunction=NULL;
HalKeyConfigured=FALSE;
#endif/*HAL_KEY*/
}
按键驱动初始化函数HalKeyInit()说明:
⑴、配置了三个全局变量。
全局变量halKeySavedKeys是用来保存按键值的,初始化时将其初始化为0;pHalKeyProcessFunction为指向按键处理函数的指针,当有按键按下时调用按键处理函数对按键进行处理,初始化时将其初始化为NULL,在按键的配置函数中对其进行配置;全局变量HalKeyConfigured用来标示按键是否被配置,初始化时没有配置按键,所以此时该变量被初始化为FALSE。
⑵、配置了两个按键的I/O口。
函数中用条件语句判定是否使能了SW5和SW6,由前面的宏定义可以看出,如果使用的是TI的EB板,则SW5和SW6都将被使能。
有上述代码可以看出按键驱动初始化函数HalKeyInit()将与SW5和SW6相连接的I/O设定通用I/O口,并都设置为输入模式。
而且将SW5的输入模式设定为三态。
4、按键的配置
按键的初始化只是简单的对按键进行了初始化与I/O的配置,如果要使用Zstack的按键仍需要进一步对按键进行配置,下面我们着重理清按键的配置。
Zstack对按键处理提供了两种方法:
轮询法和中断法。
在配置按键时也是分为两种情况与之对应。
我们这里对两种配置模式逐一说明。
Zstack默认使用轮询的方式处理,我们先以轮询入手。
A)、配置轮询方式的按键
TI的Zstack为什么会默认使用轮询方式对按键进行处理?
其实最重要的一点是因为TI的EB和ED板都有摇杆。
因为摇杆的四个方向是以电压的大小区分的,是不能产生中断的。
如果使用了中断方式对按键进行处理那么摇杆的四个方向键就是摆设了,所以TI的Zstack采取轮询的方式处理按键。
为什么要使用摇杆?
其实原因也很简单,为了节省I/O口资源,CC2430只有21个通用I/O口,如果使用一个摇杆就可以就可以节省使用三个独立I/O口。
代码分析:
按键的配置函数在板载初始化函数InitBoard()中被调用,函数InitBoard()负责板载的初始化与配置。
HalKeyConfig()决定了将按键的处理方式为轮询方式或者是中断方式。
程序代码:
#defineHAL_KEY_INTERRUPT_DISABLE0x00
#defineHAL_KEY_INTERRUPT_ENABLE0x01
voidInitBoard(bytelevel)
{
……
OnboardKeyIntEnable=HAL_KEY_INTERRUPT_DISABLE;//使用轮询方式
HalKeyConfig(OnboardKeyIntEnable,OnBoard_KeyCallback);
……
}
板载初始化函数InitBoard()说明:
由代码HAL_KEY_INTERRUPT_DISABLE得知处理方式被设置为轮询方式。
如果我们要设置为中断方式,只需要给变量OnboardKeyIntEnable赋值HAL_KEY_INTERRUPT_ENABLE即可。
另一个参数OnBoard_KeyCallback是按键处理的回调函数的函数名,如果有按键按下时将会调用这个回调函数进行处理。
该按键回调函数会在按键处理详细说明。
程序代码:
voidHalKeyConfig(boolinterruptEnable,halKeyCBack_tcback)
{
#if(HAL_KEY==TRUE)
Hal_KeyIntEnable=interruptEnable;//保存参数决定处理方式是轮询或是中断
pHalKeyProcessFunction=cback;//保存参数按键处理的回调函数
if(Hal_KeyIntEnable)//如果为真则配置为中断方式
{
……
}
else//否则配置为轮询方式
{
……
#ifdefined(HAL_KEY_SW_6_ENABLE)
HAL_KEY_SW_6_ICTL&=~(HAL_KEY_SW_6_ICTLBIT);//清除中断HAL_KEY_SW_6_IEN&=~(HAL_KEY_SW_6_IENBIT);
#endif
#ifdefined(HAL_KEY_SW_5_ENABLE)
HAL_KEY_SW_5_ICTL&=~(HAL_KEY_SW_5_ICTLBIT);HAL_KEY_SW_5_IEN&=~(HAL_KEY_SW_5_IENBIT);
#endif
osal_start_timerEx(Hal_TaskID,HAL_KEY_EVENT,L_KEY_POLLING_VALUE);
//定时触发事件HAL_KEY_EVENT,溢出时间为HAL_KEY_POLLING_VALUE。
}
HalKeyConfigured=TRUE;
#endif/*HAL_KEY*/
}
按键配置函数HalKeyConfig()说明:
⑴、配置三个全局变量。
Hal_KeyIntEnable保存了按键处理方式,全局变量pHalKeyProcessFunction保存了按键处理的回调函数,在按键处理工程中将被调用。
第三个变量仍是HalKeyConfigured用来标示按键是否配置,当按键配置完成将其设定为TRUE。
⑵、配置两个按键。
由于上述代码使用的是轮询方式对按键事件进行配置,就不允许按键产生中断。
在配置按键SW5和SW6时将其对应的中断使能禁止。
具体配置代码需参见按键相关宏定义和CC2340的datasheet进行理解。
⑶、事件HAL_KEY_EVENT,在将按键配置为轮询方式后,Zstack会定时触发事件HAL_KEY_EVENT检测是否有按键按下。
定时器的溢出时长为HAL_KEY_POLLING_VALUE。
事件的处理我们后续讲解,这里完成了轮询方式的配置,接下来我们看如何将按键配置为中断方式。
B)、配置中断方式的按键
为了让大家能更加深入了解Zstack中机制和数据流的传递。
虽然TI的Zstack默认是以轮询方式处理按键,但其中断方式的代码都给我们准备好了,只需我们稍微改动一点即可。
下面一起看如何将按键配置为中断方式。
程序代码:
代码分析:
按键的配置函数在板载初始化函数InitBoard()中被调用,函数InitBoard()负责板载的初始化与配置。
在函数InitBoard()调用按键配置函数HalKeyConfig()根据参数值对按键进行配置,决定了将按键的处理方式为轮询方式或者是中断方式。
程序代码:
#defineHAL_KEY_INTERRUPT_DISABLE0x00
#defineHAL_KEY_INTERRUPT_ENABLE0x01
voidInitBoard(bytelevel)
{
……
OnboardKeyIntEnable=HAL_KEY_INTERRUPT_ENABLE;//使用中断方式
HalKeyConfig(OnboardKeyIntEnable,OnBoard_KeyCallback);
……
}
程序代码:
voidHalKeyConfig(boolinterruptEnable,halKeyCBack_tcback)
{
#if(HAL_KEY==TRUE)
Hal_KeyIntEnable=interruptEnable;//保存参数决定处理方式是轮询或是中断
pHalKeyProcessFunction=cback;//保存参数按键处理的回调函数
if(Hal_KeyIntEnable)
{
……
#ifdefined(HAL_KEY_SW_5_ENABLE)
PICTL&=~(HAL_KEY_SW_5_EDGEBIT);//设定上升沿或者下降沿触发
#if(HAL_KEY_SW_5_EDGE==HAL_KEY_FALLING_EDGE)
PICTL|=HAL_KEY_SW_5_EDGEBIT;
#endif
HAL_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);//清除中断标志
#endif
#ifdefined(HAL_KEY_SW_6_ENABLE)
PICTL&=~(HAL_KEY_SW_6_EDGEBIT);//设定上升沿或者下降沿触发
#if(HAL_KEY_SW_6_EDGE==HAL_KEY_FALLING_EDGE)
PICTL|=HAL_KEY_SW_6_EDGEBIT;
#endif
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);/清除中断标志
#endif
……
}
else
……
HalKeyConfigured=TRUE;
#endif/*HAL_KEY*/
}
按键配置函数HalKeyConfig()说明:
⑴、配置三个全局变量。
⑵、配置两个按键。
我们这里是要将按键配置为中断方式。
需要将按键配置为上升沿或是下降沿触发,同时需要将按键的对应I/O口配置为允许中断,即中断使能。
在配置触发沿时首先默认配置为上升沿,然后检测按键相关宏定义决定是否需要配置为下降沿。
在配置完中断使能后清除中断标志位允许按键中断。
具体配置代码需参见按键相关宏定义和CC2340的datasheet进行理解。
⑶、将按键配置为中断方式,在程序中没有触发类似HAL_KEY_EVENT的事件,而是交由中断函数进行处理,当有按键按下时中断函数就会捕获中断,从而调用按键的处理函数进一步进行相关处理。
关于中断方式的按键处理将在后面的进行梳理。
5、按键的处理
A)、轮询方式处理
轮询方式是TI的Zstack对按键默认的处理方式,Zstack会每隔100ms对按键检测一次,如果有按键按下就执行相关的处理。
Zstack是以每隔100ms触发一次HAL_KEY_EVENT事件实现的轮询的,定时器溢出时间HAL_KEY_POLLING_VALUE即为轮询的的间隔。
Zstack每次轮询按键都会与保存的按键值(halKeySavedKeys)进行对比,保存按键值在按键初始化函数被初始化为0。
如果没有按下即与先前保存的按键值相等,Zstack不进行处理。
如果有按键按下,那么按键值与保存的按键值(halKeySavedKeys)不同,将会调用按键处理回调处理函数进行处理,并将此时得到的按键值保存以便下次比较。
在轮询方式配置完成后,Zstack便触发了事件HAL_KEY_EVENT,其任务ID为Hal_TaskID,则对应的处理函数即为HAL层的事件处理函数Hal_ProcessEvent()。
触发了HAL层的HAL_KEY_EVENT标志着开始了按键的轮询。
详细代码如下:
程序代码:
uint16Hal_ProcessEvent(uint8task_id,uint16events)
{
……
if(events&HAL_KEY_EVENT)
{
#if(definedHAL_KEY)&&(HAL_KEY==TRUE)
HalKeyPoll();
if(!
Hal_KeyIntEnable)
{
osal_start_timerEx(Hal_TaskID,HAL_KEY_EVENT,100);
}
#endif//HAL_KEY
returnevents^HAL_KEY_EVENT;
}
……
}
HAL_KEY_EVENT事件处理说明:
⑴、在处理HAL_KEY_EVENT事件时调用了函数HalKeyPoll(),函数HalKeyPoll()负责检测是否有按键按下,如果有按键按下会触发相应的回调函数。
⑵、在调用函数HalKeyPoll()检测完按键过后,用if条件判断语句检测按键是否是轮询方式处理,这里我们是以轮询方式处理按键,所以满足if条件判断语句的条件,即执行函数osal_start_timerEx()定时再次触发事件HAL_KEY_EVENT,定时长度为100ms,由此可以看出如此的循环的触发事件HAL_KEY_EVENT即完成了对按键的定时轮询。
处理HAL_KEY_EVENT事件时调用了函数HalKeyPoll(),HalKeyPoll()函数进一步来去检测是否有按键按下,其详细代码如下:
程序代码:
#defineHAL_KEY_STATE_NORMAL0x00
#defineHAL_KEY_STATE_SHIFT0x01
voidHalKeyPoll(void)
{
uint8keys=0;////初始键值为0
#ifdefined(HAL_KEY_SW_6_ENABLE)
if(!
(HAL_KEY_SW_6_PORT&HAL_KEY_SW_6_BIT))//SW6低电平有效
{
keys|=HAL_KEY_SW_6;
}
#endif
#ifdefined(HAL_KEY_SW_5_ENABLE)
if(HAL_KEY_SW_5_PORT&HAL_KEY_SW_5_BIT)//SW5高电平有效
{
keys|=HAL_KEY_SW_5;
}
#endif
if(!
Hal_KeyIntEnable)//轮询方式
{
if(keys==halKeySavedKeys)
{
return;
}
halKeySavedKeys=keys;//保存按键值下次比较
}
if(keys&&(pHalKeyProcessFunction))
{
//调用按键回调函数对按键进一步处理
(pHalKeyProcessFunction)(keys,HAL_KEY_STATE_NORMAL);
}
}
Ha
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 按键 机制 教学内容