AVR 引脚变化中断不可预测地触发

3

所以,我正在使用带有ATMega168NerdKits套件,并将LCD连接到其中,使用两个中断INT0和INT1。 我想连接一个Grove心率监测器,我已将其连接到PCINT1并尝试启用和使用。

void hrm_init()
{
//clear pin
  DDRB &= ~(1<<DDB0);
  PORTB |= (1<<PORTB0);
//turn on pull up
  PCICR |= (1<<PCIE0);   //enable pcint 1
  PCMSK0 |= (1<<PCINT1); //Trigger on change of PCINT1 (PB1)
  sei();
}

ISR(PCINT0_vect)
{
   uint8_t changedBits;

   changedBits = PINB ^ porthistory;
   porthistory = PINB;

   //pin has changed
   if (changedBits & (1<<PB1)) 
   {     
      beats += ((PINB & _BV(PB1)) ? 1 : 0); //add a beat on the rising edge 
   }
}

这段节拍计数代码是从网上借鉴的,因此使用了宏。

这个代码大部分时间都能正常工作,但有时会增加一些额外的节拍,我曾经见过多达10个节拍,同时我还有一个定时器中断(我将用它来计算每分钟的节拍数)。

void clock_init() 
{
  TCCR0A |= (1<<WGM01);
  TCCR0B |= (1<<CS02) | (1<<CS00);
  OCR0A = 143;
  TIMSK0 |= (1<<OCIE0A);
}

SIGNAL(SIG_OUTPUT_COMPARE0A) {
  the_time++;

  if (the_time > 500)
  {
    bpm = beats;
    bpm *= 12; //60 seconds divided by 5

    the_time = 0;
    beats = 0;
  }
}
1个回答

2
很可能心率监测仪的信号存在噪声。有几种处理方法。一种是硬件滤波器,但你可以使用“去抖动”或“去毛刺”机制在软件中处理它。
下面是一个“去毛刺”机制。你不会预期在几毫秒内出现两个心跳。因此,你可以拒绝(跳过对应计数)在之前的上升沿两毫秒内的任何上升沿。
如果你有一个具有毫秒分辨率的自由运行计时器,请在每个上升沿处捕获计时器。如果与上一个上升沿的差异超过2毫秒,则计算上升沿,否则不计算。当你计算时,保存计时器的值以进行下一次比较。
使用无符号算术进行相减和比较结果与2毫秒。这样,你就不必担心计时器的环绕。
ISR(PCINT0_vect)
{
   static uint16_t last_rising_edge = 0;
   uint8_t changedBits;

   changedBits = PINB ^ porthistory;
   porthistory = PINB;

   //pin has changed
   if (changedBits & (1<<PB1)) 
   {
      uint16_t now = get_milliseconds();

      if (0 != (PINB & _BV(PB1) && (now - last_rising_edge) >= 2u)
      {
          beats += 1; //add a beat on the rising edge
          last_rising_edge = now;
      }
   }
}

我听说过反弹,但我以为单行数字信号不会受到影响,显然我的想法是错误的。谢谢,我会尝试一下,如果有效的话就接受它。 - Ross Drew
2
如果您预计在用于触发中断的引脚上出现故障,您应该将中断更改为轮询机制,或者添加硬件低通滤波器。否则,输入理论上可能会挂起整个CPU,以至于它除了执行中断之外什么也做不了。这对于迟缓的8位MCU尤其如此。 - Lundin
我最初尝试每秒轮询大约10次,但似乎收到了奇怪的结果,连续多次开或关,然后在节拍之间有很长的间隔(与正常运行的心率监测手表相比)。中断似乎效果更好。由于我的心脏不能每秒跳动超过4次,只要我保持中断程序短小精悍,这还会是一个问题吗? 此外,低通滤波器是否比软件更好地消除抖动? - Ross Drew
1
心率监测器的脉冲看起来非常短,如果网页上的示波器跟真实情况相符,那么占空比应该低于1%。因此,轮询不会起作用。我相信我在上面的答案中提出的解决方案是最好的软件方法。它也适用于硬件滤波器。 - Doug Currie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接