ZiGbee CC2530 OSAL系统 按键事件讲解
2017-03-24 15:01
239 查看
因朋友所托而我也正在学习Zigbee跟BLE4.0所以就花了两小时先看了下KEY的运作原理 下面来介绍下
首先打开Zmain.c文件的main函数我们可以看到 HalDriverInit(); 硬件抽象层也就是驱动层的初始化 ,里面有很多芯片外设的初始化 包括KEY
我们go to跟上会发现这个函数里面是所有按键的初始化设置 DIR跟SEL寄存器
我们继续回到main.c文件的main函数
里面有调用按钮初始化函数
继续go to
这里宏定义带进去的是OB_COLD,所以这里的调用是先初始化if检测成立的 主要任务是关闭所有中断
而else里面的什么时候被执行呢 ,我们继续到main函数
在系统初始化完成后又再一次调用了这个函数
而这次带进的参数是
这次会进入否则语句
这次则会调用hal_key.c文件里面的按键配置,带入的第一个参数是HAL_KEY_INTERRUPT_ENABLE
按键的检查方式有两种:
1:轮询的方式
2:外部中断的方式
进入HalKeyConfig函数我们可以看到有if判断
Hal_KeyIntEnable参数已经等于函数带入的interruptEnable
Hal_KeyIntEnable = HAL_KEY_INTERRUPT_ENABLE
则配置IO的中断寄存器等
如果不成立Hal_KeyIntEnable = HAL_KEY_INTERRUPT_DISABLE 时
测不产生中断 清除配置寄存器并且触发一个事件
osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
这个事件在hal_drivers.c文件里的Hal_ProcessEvent函数被处理
事件里面调用了HalKeyPoll来检查哪个按键被按下 这个函数是被 轮训方式 的时候调用 中断方式也会调用这个来检测
而这个函数里面有一个指针pHalKeyProcessFunction这个是halKeyCBack_t类型的指针变量
类型定义:typedef void (*halKeyCBack_t) (uint8 keys, uint8 state);
他在HalKeyConfig被调用的时候被赋值了HalKeyConfig带进的第二个参数 也就是回调函数的地址
相当于这个指针可以调用OnBoard_KeyCallback函数 因为在HalKeyConfig被调用的时候就已经OnBoard_KeyCallback函数的地址传递给了pHalKeyProcessFunction指针
好了 现在回到刚刚讲的HalKeyPoll函数
我们开最后的两句 if(keys && (pHalKeyProcessFunction))
检测keys是否成立 如果有按键按下则按位 |(或)上则成立 (&&)并且检测pHalKeyProcessFunction是否成立 如果没有设置回调这个地址会是0 现在它已经被赋值了所以….
成立测调用OnBoard_KeyCallback并带入参数keys和一个宏定义 额。。。这个宏定义在这个函数里并没什么操作 请看代码:
这个函数里面有调用了OnBoard_SendKeys并且带入keys参数以及shift也就是HAL_KEY_SW_6是否被按下..
为什么这么做我也不清楚….
我们来看OnBoard_SendKeys函数
检测registeredKeysTaskID有没被注册
给msgPtr分配内存
发送了这个信号之后触发SampleApp.c文件的SampleApp_ProcessEvent任务里的系统事件
接下来你懂得 ….
如果是轮训方式的话在第一次设置HAL_KEY_EVENT事件的时候就已经开始定时100毫秒后再次触发事件了
这样的话就可以100ms调用一次HalKeyPoll函数来检测按键了
好了,按键的流程就讲完了 希望对你们有帮助 也希望写出这文章能让我记得更牢固写,或者以后忘记了可以翻出来看看。
首先打开Zmain.c文件的main函数我们可以看到 HalDriverInit(); 硬件抽象层也就是驱动层的初始化 ,里面有很多芯片外设的初始化 包括KEY
/* KEY */ #if (defined HAL_KEY) && (HAL_KEY == TRUE) HalKeyInit(); #endif
我们go to跟上会发现这个函数里面是所有按键的初始化设置 DIR跟SEL寄存器
void HalKeyInit( void ) { /* Initialize previous key to 0 */ halKeySavedKeys = 0; HAL_KEY_SW_6_SEL &= ~(HAL_KEY_SW_6_BIT); /* Set pin function to GPIO */ HAL_KEY_SW_6_DIR &= ~(HAL_KEY_SW_6_BIT); /* Set pin direction to Input */ HAL_KEY_JOY_MOVE_SEL &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin function to GPIO */ HAL_KEY_JOY_MOVE_DIR &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin direction to Input */ /* Initialize callback function */ pHalKeyProcessFunction = NULL; /* Start with key is not configured */ HalKeyConfigured = FALSE; }
我们继续回到main.c文件的main函数
里面有调用按钮初始化函数
继续go to
// Initialize board I/O InitBoard( OB_COLD );
这里宏定义带进去的是OB_COLD,所以这里的调用是先初始化if检测成立的 主要任务是关闭所有中断
void InitBoard( uint8 level ) { if ( level == OB_COLD ) { // IAR does not zero-out this byte below the XSTACK. *(uint8 *)0x0 = 0; // Interrupts off osal_int_disable( INTS_ALL ); // Check for Brown-Out reset ChkReset(); } else // !OB_COLD { /* Initialize Key stuff */ HalKeyConfig(HAL_KEY_INTERRUPT_ENABLE, OnBoard_KeyCallback); } }
而else里面的什么时候被执行呢 ,我们继续到main函数
在系统初始化完成后又再一次调用了这个函数
// Final board initialization InitBoard( OB_READY );
而这次带进的参数是
#define OB_READY 2
这次会进入否则语句
else // !OB_COLD { /* Initialize Key stuff */ HalKeyConfig(HAL_KEY_INTERRUPT_ENABLE, OnBoard_KeyCallback); }
这次则会调用hal_key.c文件里面的按键配置,带入的第一个参数是HAL_KEY_INTERRUPT_ENABLE
按键的检查方式有两种:
1:轮询的方式
2:外部中断的方式
进入HalKeyConfig函数我们可以看到有if判断
void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback) { /* Enable/Disable Interrupt or */ Hal_KeyIntEnable = interruptEnable; /* Register the callback fucntion */ pHalKeyProcessFunction = cback; /* Determine if interrupt is enable or not */ if (Hal_KeyIntEnable) { /* Rising/Falling edge configuratinn */ PICTL &= ~(HAL_KEY_SW_6_EDGEBIT); /* Clear the edge bit */ /* For falling edge, the bit must be set. */ #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE) PICTL |= HAL_KEY_SW_6_EDGEBIT; #endif /* Interrupt configuration: * - Enable interrupt generation at the port * - Enable CPU interrupt * - Clear any pending interrupt */ 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); /* Rising/Falling edge configuratinn */ HAL_KEY_JOY_MOVE_ICTL &= ~(HAL_KEY_JOY_MOVE_EDGEBIT); /* Clear the edge bit */ /* For falling edge, the bit must be set. */ #if (HAL_KEY_JOY_MOVE_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_EDGEBIT; #endif /* Interrupt configuration: * - Enable interrupt generation at the port * - Enable CPU interrupt * - Clear any pending interrupt */ HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_ICTLBIT; HAL_KEY_JOY_MOVE_IEN |= HAL_KEY_JOY_MOVE_IENBIT; HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT); /* Do this only after the hal_key is configured - to work with sleep stuff */ if (HalKeyConfigured == TRUE) { osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT); /* Cancel polling if active */ } } else /* Interrupts NOT enabled */ { HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */ HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT); /* Clear interrupt enable bit */ osal_set_event(Hal_TaskID, HAL_KEY_EVENT); } /* Key now is configured */ HalKeyConfigured = TRUE; }
Hal_KeyIntEnable参数已经等于函数带入的interruptEnable
Hal_KeyIntEnable = HAL_KEY_INTERRUPT_ENABLE
则配置IO的中断寄存器等
如果不成立Hal_KeyIntEnable = HAL_KEY_INTERRUPT_DISABLE 时
测不产生中断 清除配置寄存器并且触发一个事件
osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
这个事件在hal_drivers.c文件里的Hal_ProcessEvent函数被处理
if (events & HAL_KEY_EVENT) { #if (defined HAL_KE 4000 Y) && (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; }
事件里面调用了HalKeyPoll来检查哪个按键被按下 这个函数是被 轮训方式 的时候调用 中断方式也会调用这个来检测
void HalKeyPoll (void) { uint8 keys = 0; if ((HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT)) /* Key is active HIGH */ { // keys = halGetJoyKeyInput(); } /* If interrupts are not enabled, previous key status and current key status * are compared to find out if a key has changed status. */ 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 */ } if (HAL_PUSH_BUTTON1()) { keys |= HAL_KEY_SW_6; } /* Invoke Callback if new keys were depressed */ if (keys && (pHalKeyProcessFunction)) { (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL); } }
而这个函数里面有一个指针pHalKeyProcessFunction这个是halKeyCBack_t类型的指针变量
类型定义:typedef void (*halKeyCBack_t) (uint8 keys, uint8 state);
他在HalKeyConfig被调用的时候被赋值了HalKeyConfig带进的第二个参数 也就是回调函数的地址
相当于这个指针可以调用OnBoard_KeyCallback函数 因为在HalKeyConfig被调用的时候就已经OnBoard_KeyCallback函数的地址传递给了pHalKeyProcessFunction指针
好了 现在回到刚刚讲的HalKeyPoll函数
我们开最后的两句 if(keys && (pHalKeyProcessFunction))
检测keys是否成立 如果有按键按下则按位 |(或)上则成立 (&&)并且检测pHalKeyProcessFunction是否成立 如果没有设置回调这个地址会是0 现在它已经被赋值了所以….
成立测调用OnBoard_KeyCallback并带入参数keys和一个宏定义 额。。。这个宏定义在这个函数里并没什么操作 请看代码:
void OnBoard_KeyCallback ( uint8 keys, uint8 state ) { uint8 shift; (void)state; shift = (keys & HAL_KEY_SW_6) ? true : false; if ( OnBoard_SendKeys( keys, shift ) != ZSuccess ) { // Process SW1 here if ( keys & HAL_KEY_SW_1 ) // Switch 1 { } // Process SW2 here if ( keys & HAL_KEY_SW_2 ) // Switch 2 { } // Process SW3 here if ( keys & HAL_KEY_SW_3 ) // Switch 3 { } // Process SW4 here if ( keys & HAL_KEY_SW_4 ) // Switch 4 { } // Process SW5 here if ( keys & HAL_KEY_SW_5 ) // Switch 5 { } // Process SW6 here if ( keys & HAL_KEY_SW_6 ) // Switch 6 { } } }
这个函数里面有调用了OnBoard_SendKeys并且带入keys参数以及shift也就是HAL_KEY_SW_6是否被按下..
为什么这么做我也不清楚….
我们来看OnBoard_SendKeys函数
uint8 OnBoard_SendKeys( uint8 keys, uint8 state ) { keyChange_t *msgPtr; if ( registeredKeysTaskID != NO_TASK_ID ) { // Send the address to the task msgPtr = (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 ); } else return ( ZFailure ); }
检测registeredKeysTaskID有没被注册
给msgPtr分配内存
发送了这个信号之后触发SampleApp.c文件的SampleApp_ProcessEvent任务里的系统事件
接下来你懂得 ….
case KEY_CHANGE: HalUARTWrite(0,"KEY ",4);//串口提示 SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys ); break;
如果是轮训方式的话在第一次设置HAL_KEY_EVENT事件的时候就已经开始定时100毫秒后再次触发事件了
这样的话就可以100ms调用一次HalKeyPoll函数来检测按键了
/* if interrupt disabled, do next polling */ if (!Hal_KeyIntEnable) { osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100); }
好了,按键的流程就讲完了 希望对你们有帮助 也希望写出这文章能让我记得更牢固写,或者以后忘记了可以翻出来看看。
相关文章推荐
- 基于CC2530的zIgbee传感器无线数据采集系统开发(部分关键源码)
- zigbee 是怎样注册,产生,处理 按键事件的?
- Android系统中自定义按键的短按、双击、长按事件
- 2、CC2541芯片中级教程-OSAL操作系统(进一步了解-OLED && 普通按键和5方向按键-中断!!!)这个系统驱动层和应用层不一样~
- ZigBee TI ZStack CC2530 3.14 按键驱动01-轮询模式
- Android系统中自定义按键的短按、双击、长按事件
- 通过代码调整系统音量,监听音量实体按键事件
- zigbee学习笔记--电源管理OSAL机制的ZigBee低功耗管理(CC2530)
- Android 4.0按键事件以及系统流程分析
- zigbee--电源管理OSAL机制的z-statk低功耗管理(CC2530)
- ZigBee TI ZStack CC2530 5.7 实例(三)多功能按键02-指示灯
- Zigbee-cc2530笔记---按键与外部中断
- 奥特曼Zigbee读书日记(二)--OSAL系统框架专题
- c进程读取按键输入,通过socket传输给qt,qt按键线程接收到后,提交到Qt的事件处理系统中
- Android系统中自定义按键的短按、双击、长按事件
- ZIGBEE协议栈-OSAL系统框架专题【转载】
- Android模拟、实现、触发系统按键事件的方法
- OSAL机制的ZigBee低功耗管理(CC2530)
- Android系统中自定义按键的短按、双击、长按事件
- Android系统中自定义按键的短按、双击、长按事件