Timer0 zu langsam?

Gast #1282109
Lesenswert?

Hallo habe folgende Code und komme nicht mehr klar.

Timer 0 sollte doch alle 800000/1/256=31250 ausgeführt werden. Also 
32250/2= 15625Hz Warum leuchtet bei der Siebensegmentanzeige aber die 
Einerstelle immer heller bei einer Refreshrate von 15kHz?

Danke
Bruno

Code
// WINAVR 20090306
// AVR Studio 4.16.628

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

volatile uint8_t tausender, hunderter, zehner, einer;
volatile uint16_t wert;

#define maxwert 999

const int8_t numbers [10] =
{
//   1gfedcba
   0b10111111,     //0
   0b10000110,     //1
   0b11011011,     //2
   0b11001111,     //3
   0b11100110,     //4
   0b11101101,     //5
   0b11111101,     //6
   0b10000111,     //7
   0b11111111,     //8
   0b11101111,     //9
};

void out_zahl(uint8_t wertig, uint8_t stelle)
{
  // Ausschalten sonst nachleuchten der Zahl
  PORTB = 0b00000000;
  PORTD = 1 << stelle;
  // Neue Zahl ausgeben
  PORTB = numbers[wertig];
  PORTD = 1 << stelle;
}

void out_nummer()
{

  for(int8_t position=4; position>=0; position--)
    {
      switch (position)
      {
        case 3:
        {
          // out_zahl(tausender, 3);
          break;
        }
        case 2:
        {
          out_zahl(hunderter, 2);
          break;
        }
        case 1:
        {
          out_zahl(zehner, 1);
          break;
        }
        case 0:
        {
          out_zahl(einer, 0);
          break;
        }
      }
    }

}


// Timer 0 - 8 Bit Overflow
ISR (TIMER0_OVF_vect)
{
  // Anzeige erneuern
  out_nummer();
  // Timer hochstellen
}

// Timer 1 - 16 Bit
// Zähler um eins erhöhen
ISR (TIMER1_OVF_vect)
{
  // Maximaler zähler
  if (wert == maxwert)
    {
      wert=0;
    }

  // Eins hoch
  wert++;

  uint16_t auswert;
  auswert = wert;

  // tausender
  tausender = auswert/1000;
  auswert = auswert%1000;

  // hunderter
  hunderter = auswert/100;
  auswert = auswert%100;

  // zehner
  zehner = auswert/10;

  // einer
  einer = auswert%10;

}

int main(void)
{
  // Port C 4 auf Ausgang
  DDRD |= (1 << DDD0) | (1 << DDD1) | (1 << DDD2) | (1 << DDD3) | (0 << 
DDD4) | (0 << DDD5) | (0 << DDD6) | (0 << DDD7);
  // Port B alles auf Ausgang
  DDRB |= (1 << DDB0) | (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << 
DDB4) | (1 << DDB5) | (1 << DDB6) | (1 << DDB7);

  // Variablen init
  wert = 0;
  einer = 0;
  zehner = 0;
  hunderter = 0;
  tausender= 0;

  // Ausgabe neu zeichnen
  // Timer 0
  // Prescaler = 1 Clock Takt!!!
  TCCR0 |= (1 << CS00) | (0 << CS01) | (0 << CS02) ;
  // Prescaler =  8 Clock Takt!!!
  // TCCR0 |= (0 << CS00) | (1 << CS01) | (0 << CS02) ;
  // Prescaler =  64 Clock Takt!!!
  // TCCR0 |= (1 << CS00) | (1 << CS01) | (0 << CS02) ;
  // Prescaler =  256 Clock Takt!!!
  // TCCR0 |= (0 << CS00) | (0 << CS01) | (1 << CS02) ;
  // Prescaler = 1024
  // TCCR0 |= (1 << CS00) | (0 << CS01) | (1 << CS02) ;

  // Hochzählen
  // Timer 1
  // Prescaler = 1 Clock Takt!!!
  // TCCR1B |= (1 << CS00) | (0 << CS01) | (0 << CS02) ;
  // Prescaler =  8 Clock Takt!!!
  // TCCR1B |= (0 << CS00) | (1 << CS01) | (0 << CS02) ;
  // Prescaler =  64 Clock Takt!!!
  TCCR1B |= (1 << CS00) | (1 << CS01) | (0 << CS02) ;
  // Prescaler =  256 Clock Takt!!!
  // TCCR1B= (0 << CS00) | (0 << CS01) | (1 << CS02) ;
  // Prescaler = 1024
  // TCCR1B= (1 << CS00) | (0 << CS01) | (1 << CS02) ;

  // TIMER Interrupt Maske Timer 0 und Timer 1 bei Overfow
  TIMSK |= (1 << TOIE0) | (1 << TOIE1);

  sei();  //IRQ ein

  // Timer 0 hochstellen für OVF
  // TCNT0=253;

  // Timer 0 für COMP
  OCR0 = 128;

  while(1)
    {
      // nothing
    }
  return 0;

}
Gast #1282138
Lesenswert?

Das Problem ist, daß er im Interrupt immer
alle 5 Ziffern ausgibt
>  for(int8_t position=4; position>=0; position--)
und die letzte dann stehenbleibt.

Richtig ist im Interrupt (400 Hz für 4 Digits mehr als
ausreichend) eine Ziffer einschalten, dann im nächsten
Aufruf diese aus- und die nächste einschalten.
Die Ziffern haben dann alle einen Duty von 1:3 (und etwas
Verarbeitungszeiten).


gruß avr

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren