mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer1 beim ATmega8 auch rückwärts?


Autor: Hermi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
ich muss für ein Wegmesssystem einen Inkrementgeber auswerten, d.h. die 
Schritte Zählen und die Bewegungsrichtung feststellen und den aktuellen 
Messwert auf einem LCD anzeigen. Ich hatte die beiden Signale als 
externe Interrupts angebunden, in der entsprechenden Interruptroutine 
die Richtung ermittelt, eine Variable hoch- bzw. runtergezählt und dann 
den aktuellen Wert zum LCD gesendet. Prinzipiell funktioniert das Ganze, 
aber während des sendens zum LCD gehen Inkremente verloren. Jetzt hab 
ich mir überlegt das Zählen der Inkremente dem Timer1 zu überlassen weil 
der unabhängig vom Programm läuft. das funktioniert auch, aber bei 
Rückwärtsbewegung des Messsystems mus er auch rückwärts zählen.
Jetzt meine Frage: kennt jemand eine Möglichkeit wie ich den Timer1 
rückwärts zählen lassen kann (im PWM- Bertieb macht er das doch auch)?

Ich hab jedenfalls im Datenblatt nichts gefunden und wäre dankbar für 
einen Hinweis.

Grüße: Hermi

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hermi schrieb:

> Messwert auf einem LCD anzeigen. Ich hatte die beiden Signale als
> externe Interrupts angebunden, in der entsprechenden Interruptroutine
> die Richtung ermittelt, eine Variable hoch- bzw. runtergezählt und dann
> den aktuellen Wert zum LCD gesendet.

Lass mich raten: du machst die Ausgabe aufs LCD auch innerhalb der ISR?

> Prinzipiell funktioniert das Ganze,
> aber während des sendens zum LCD gehen Inkremente verloren.

Das wundert mich nicht.
Verlagere die Ausgabe in die Hauptschleife und alles wird gut.
Alte Regel: In einer ISR nur das allernotwendigste machen. Alles was 
nicht zeitkritisch ist oder nicht unbedingt in der ISR gemacht werden 
muss, fliegt dort raus.

> Jetzt meine Frage: kennt jemand eine Möglichkeit wie ich den Timer1
> rückwärts zählen lassen kann (im PWM- Bertieb macht er das doch auch)?

Du zäumst das Pferd am falschen Ende auf.
Mach deine SW-Architektur richtig und alles wird gut.

...

volatile uint16_t counter;
volatile uint8_t updateLCD;

ISR( .... )
{
  // frage die notwendigen Eingänge ab
  // einfache und kurze Berechnungen können auch noch gemacht
  // werden, wenn die Zeit reicht
  counter++;


  // und teile der Hauptschleife mit, dass neue Werte aufs LCD müssen
  updateLCD = TRUE;
}

...

int main()
{
  ....

  while( 1 ) {
    ...

    if( updateLCD ) {
      updateLCD = FALSE;

      // mach die Ausgabe aufs LCD, beim Zugriff auf die globalen
      // Variablen auf atomaren Zugriff achten! Nicht dass die ISR
      // während der Ausgabe die globalen Variablen zwischendurch
      // verändert

      cli();
      tmp = counter;
      sei();

      itoa( buffer, tmp, 10 );
      lcd_string( buffer );
    }
  }
}

Autor: MeinerEiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übermittelst du die Daten in der Interruptroutine an das LCD? Wenn ja, 
dann ist das normal, dass Schritte verloren gehen.
Wenn nein, stimmt irgendwas nicht, da das Display-Update durch das 
Zählen kurz unterbrochen werden müsste...

Autor: Hermi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
vielen dank für Eure ersten Tipps. Ich habe jetzt das Ganze so 
abgeändert, dass ich in der jeweiligen Interruptroutine die Variable mit 
dem Messwert hoch oder runterzähle, die Erkennung der Bewegungsrichtung 
im Hauptprogramm realisiere und das LCD nur etwa viermal pro Sekunde in 
einer Interruptroutine von timer1 aktualisiere. Jetzt läuft es 
jedenfalls erstmal stabil, aber ich denke Währenfd des sendens an das 
LCD können doch noch Inkremente verlorengehen- weil doch in dieser Zeit 
die Interrupts ausgeschaltet sind.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hermi schrieb:

> jedenfalls erstmal stabil, aber ich denke Währenfd des sendens an das
> LCD können doch noch Inkremente verlorengehen- weil doch in dieser Zeit
> die Interrupts ausgeschaltet sind.

Wenn du es so gemacht hast, wie ich es dir weiter oben gezeigt habe, 
dann müssen die Interrupts aber schon sehr schnell kommen. Konkret kann 
nur in der kurzen Zeitspanne hier
      cli();
      tmp = counter;
      sei();

ein Interrupt verloren gehen. Nur hier sind die Interrupts gesperrt. Und 
das auch nur, wenn 2 so knapp hintereinander kommen, dass sich das mit 
dem Timing nicht mehr anders ausgeht.

Nachdem du dir die aktuellen Werte geholt hast, hast du alle Zeit der 
Welt die Anzeige auf den neuesten Stand zu bringen. Und es gibt auch 
keinen Grund während der Aufbereitung bzw. des Sendens an das LCD die 
Interrupts zu sperren :-) Wenn das LCD ein paar µs später die neuen 
Werte anzeigt, so spielt das keine Rolle. So schnell kann ein Mensch 
sowieso nicht schaun.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Hermi (Gast)


>Messwert auf einem LCD anzeigen. Ich hatte die beiden Signale als
>externe Interrupts angebunden, in der entsprechenden Interruptroutine
>die Richtung ermittelt, eine Variable hoch- bzw. runtergezählt und dann

Möööööp!!!

1.) Fehler: Drehgeber werden durch Abtastung per Timerinterrupt 
ausgewertet. Siehe Artikel.

>aber während des sendens zum LCD gehen Inkremente verloren. Jetzt hab

2.) Fehler. Interrupt-Routinen müssen kurz sein, längere Aufgaben 
werden, nein MÜSSEN, in der Hauptschleife ausgeführt werden, siehe 
Artikel.

>Rückwärtsbewegung des Messsystems mus er auch rückwärts zählen.

Macht eine richtige(tm) Auswertung problemlos.

>Jetzt meine Frage: kennt jemand eine Möglichkeit wie ich den Timer1
>rückwärts zählen lassen kann (im PWM- Bertieb macht er das doch auch)?

Käse.

MfG
Falk

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.