www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer0 zu langsam?


Autor: Bruno (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

}

Autor: Bruno (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke
aber manchmal ist zu schnell eben zu schnell!

Bruno

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;
  delay_ms(5);
}

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno schrieb:
> void out_zahl(uint8_t wertig, uint8_t stelle)
> ...
>   delay_ms(5);

Prust, Lach.
out_zahl wird im Interrupt aufgerufen, da sind Delays streng verboten!

Aber etwas recht hast Du, 15kHz ist viel zu schnell, da können sich 
schon Programmlaufzeiten bemerkbar machen.

Für 4 Digits reichen 400Hz völlig.


Peter

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weil deine AUsgaberoutine Unsinn ist.

Du tust pro Interrupt (T0) alle Segmente für 5ms anzeigen, danach den 
Int. verlassen.

Das heißt, alle Segmente, außer dem ersten, werden 5ms angezeigt, die 
erste solange bis der Int wieder kommt.

Das ist Müll.

So funktioniert keine Multiplexausgabe!

Autor: avr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.