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.
Das geht vielleicht besser, wenn du auch beide interrupts aktivierst ;)
1 | TCCR0 = 1<<CS01; //divide by 8 * 256 |
2 | TIMSK = 1<<TOIE0; //enable timer interrupt |
3 | |
4 | TCCR2 = (1<<CS22) | (1<<CS21); /*Timertakt= CPU-Takt/256 (nochmal |
5 | durch 256 wegen 8-Bit Timer, ist Freq. der Anzeige)*/
|
6 | TIMSK = (1<<TOIE2); //Enable Timer Interrup |
7 | // ^ Hier wird der erste Timer interrupt wieder abgeschaltet
|
8 | // '|=' waere besser
|
hth, Jörg
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.
>"Deter Dannegger"
lol :D
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
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.