Z-STACK中按键KEY驱动流程-修改到任意IO口
2013-10-23 16:45
190 查看
|
![](http://img.bimg.126.net/photo/r8OnfryTf6cRztrEjpCkYA==/4510636501805139181.jpg)
安装IAR 8051 7.30B运行安装程序EW8051-EV-730B.exe,这里说一下如何快速的查找代码,按下Ctrl+Shift+f 可以在整个项目中查找你想要的关键字,注意选择和你workspace工作空间对应的文件,通常有CC2430DB和CC2430EB两个。把光标放在函数名上,右键选择Go to definition fo XX就可以跳到该函数定义处,工具栏的Navigate Backward 和Navigate Forward 可以让你来回穿梭,还有很多功能,这里不多说了。安装ZigBee2006下载Zigbee协议栈压缩包swrc073d.zip,安装后一般在C盘可以找到Texas Instruments文件夹,把它复制,考到D盘,我的IAR装在D盘,有必要看下Documents里面的文档,如Create New Application For The CC2430DB_F8W-2005-0033_.pdf如何新建项目;其它的就不多说了,下面是按键的简单说明,可以初步了解一下OSAL;例子目录为:TexasInstruments\ZStack-1.4.3-1.2.1\Projects\zstack\Samples\SimpleApp\CC2430DBWorkspace 选择 simplecollectorEB ;我们先从主函数说起,如果不知主函数在哪,可以Ctrl+Shift+f输入int main查找,...........为省略ZSEG int main( void ){// Turn off interruptsosal_int_disable( INTS_ALL );………………..// Initialze HAL driversHalDriverInit(); //HalKeyInit();初始化按键………………..// Determine the extended addresszmain_ext_addr(); //HalKeyRead();读取按键…………………..osal_init_system(); //RegisterForKeys( sapi_TaskID ); 注册按键任务//或许你的协议栈注册按键不在这里面。那就是在应用层任务初始化里面……………………..// Final board initializationInitBoard( OB_READY ); /*HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);配置按键,默认为轮询方式*/…………………osal_start_system(); // No Return from here 进入系统大循环} // main()从主函数可以看出,里面都是初始化函数init,执行过程HalDriverInit()àHalKeyInit();在HalKeyInit()里基本完成了相应管脚的输入输出配置,然后到zmain_ext_addr();时,判断物理扩展地址是否合法,如果不合法,则LED1一直闪烁,等while ( HAL_KEY_SW_5 != HalKeyRead() )按下把无效的地址初始化为有效地物理地址,然后到osal_init_system();àosalInitTasks();SAPI_Init( taskID );RegisterForKeys( sapi_TaskID );注册按键事件,//注意:可能你的协议栈注册按键不在这里,而在应用层任务初始化里面。你的协议栈可能也没有SAPI_Init( taskID );最后InitBoard( OB_READY );HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);配置按键为中断方式还是轮询方式,从/* Initialize Key stuff */OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);可以看出默认是配置为轮询方式的,这就是主函数大致对按键的处理过程,接下来从HalKeyConfig()入手,void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback){#if (HAL_KEY == TRUE)/* Enable/Disable Interrupt or */Hal_KeyIntEnable = interruptEnable;/* Register the callback fucntion */pHalKeyProcessFunction = cback; //指向回调函数/* Determine if interrupt is enable or not */if (Hal_KeyIntEnable) //如果设为中断方式{………………..进行一些中断的相关配置}else /* Interrupts NOT enabled */ //否则为轮询方式{…………………….osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_POLLING_VALUE); /* Kick off polling */}……………………..}可以看出,配置为轮询方式是时启动osal_start_timerEx()函数,那么这个函数是干什么的呢?这个是系统软定时器,在HAL_KEY_POLLING_VALUE时间(100ms)内会触发系统任务事件,也就是触发uint16 Hal_ProcessEvent( uint8 task_id, uint16 events );触发时会把Hal_TaskID、HAL_KEY_EVENT两个参数传给Hal_ProcessEvent();然后看看Hal_ProcessEvent()里面又做了些什么事,uint16 Hal_ProcessEvent( uint8 task_id, uint16 events ){uint8 *msgPtr;……………………….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();{osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);}#endif // HAL_KEYreturn events ^ HAL_KEY_EVENT;}……………………..}函数里面执行完HalKeyPoll();后,如果还是轮询方式,则再一次启动osal_start_timerEx();如此一来,就会每隔100ms循环进入Hal_ProcessEvent()函数读取按键,也就是说系统每隔100ms扫描一次按键,那么HalKeyPoll()又是干什么的呢?我们继续看看,void HalKeyPoll (void){………………#if defined (HAL_KEY_SW_6_ENABLE)if (!(HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)) /* Key is active low */{keys |= HAL_KEY_SW_6;}#endif#if defined (HAL_KEY_SW_5_ENABLE)if (HAL_KEY_SW_5_PORT & HAL_KEY_SW_5_BIT) /* Key is active high */{keys |= HAL_KEY_SW_5;}#endif………….. 调用HalAdcRead()得出操纵杆的值,是通过AD进来了模拟电压值得出;/* Invoke Callback if new keys were depressed */if (keys && (pHalKeyProcessFunction)){(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL); //回调函数}}该函数读出按键值keys,并执行了回调函数(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL); pHalKeyProcessFunction是在void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)里面pHalKeyProcessFunction = cback;进行赋函数指针的,这样我们就进入回调函数了,我们来看一下回调函数:void OnBoard_KeyCallback ( uint8 keys, uint8 state ) //回调函数{uint8 shift;// shift key (S1) is used to generate key interrupt// applications should not use S1 when key interrupt is enabledshift = (OnboardKeyIntEnable == HAL_KEY_INTERRUPT_ENABLE) ? false : ((keys & HAL_KEY_SW_6) ? true : false);if ( OnBoard_SendKeys( keys, shift ) != ZSuccess )//ZFailure,如果不成功则执行下面{// Process SW1 hereif ( keys & HAL_KEY_SW_1 ) // Switch 1{}…………………}}回调函数里面又调用了OnBoard_SendKeys( keys, shift );接着看byte OnBoard_SendKeys( byte keys, byte state ){keyChange_t *msgPtr;if ( registeredKeysTaskID != NO_TASK_ID )//之前是否RegisterForKeys( sapi_TaskID );注册过?{// Send the address to the taskmsgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );if ( msgPtr ){msgPtr->hdr.event = KEY_CHANGE;msgPtr->state = state;msgPtr->keys = keys;osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );}return ( ZSuccess );}elsereturn ( ZFailure );}如果之前注册过按键事件,那么就会调用osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );发送系统消息,它又会调用osal_set_event(registeredKeysTaskID, SYS_EVENT_MSG );设置事件发生标志,byte osal_set_event( byte task_id, UINT16 event_flag ){if ( task_id < tasksCnt ){halIntState_t intState;HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interruptstasksEvents[task_id] |= event_flag; // Stuff the event bit(s) 置任务标志,HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts}elsereturn ( INVALID_TASK );return ( ZSUCCESS );}然后触发SAPI_ProcessEvent()应用层处理事件,SAPI_ProcessEvent()再调用zb_HandleKeys()函数进行最终的按键处理事件:void zb_HandleKeys( uint8 shift, uint8 keys ){uint8 startOptions;uint8 logicalType;if ( keys & HAL_KEY_SW_5 )//我自己加的sw5按键处理{P1_0=~P1_0;}…………..}经过了层层函数,最终到达了zb_HandleKeys()按键处理函数,其中的各种函数关系我们应该理清,这样对整个系统的OSAL编程有一定的了解,其中按键有两种处理方式,轮询和中断方式,系统默认为轮询方式,下面再看一下中断方式的过程:如果修改InitBoard( OB_READY )里的OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ ENABLE;//原HAL_KEY_INTERRUPT_DISABLEHalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);那么会把按键配置为中断方式,具体可看上面提到的HalKeyConfig()函数;此时如有按键按下,则会进入中断服务函数:HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR ){/* P0IF is cleared by HW for CHVER < REV_E */halProcessKeyInterrupt(); //按键的中断处理if( CHVER >= REV_E ){……………………}}在中断函数中会执行halProcessKeyInterrupt()函数,我们看看void halProcessKeyInterrupt (void){#if (HAL_KEY == TRUE)bool valid=FALSE;#if defined (HAL_KEY_SW_6_ENABLE)if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT) /* Interrupt Flag has been set */{HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Clear Interrupt Flag */valid = TRUE;}#endif#if defined (HAL_KEY_SW_5_ENABLE)if (HAL_KEY_SW_5_PXIFG & HAL_KEY_SW_5_BIT) /* Interrupt Flag has been set */{HAL_KEY_SW_5_PXIFG = ~(HAL_KEY_SW_5_BIT); /* Clear Interrupt Flag */valid = TRUE;}#endifif (valid){osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);//25ms}#endif /* HAL_KEY */}我们终于发现了osal_start_timerEx()函数,在HAL_KEY_DEBOUNCE_VALUE时间(25ms)后再次触发,用于按键去抖,然后osal_start_timerEx()会触发Hal_ProcessEvent()函数,这样就和轮询方式的后半部分是一样的,也就是说中断法和轮询法在前面的不同,一旦遇到Hal_ProcessEvent(),那么后面的也就一样了,这就是整个按键的处理过程.
![](http://img.bimg.126.net/photo/JxxwLNVNfF9JRmD9f4jgQA==/4510636501805139182.jpg)
相关文章推荐
- Z-STACK中按键KEY驱动的处理
- ZigBee TI ZStack CC2530 3.14 按键驱动01-轮询模式
- 精读OSAL --按键的执行流程(hal_key.c onboard.c)
- mini2440 KEY按键设备驱动(中断模式和查询模式)源代码--(宋宝华框架)
- linux驱动之input子系统之按键驱动编写流程(三)
- A10开发板增加红外驱动及android层红外按键修改介绍
- android定制化软件修改或添加按键驱动的核心操作步骤讲解
- 任意2个io直接驱动LCD1602,并且不需外加芯片(转)
- uboot流程分析--修改android启动模式按键
- A10开发板增加红外驱动及android层红外按键修改介绍
- Z-Stack/ble OSAL 中OSAL按键事件的触发流程分析
- [RK3288][Android6.0] 系统按键驱动流程分析【转】
- 把驱动编译进内核的3种方法(mini2440 key按键为例)
- ZigBee TI ZStack CC2530 3.15 按键驱动02-中断模式
- A10开发板增加红外驱动及android层红外按键修改介绍
- uboot流程分析--修改android启动模式按键
- 关于设备栈,IO栈,IO_STACK_LOCATION----文件系统过滤驱动学习收获
- android定制化软件修改或添加按键驱动的核心操作步骤讲解
- MTK6577+Android之按键(key)修改
- uboot流程分析--修改android启动模式按键