您的位置:首页 > 其它

ZiGbee CC2530 OSAL系统 按键事件讲解

2017-03-24 15:01 239 查看
因朋友所托而我也正在学习Zigbee跟BLE4.0所以就花了两小时先看了下KEY的运作原理 下面来介绍下

首先打开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);
}


好了,按键的流程就讲完了 希望对你们有帮助 也希望写出这文章能让我记得更牢固写,或者以后忘记了可以翻出来看看。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  zigbee物理层