Hallo, vielleicht könnt ihr mir weiterhelfen.
Ich habe ein Programm für einen ATmega32 geschrieben, das auf der
Drehencoder-Routine von Deter Dannegger beruht (hier aus der
Codesammlung). Das einlesen der 4 Drehencoder die ich an Port A
angeschlossen habe, funktioniert auch prima.
Jetzt zu meinem Problem: Das einlesen der Drehencoder erfolgt über den
Timer-Overflow-Interrupt mit Timer0 (ca. 7 KHz).
Die Ausgabe der zweistelligen Zahl erfolgt mit 7-Segment-Anzeigen, von
denen habe ich ingesamt vier Paare (Also viermal eine zweistellige
Anzeige) die an Port C parallel angeschlossen sind. Die
7-Segment-Anzeigen werden durch einen BCD-to-7 Segment Treiber/Latch
angesteuert. Die Parallelen Anzeigen werden über den Latch-Eingang des
4543 gemultiplext der auf Port B liegt.
Da es ja aber schwachsinn ist, das multiplexen mit 7 Khz zu machen, hab
ich einen zweiten Interrupt über Timer2 realisiert, der mit 200 Hz
arbeitet.
Das Problem: wenn ich den zweiten Interrupt benutze werden auf den
Anzeigen nur noch Nullen angezeigt, die durch Drehen nicht verändert
werden. Die einzige Variable im zweiten Interrupt ist die counter1_high
und counter1_low, die ich als global und volatile deklariert habe. Diese
wird in der ersten Interruptroutine geschrieben und in der zweiten nur
gelesen. Mach ich da irgendwo nen Denkfehler?
Wenn ich das setzen der Anzeigen mit in die erste Routine packe wird
alles so angezeigt wie es soll.
Ich weiß nicht mehr weiter!
Vielen Dank für alle Antworten!
MfG Matthias
Das Updaten eines Displays mit 7kHz ist Unsinn. Eine zweiten Timer zu
verblasen ist auch Unsinn. Einfacher waere es das Dasplay im Ersten zu
machen, aber zb nur jedes 1000. Mal.
aaa wrote:
> Das Updaten eines Displays mit 7kHz ist Unsinn.
Was er schon selber sagte.
> Eine zweiten Timer zu> verblasen ist auch Unsinn.
Nein, ist es beim AVR nicht. Der hat ja keine Interruptprioritäten.
Wenn der 2. Timer-Handler länger braucht, könnte der 1. Handler
Überläufe verlieren.
Man müßte dann tricksen (SEI im Interrupt), was gefährlich sein kann.
Daher ist ein 2. Timer durchaus sinnvoll, wenn er noch frei ist.
Peter
Ein BCD ueber parallellatch anzusteuern braucht ja praktisch keine Zeit,
solange man keine Float umrechnung vorschaltet. Vernuenftigerweise hat
man die Werte im Main aufbereitet, sodass der Timerinterrupt nur noch
laden muss.
Zwei konkurrierende Timer ersetzt man besser durch eine Statusmaschine
im Timer.
Peter Dannegger wrote:
> Nein, ist es beim AVR nicht. Der hat ja keine Interruptprioritäten.> Wenn der 2. Timer-Handler länger braucht, könnte der 1. Handler> Überläufe verlieren.> Man müßte dann tricksen (SEI im Interrupt), was gefährlich sein kann.> Daher ist ein 2. Timer durchaus sinnvoll, wenn er noch frei ist.
Ist natürlich quatsch, was ich da geschrieben habe.
Der 2.Timer ändert kaum was.
Wenn ein Interrupt zu lange dauert, ist wurscht, ob er sich selber
blockiert oder nen anderen.
Daher lange Sachen beim AVR möglichst im Main machen.
Peter
Oh man, danke leute. Ist schon ganz schön doof, wenn man copy and paste
macht ohne die zu schreibenden Registerbits zu ändern.
Ich hab noch eine weitere Frage: Das hier sollte erstmal eine primitive
Grundversion sein, die genau das ermöglicht was ich geschrieben hab.
Ich hab auch schon über verbesserungen nachgedacht, da der erste
Interrupt ja doch ziemlich "lang" ist. Auf der anderen Seite braucht die
Drehencoder-Auswertung auch nicht öfter laufen, und soo kompliziert ist
die ja auch nicht
(Dank PETER (sorry, war noch etwas fertig vorhin), großes kompliment
dafür. Hat zwar augenblick gedauert bis so ein Anfänger wie ich das
kapiert hatte, aber im endeffekt ist es Genial. Vielleicht solltest du
noch mal erwähnen das der Code für drehencoder ist die pro "Raste" nur
zwei wechsel haben. war schwer für mich den Fehler und die Behebung zu
finden da ich einen mit 4 Zuständen hab.)
Könnte man nicht nur mit dem Interrupt die Eingänge sozusagen
"kontrollieren" ob sich da was geändert hat, und nur dann die
Einleseroutine laufen lassen?
In einer vorigen version hatte ich die "nebenberechnung" der counter
(>23, <0), counter_high und counter_low variablen im Hauptprogramm
gemacht, was ja aber auch blödsinn ist, weil die ja gar nicht so oft
geändert werden!
Demnächt soll da noch ein externer Interrupt rein der dann die counter
inhalte über USART verschickt. Das sollte doch ohne probleme gehen oder?
Hat irgendwer noch gröbere Schnitzer gefunden? Oder
optimierungsvorschläge?
Trotzdem schon mal vielen Dank für die schnellen Antworten hier.
Mathhias