timer 1 compare A triggered twice (m88)

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What I want is an interrupt in the middle of each PWM pulse. The idea is to trigger when timer 1 reaches TOP and BOTTOM (in one of the phase correct PWM modes).

This is the code I ended up with and TIMER1_COMPA_vect is called twice every now and then.

#include "iodef.h"

#include 
#include 

ISR( TIMER1_OVF_vect) {
  TOGGLE( LED_GREEN);
}

ISR( TIMER1_COMPA_vect) {
  TOGGLE( LED_AMBER);
  //TIFR1  |= _BV( OCF1A);
}


int main(int, char**) {
  ICR1   = uint16_t(F_CPU / 1000);      // TOP := 1ms
  OCR1A  = uint16_t(F_CPU / 1000);      // overflow
  OCR1B  = uint16_t(F_CPU / 1000) / 2;  // 50:50 duty cycle
  TCCR1A = _BV( COM1B1) | _BV( COM1B1); // set/clear COM1B
  TCCR1B = _BV( WGM13) | _BV( CS10);    // mode 13, clk = 12MHz
  TIMSK1 = _BV( OCIE1A) | _BV( TOIE1);  // interrupt on overflow and 0 crossing

  DEF_OUTPUT( LED_GREEN);
  DEF_OUTPUT( LED_AMBER);
  DEF_OUTPUT( LED_RED);
  DEF_OUTPUT( LED_ORANGE);
  DEF_OUTPUT( PIN_PWM);

  sei();

  while ( true) {
    TOGGLE( LED_ORANGE);
  }
  return 0;
}

There actually is a pattern to it. If I don't clear OCF1A in the ISR it processes 3 interrupts correctly and then 3 double interrupts. If I clear the interrupt flag it goes down to 2 interrupts single and then 2 double.

I've tried it with all phase correct and phase and frequency correct modes, different values for OCR1A, gcc 4.1.1 and 4.2.2 and 2 different m88 chips. Same behaviour.

So obviously I'm doing something wrong and have been staring at the screen and datasheet for too long to spot it. Does anybody else see it?

Thanks,
Markus

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I played a bit more with the system and one of the things I tried was using a different pin for LED_AMBER. And sure enough, the behaviour went away. LED_AMBER is connected to PB0 (when the wierdness happens).

Checking the datasheet I realized that the only special thing about PB0 is that it can be used to output the clock (CKOUT). So i checked my fuses again and lfuse was at 0xDF (as it should be for my setup).

Anyway, writing the same value 0xDF to lfuse (avrdude terminal mode). Made the double interrupts go away.

I just tried to verify that with the other m88 (which I had reprogrammed with a different app again) and that one works now fine as well (without having to reprogram the lfuse).

So maybe I let out the magic smoke a while ago and my AVRs are now run by gremlins.