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
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.
1 | ...
|
2 | |
3 | volatile uint16_t counter; |
4 | volatile uint8_t updateLCD; |
5 | |
6 | ISR( .... ) |
7 | {
|
8 | // frage die notwendigen Eingänge ab
|
9 | // einfache und kurze Berechnungen können auch noch gemacht
|
10 | // werden, wenn die Zeit reicht
|
11 | counter++; |
12 | |
13 | |
14 | // und teile der Hauptschleife mit, dass neue Werte aufs LCD müssen
|
15 | updateLCD = TRUE; |
16 | }
|
17 | |
18 | ...
|
19 | |
20 | int main() |
21 | {
|
22 | ....
|
23 | |
24 | while( 1 ) { |
25 | ...
|
26 | |
27 | if( updateLCD ) { |
28 | updateLCD = FALSE; |
29 | |
30 | // mach die Ausgabe aufs LCD, beim Zugriff auf die globalen
|
31 | // Variablen auf atomaren Zugriff achten! Nicht dass die ISR
|
32 | // während der Ausgabe die globalen Variablen zwischendurch
|
33 | // verändert
|
34 | |
35 | cli(); |
36 | tmp = counter; |
37 | sei(); |
38 | |
39 | itoa( buffer, tmp, 10 ); |
40 | lcd_string( buffer ); |
41 | }
|
42 | }
|
43 | }
|
Ü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...
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.
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
1 | cli(); |
2 | tmp = counter; |
3 | 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.
@ 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.