AVR引脚变化中断点火

时间:2013-11-17 14:12:02

标签: c embedded interrupt avr atmega

所以,我正在使用ATMega168设置NerdKits,并使用两个中断INT0& INT1。我想附加Grove Heart Rate Monitor,我已将其附加到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 个答案:

答案 0 :(得分: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;
      }
   }
}