Hallo zusammen,
ich hätte eine kurze Frage.
Ich habe einen Speicher den ich per Interrupt auf einer LED-Matrix
ausgebe.
Jetzt habe ich eine Funktion die Werte in den Speicher legt (in der
main).
Es wird immer zuerst der komplette Speicher gelöscht (da ich nicht jede
Stelle beschreibe) und dann die neuen Informationen abgelegt. Der
Interrupt schreibt die Daten auf die Anzeige wann immer er auch kommt.
Ich dachte es macht nichts aus, wenn er "mittendrin" kommt, doch leider
sieht man ab und zu ein flackern.
Da die Main noch ziemlich leer ist, wird die "Schreib-Funktion" häufig
aufgerufen und wenn es doof läuft schreib die Ausgaberoutine immer einen
leeren Videospeicher raus.
Deswegen möchte ich den Speicher nur ändern, wenn keine Ausgabe erfolgt.
Frage ist wie macht man das ordenlich.
Interupt deaktivieren
Speicher beschreiben
Interrupt aktivieren???
Dann würde die Interrupts wärend dieser Zeit flöten gehen.
Andere Möglichkeit wäre Speicher den Speicher nur während des Interrupts
zu ändern.
D.h.
Interrupt
-> neue Daten übernehmen
-> Ausgabe
Ende.
Finde beide Möglichkeiten nicht so toll. Wie macht man es richtig?
Vielen Dank und viele Grüße
...
Wenn genug Speicher vorhanden ist: Zwei Puffer anlegen und in den main
abwechselnd befüllen und nach jedem Befüllen ein bit toggeln, damit der
Interrupt weiß, aus welchem Puffer er lesen soll.
Ansonsten musst du das Puffern und die Ausgaben synchronisieren. Wo
kommen die Daten den her? Kannst du nach der Ausgabe im Interrupt
prüfen, ob neue Daten zur Verfügung stehen und diese dann in den Puffer
schreiben?
Der Interrupt kann auch ein Flag setzen, das er gerade aktiv ist, und
main checkt dieses Flag. Wenn du Flimmern vermeiden willst, sollte ja
der IRQ möglichst störungsfrei zünden und main sich zurückhalten. Hängt
also von deinen Prioritäten ab.
Matthias Sch. schrieb:> Der Interrupt kann auch ein Flag setzen, das er gerade aktiv ist, und> main checkt dieses Flag
das wird wohl nichts. Wenn der Interrupt aktiv ist, dann kann die main
nichts checken weil sie schläft.
Wow,
das ging schnell... :-D
Hier haben wohl grad einige Mittagspäuschen.
Vielen Dank an alle!
Das mit dem Doppelspeicher probier ich mal aus.
D.h. wenn ich Speicher1 fertig beschrieben habe setze ich ein Flag auf
Speicher1 -> Interrupt gibt Speicher 1 aus
Wenn ich das nächste mal schreiben möchte, teste ich das Flag und wenn
es auf Speicher 1 steht schreibe ich in Speicher 2. Speicher 1 wird so
lange ausgegeben, bis das Flag in der Schreibroutine auf Speicher 2
umgestellt wird.
Super Danke!
Ist besser als den Interrupt zu deaktivieren.
VIELEN DANK!
> Es wird immer zuerst der komplette Speicher gelöscht> (da ich nicht jede Stelle beschreibe)
Diesen Teil würde ich in Frage stellen. Also, das komplette Löschen.
Tus nicht, dann flackert auch nichts.
Ist irgendwie dasselbe wie: Hilfe, mein LCD flackert.
UNd wenn man dann ins Programm reinschaut, wimmelt es da wieder nur so
vor AUfrufen von LCD Lösch Routinen.
Der Trick besteht darin, eben nicht zu löschen wenn es nicht sein muss,
sondern die Teile zu überschreiben, die sich ändern.
... schrieb:> Es wird immer zuerst der komplette Speicher gelöscht
Das ist natürlich sichtbar, da das Main ja Zeit braucht zum neu
schreiben.
Besser ist daher, einfach überschreiben ohne zu löschen.
... schrieb:> D.h. wenn ich Speicher1 fertig beschrieben habe setze ich ein Flag auf> Speicher1 -> Interrupt gibt Speicher 1 aus
statt flag, kann man auch einen Zeiger verwenden der auf die aktuellen
Daten zeigt.
> Ist besser als den Interrupt zu deaktivieren.
brauchst du dann nicht.
In der ISR benutzt du nur den readPtr, in der main, wo deine
Berechnungen liegen verwendest du den writePtr.
Somit sparst du dir jedesmal die Flag-Abfrage.
Wenn ein neues Bild zur Ausgabe fertig berechnet wurde, einfach kurz die
Pointer vertauschen. Dieser Abschnitt muss allerdings atomar sein.
1. Beim Schreiben in "LEDs" geht es praktisch immer um die maximale
Geschwindigkeit der menschlichen Wahrnehmung. Also nix mit
Mikrosekunden oder gar schneller.
2. Einen Speicher komplett löschen, bedeutet erst mal: Du hast nix
besseres zutun.
Fazit: Den Speicher von vorne beschreiben bis (gewünschtes) Ende,
diesen Zeiger (Ende) merken und von da aus löschen. In praktisch
allen Fällen merkt kein Mensch, wenn Du in dieser Zeit die
Ausgabe stoppst.
Also spar' Dir das Dual-Ported-RAM und geh dafür mit Deiner Freundin mal
gut essen.
Übrigens: Was soll das bringen? Offensichtlich hast Du ja kein Zugriffs-
sonder ein Timing-Problem.
Peter II schrieb:> Matthias Sch. schrieb:>> Der Interrupt kann auch ein Flag setzen, das er gerade aktiv ist, und>> main checkt dieses Flag>> das wird wohl nichts. Wenn der Interrupt aktiv ist, dann kann die main> nichts checken weil sie schläft.
Das ist auch wieder wahr. Allerdings kann die ISR markieren, wann sie
fertig ist und das für die nächste Zeit der Speicher frei ist.
... schrieb:> Interupt deaktivieren> Speicher beschreiben> Interrupt aktivieren???> Dann würde die Interrupts wärend dieser Zeit flöten gehen.
Der Interrupt, der während dieser Zeit auftritt, wird dann anschließend
(zeitlich verschoben) ausgeführt.
Nur wenn es mehrere Interrupts während "Speicher beschreiben" auftreten,
können welche verloren gehen.
Nur wenn das so ist, dann stimmt was an der Gesamt-Zeitbilanz nicht: Du
willst häufiger die Daten auf der LED-Matrix ausgeben als der Update des
Speichers dauert. Das ist aber Unsinn, denn 2x dasselbe ausgeben kann
man sich dann sparen...
Gruß Dietrich
Dietrich L. schrieb:> Das ist aber Unsinn, denn 2x dasselbe ausgeben kann> man sich dann sparen...
die matrix muss ständig ausgeben werden sonst sieht man nichts.
Peter II schrieb:> die matrix muss ständig ausgeben werden sonst sieht man nichts
Ok, ja, ich hatte einen Gedankenfehler :-(
Wenn also der Speicher-Update lange dauern kann, ist die Lösung mit
"doppelter Speicher" wohl die einzig sinnvolle :-)
Gruß Dietrich