一、基于CC2640R2F的按键开发

背景

今年上半年一直在负责基于CC2640R2F挂锁项目的开发,项目目前基本完成,分享下2640各个外设的开发。

实现功能

短按进入NB模式,长按3s左右进入BLE模式,长按5s关机。

实现步骤

首先按键作为一个输入设备,我们应该把IO口设置成输入上拉模式,其次还涉及到消抖处理,防止误触发。由于该按键需实现长短按,于是把IO口设置成双边沿触发中断,具体实现如下:

//配置IO位输入上拉模式

PIN_Config keyPinsCfg[] =
{
    Board_WakeUpKey | PIN_GPIO_OUTPUT_DIS  | PIN_INPUT_EN  |  PIN_PULLUP,
    
    PIN_TERMINATE
};

//注册按键回调函数

Board_initKeys(SimpleBLEPeripheral_keyChangeHandler);

//按键初始化

void Board_initKeys(keysPressedCB_t appKeyCB)
{
  // Initialize KEY pins. Enable int after callback registered
  KeyHandle = PIN_open(&KeyState, keyPinsCfg);
  PIN_registerIntCb(KeyHandle, Board_keyCallback);    //注册中断,中断触发进入Board_keyCallback函数
 //定义中断触发条件
  PIN_setConfig(KeyHandle,  PIN_BM_IRQ, Board_WakeUpKey   | PIN_IRQ_BOTHEDGES); //电源按键

#ifdef POWER_SAVING    //低功耗状态唤醒
  //Enable wakeup
  PIN_setConfig(KeyHandle,  PINCC26XX_BM_WAKEUP, Board_WakeUpKey   | PINCC26XX_WAKEUP_NEGEDGE);
#endif //POWER_SAVING

  // Setup keycallback for keys  消抖
  Util_constructClock(&keyChangeClock, Board_keyChangeHandler,
                      KEY_DEBOUNCE_TIMEOUT, 0, false, 0);  //手动定时器
  // Set the application callback
  //appKeyCB 入队列的函数指针
  appKeyChangeHandler = appKeyCB;   //通知APP层,有按键触发
}

具体思路

1   //按键消抖,延时16ms处理

static void Board_keyCallback(PIN_Handle hPin, PIN_Id pinId)
{
  Util_restartClock(&keyChangeClock, 16);           //启动定时器,延时消抖
  PIN_clrPendInterrupt(hPin, pinId);  //清中断
}

//按键消抖后,长短按键处理
static void Board_keyChangeHandler(UArg a0)

  uint8_t key_pressed = 0;

2 //检测到下降沿触发,打开定时器
  if (!PIN_getInputValue(Board_WakeUpKey))
  {
     Util_startClock(&keyTime_periodicClock);  //启动定时器,判断长短按键
     key_time = 0;
  }
  else
  {

4 //按键上升沿触发,关闭定时器,事件入队列
     Util_stopClock(&keyTime_periodicClock);
     if (appKeyChangeHandler != NULL)
     {
       if (key_time <= 2)
       {
            key_pressed |= KEY_SHORT;
       }
       else if ((key_time > 2) && (key_time <= 5))
       {
            key_pressed |= KEY_LONG;
       }
       else
       {
            key_pressed |= KEY_TOO_LONG;
       }
     }
    // Notify the application  入队列
    (*appKeyChangeHandler)(key_pressed);
  }
}

3 //APP任务中处理定时器,设定为1s定时器,定时到则key_time++,指示灯亮则松手触发按键的上升沿中断

      case SBP_KEY_TIME_EVT:
        events &= ~SBP_KEY_TIME_EVT;    //清事件ID
        key_time++;
        if (key_time == 3)
        {
            HwGPIOSet(Board_GLED, 1);  //绿LED指示3s到
            Util_startClock(&one_second);  
        }
        else if (key_time == 6)
        {
            HwGPIOSet(Board_RLED, 1);  //红LED指示6s到
            Util_startClock(&one_second);  
        }
        else
        {
            //do nothing
        }
        break;

5 //按键回调函数,入队列

void SimpleBLEPeripheral_keyChangeHandler(uint8 keys)
{
  SimpleBLEPeripheral_enqueueMsg(SBP_KEY_CHANGE_EVT, keys);
}

//入队列函数

static void SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state)
{
  sbpEvt_t *pMsg;
  // Create dynamic pointer to message.
  if ((pMsg = ICall_malloc(sizeof(sbpEvt_t))))
  {
    pMsg->hdr.event = event;
    pMsg->hdr.state = state;
    // Enqueue the message.
    Util_enqueueMsg(appMsgQueue, syncEvent, (uint8*)pMsg);
  }
}

6 //出队列
  case SBP_QUEUE_EVT:
         events &= ~SBP_QUEUE_EVT;
         while (!Queue_empty(appMsgQueue))
         {
           sbpEvt_t *pMsg = (sbpEvt_t *)Util_dequeueMsg(appMsgQueue);
           if (pMsg)
           {
            // Process message.
             SimpleBLEPeripheral_processAppMsg(pMsg);
            // Free the space from the message.
             ICall_free(pMsg);
           }
         }

static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *pMsg)
{
  switch (pMsg->hdr.event)
  {
    case SBP_STATE_CHANGE_EVT:
      SimpleBLEPeripheral_processStateChangeEvt((gaprole_States_t)pMsg->
                                                hdr.state);
      break;

    case SBP_CHAR_CHANGE_EVT:
      SimpleBLEPeripheral_processCharValueChangeEvt(pMsg->hdr.state);
      break;

    case SBP_KEY_CHANGE_EVT:  //按键处理
      SimpleBLEPeripheral_handleKeys(pMsg->hdr.state);
      break;

    default:
      break;
  }
}

7 //APP处理不同的按键事件

static void SimpleBLEPeripheral_handleKeys(uint8_t keys)
{
  switch (keys)
  {
  case KEY_SHORT:


    break;
  //打开蓝牙  
  case KEY_LONG:

    break;
  //断电,切换管理员  
  case KEY_TOO_LONG:

    break;

思路总结

当按键按下,检测到下降沿中断触发,消抖后,打开定时器,计时,3s时间到绿灯亮或则6时间到红灯亮,松手,检测到上升沿中断触发,消抖后,关闭定时器,将对应事件加入队列中,唤醒APP任务,出队列,进行相应的事件处理。

你可能感兴趣的:(TI-CC2640R2F)