This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2530: 中断方式按键触发怎么修改触发边缘为上升沿下降沿都触发

Part Number: CC2530


想做按键长按功能,想法是按键按下后记录时间按键松开后再触发一次中断再次记录时间计算时间差,

现在问题是下降沿可以触发,上升沿无法触发

static void zclSampleSw_HandleKeys( byte shift, byte keys )
{
  if(keys & HAL_KEY_SW_6){
    key(keys);
  } 
}




static void key(byte keys){
  static uint32 keyPressTime = 0;
  if(PICTL & 1){//下降沿触发,按键按下
    HAL_KEY_starting_time = osal_getClock();//获取当前系统时间
  }else{//上升沿触发,按键抬起
    keyPressTime = ( osal_getClock() - HAL_KEY_starting_time );//计算按下时间

      if(keyPressTime<=KEY_HOLD_SHORT_INTERVAL){//计算出时间小于预设时间(短按)
        
        printf("short\r\n");
      }else if(keyPressTime>KEY_HOLD_LONG_INTERVAL && keyPressTime<KEY_HOLD_LONG_LONG_INTERVAL){//计算出时间处于两个预设值之间,执行相应功能
        HalLedBlink(HAL_LED_1,10,50,1000);

        printf("long\r\n");
      }else if(keyPressTime>KEY_HOLD_LONG_LONG_INTERVAL){//大于预设值

      }
  }
    PICTL^=1;
}

  • CC2530硬件不支持双边沿触发,参考这里用定时事件实现长按键:https://e2echina.ti.com/support/wireless-connectivity/zigbee-and-thread/f/zigbee-thread-forum/202658/thread

    或者在中断处理函数中根据当前的IO口状态切换触发的电平,这样可以实现类似双边沿触发

  • 现在就是在中断处理函数中切换的触发状态,但是切换后按键无法被检测到,中断能进入,按键不识别

    static void zclSampleSw_HandleKeys( byte shift, byte keys )
    {
    if(keys & HAL_KEY_SW_6){(这里修改触发状态后无法再次进入)
    key(keys);
    }
    }

  • 切换后按键无法被检测到時調試看看register的設置有沒有又被改掉了

  • if(PICTL & 1){//下降沿触发,按键按下

    HAL_KEY_starting_time = osal_getClock();//获取当前系统时间
    }else{//上升沿触发,按键抬起
    keyPressTime = ( osal_getClock() - HAL_KEY_starting_time );//计算按下时间

    程序似乎有些问题,这里的if和else一次只能执行一个

    你需要再调用一次,或者在一个循环里面使用

  • 这个是写在协议栈按键的回调函数里面的,模仿的zstackhome1.2 SampleLight例程里面的按键处理,

    但是只有第一次按下时能进入回调,执行切换中断方式后松开按键和再次按下按键都没办法被正确识别了

    回调函数还是能进入,没办法正确识别到按键

  • 如果你不执行切换中断方式、每次按下时都能进入回调嗎?

  • 可以,我在想是不是按键配置出了问题,或者不能在回调函数里面直接修改中断方式,我试了一下把中中断方式切换放到key.c里面的halProcessKeyInterrupt函数里面,按键能识别到了,不过又出现了新问题

    void halProcessKeyInterrupt (void)
    {
      bool valid=FALSE;
    
      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;
        PICTL^=1;
      }
    
      if (HAL_KEY_JOY_MOVE_PXIFG & HAL_KEY_JOY_MOVE_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
    
      if (valid)
      {
        osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
      }
    
    }

  • 出现了什麼新问题?

  • 因为在key.c里面提前一步修改了中断方式,按键回调中的中断边缘判断失效了,判断出来是相反的结果,

    现在解决方法是是把判断移到了key.c里面,修改中断方式之前,结果用一个全局变量传出去。

    下面这样写功能实现了,但是还是好奇为什么在按键回调里面直接修改中断方式会出问题

    //key.c
    uint8 key_data = 0;
    void halProcessKeyInterrupt (void)
    {
      bool valid=FALSE;
    
      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;
        if(PICTL & 1){
          key_data = 1;
        }else{
          key_data = 0;
        }
        PICTL^=1;
      }
    
      if (HAL_KEY_JOY_MOVE_PXIFG & HAL_KEY_JOY_MOVE_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
    
      if (valid)
      {
        osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
      }
    
    }
    //zcl_samplesw.c
    static uint32 HAL_KEY_starting_time = 0;
    #define KEY_HOLD_SHORT_INTERVAL    2
    #define KEY_HOLD_LONG_INTERVAL     5
    #define KEY_HOLD_LONG_LONG_INTERVAL     10
    static void key(byte keys);
    
    
    static void zclSampleSw_HandleKeys( byte shift, byte keys )
    {
      if(keys & HAL_KEY_SW_6){
        key(keys);
      }
    }
    
    
    static void key(byte keys){
      static uint32 keyPressTime = 0;
      if(key_data & 1){//下降沿触发,按键按下
          HAL_KEY_starting_time = osal_getClock();//获取当前系统时间
          printf("%d\r\n",HAL_KEY_starting_time);
      }else{//上升沿触发,按键抬起
        keyPressTime = ( osal_getClock() - HAL_KEY_starting_time );//计算按下时间
        printf("key_release\r\n");
          if(keyPressTime<=KEY_HOLD_SHORT_INTERVAL){//计算出时间小于预设时间(短按)
    
            printf("short\r\n");
          }else if(keyPressTime>KEY_HOLD_LONG_INTERVAL && keyPressTime<KEY_HOLD_LONG_LONG_INTERVAL){//计算出时间处于两个预设值之间,执行相应功能
    
            printf("long\r\n");
          }else if(keyPressTime>KEY_HOLD_LONG_LONG_INTERVAL){//大于预设值
    
          }
      }
    }