如何处理 atmega324pb 上的 ISR?

问题描述 投票:0回答:2

我有这个问题: 我想区分触发器(BTN0 和 BTN1 - 这 2 个按钮的引脚在同一个中断向量 - PCINT2 中)。我怎么知道是谁触发了 ISR?

这是 BTN0 的代码(我需要添加什么才能使用这两个按钮?):


#pragma vector=PCINT2_vect
  __interrupt void btn01_press(void)
  {
        
    unsigned char current_btn0_state = BTN0; 
    unsigned char prev_btn0_state = !current_btn0_state;
    
    unsigned char current_btn1_state = BTN=1; 
    unsigned char prev_btn1state = !current_btn1_state;
   
     
    if(current_btn0_state == BTN_RELEASED && prev_btn0_state == BTN_PRESSED) 
      {
      
        if(LED0 == LED_OFF)
          {
            if(current_btn0_state && BTN0 == BTN_RELEASED) // for debouncing
              {
                led_PowerOn_number(L0);
                current_btn0_state = !current_btn0_state;
              }
          }
        else
          {
            if(BTN0 == BTN_RELEASED)
              {
                led_PowerOff_number(L0);
                current_btn0_state = !current_btn0_state;
              }
          }
        return;
    }


// this is is also true, and is executed with first (for BTN0), but i want to be triggered separately.   
// 
//    if(current_btn1_state == BTN_RELEASED && prev_btn1_state == BTN_PRESSED)
//    {
//    
//        if(LED1 == LED_OFF)
//          {
//            if(current_btn1_state && BTN1 == BTN_RELEASED)
//              {
//                led_PowerOn_number(1);
//                initial_btn1_state = !initial_btn1_state;
//              }
//          }
//        else
//          {
//            if(BTN1 == BTN_RELEASED)
//              {
//                led_PowerOff_number(1);
//                initial_btn1_state = !initial_btn1_state;
//              }
//          }
//        return;
//      } 

}

一些答案。一个办法。谢谢

c embedded interrupt
2个回答
0
投票

我解决了。部分地。问题出在我按下/释放按钮的逻辑中(按下== 0)。现在我需要一个没有软延迟的去抖解决方案。

 #pragma vector=PCINT2_vect
  __interrupt void btn01_press(void)
  {
    unsigned char current_btn0_state = BTN0;
    unsigned char current_btn1_state = BTN1; 

    if(current_btn0_state == BTN_PRESSED) // ISR for BTN0
      {
        if(LED0 == LED_OFF)
          {
              led_Sdelay(DEBOUNCING_TIME);
              led_PowerOn_number(L0);
              current_btn0_state = !current_btn0_state;
          }
        else
          {
              led_Sdelay(DEBOUNCING_TIME);
              led_PowerOff_number(L0);
              current_btn0_state = !current_btn0_state;
          }
            return;
      }
       
     if(current_btn1_state == BTN_PRESSED) // ISR for BTN0
      {
        if(LED1 == LED_OFF)
          {
              led_Sdelay(DEBOUNCING_TIME);
              led_PowerOn_number(L1);
              current_btn1_state = !current_btn1_state;
          }
        else
          {
              led_Sdelay(DEBOUNCING_TIME);    
              led_PowerOff_number(L1);
              current_btn1_state = !current_btn1_state;
          }
          return;
    }
        
 } 

0
投票

对按钮使用中断是个坏主意 - 这是可能的,但比你在这里复杂得多 - ISR 中的去抖动方式不可靠,因为你会在弹跳期间捕获很多虚假中断。

专业的解决办法是改用一个间隔5ms或10ms的循环定时器中断。让 ISR 只关心去抖动。将有关按下哪个按钮等的决定留给周围的按钮驱动程序。

它可能看起来像(伪代码):

static volatile uint8_t buttons;

static void timer_isr (void)  // called every 5/10ms etc
{
  static uint8_t prev_port;
  uint8_t port = PORT; // read the register

  if(port == prev_port)
  {
    buttons = port; // only use values that have been stable for 5ms/10ms etc
  } 
  prev_port = port;

  /* clear flags, reset timer etc as required by the timer peripheral */
}

bool is_button_x_pressed (void) // public function called by the user
{
  return buttons & BUTTON_X_MASK;
}
© www.soinside.com 2019 - 2024. All rights reserved.