Forum: Compiler & IDEs ISRs stören sich gegenseitig


von Thomas L. (tom)


Lesenswert?

Hallo :)

Ich versuche derzeit eine SW PWM zu realisieren. Dabei stoße ich jedoch
auf folgendes Problem.

Ein Timer arbeitet die PWM ab, der andere verändert die gewünschten
Helligkeitswerte. Das Ganze soll später noch erweitert werden, daher
habe ich das so gelöst. Hier mal der Code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

#define CPU_SPEED 1000000

#define PWM_CH0 0
#define PWM_CH1 1
#define PWM_CH2 2

#define PWM_PORT PORTB
#define PWM_PORT_DIRECTION DDRB

volatile uint8_t currentValueInRun = 0; // This is the number of the
cycle inside one frame
volatile uint8_t currentBrightness[3]; // This is the brightness of the
channels
volatile uint8_t currentColourRun = 0;
volatile uint8_t colourChangeTime = 1;

struct {
   unsigned char stateTimerEnabled:1; // 1 Bit für bStatus_1
   unsigned char stateSwitchEnabled:1; // 1 Bit für bStatus_2
} status;


void enablePWM(void)
{
  // Set PWM_PORT AS OUTPUT (0 is Output, 1 is input)
  PWM_PORT_DIRECTION &= ~ ((1 << PWM_CH0) | (1 << PWM_CH1) | (1 <<
PWM_CH2));
  PWM_PORT = 0x00; // Set to Low

  // Use Timer 2 (8bit timer) for actual PWM
  TCCR2 |= (1 << WGM21);    // CTC Mode (WGM21 -> 1, others 0)
  TCCR2 |= (1 << CS20);    // No pre-scaler (running at CPU speed) (CS20
-> 1)
  //Calculate Preload value
  OCR2 = CPU_SPEED / 25600;  // will cause an overflow (TIMER2_COMP) if
TCNT reaches OCR2
  TIMSK |= (1 << OCIE2);    // Enable the overflow interrupt
}


ISR(TIMER2_COMP_vect)
{
  // ISR for PWM

  // This happens every 100 Cycles (25 600 Times each second)
  // Every cycle has 256 steps (resolution of brightness, 256 different
levels of brightness are possible) - from 0 .. 255 is one frame
  // We run at 100fps

  currentValueInRun++;  // will overflow automatically at 255 to 0

  if (currentValueInRun >= currentBrightness[0])   // check if we are in
the range of switching on / off
  {
    // Off State
    PWM_PORT &= ~(1 << PWM_CH0);
  }
  else
  {
    // On State
    PWM_PORT |= (1 << PWM_CH0);
  }
}

ISR(TIMER0_OVF_vect)
{
  // ISR for Automatic changer

  currentBrightness[0] = 255;
  PORTD=0xff;


  /*currentColourRun++;
  if (currentColourRun >= colourChangeTime)
  {
    currentColourRun = 0;
    // change color either completely or some step
    currentBrightness[0]++;
  }
  else
  {
    currentColourRun++;
  }*/
}


void enableAutomaticChanger(void)
{
  // Use Timer 0 - timing is not important
  TCCR0 |= (1 << CS00) | (1 << CS02);   // Prescaler: 1024, no reload
value (will count from 0 ... 255)
  TIMSK |= (1 << TOIE0);          // Enable interrupt
}

int main(void)
{
  // Init the brightness settings:
  for (int i = 0; i < 3; i++) {
    currentBrightness[i] = 0x00;
  }

  enablePWM();

  enableAutomaticChanger();

  PORTD = 0x00;

  sei();            // Enable global interrupts and wait
  while(1);          // now wait for interrupts
}


PortD nutze ich zum Überprüfen ob der Atmega8 in die entsprechenden
Routinen springt. Nun wirds aber interessant.
Aktiviere ich die PWM NICHT, so springt er - wie er soll in die
TIMER0_OVERFLOW ISR (PORTD = 0xff).
Wenn nun aber parallel dazu die PWM aktiviert wird, so springt er
einfach nicht mehr in die TIMER0_OVERFLOW ISR (PORTD bleibt auf 0x00).

Was mache ich denn falsch?

Um den Effekt herbeizuführen, reicht es aus, die Zeile enablePWM();
einfach mal auszukommentieren.

Danke für jegliche Hilfe :)

von Peter D. (peda)


Lesenswert?

Du setzt OCR2 auf 39 Zyklen, das ist fast nichts.

Warscheinlich kommst Du garnicht aus dem TIMER2_COMP raus.



Peter

von Thomas L. (tom)


Lesenswert?

Uff, tatsächlich. Selten so einen dummen Fehler gehabt.

Dank dir vielmals :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.