ZiGbee CC2530 OSAL系统 按键事件讲解

因朋友所托而我也正在学习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_KEY) && (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);
    }

好了,按键的流程就讲完了 希望对你们有帮助 也希望写出这文章能让我记得更牢固写,或者以后忘记了可以翻出来看看。

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值