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 ...
... schrieb: > Finde beide Möglichkeiten nicht so toll. Wie macht man es richtig? 2 Puffer verwenden und diese dann umschaltet.
Soetwas schreit entweder nach http://de.wikipedia.org/wiki/Doppelpufferung oder Du sperrst den Interrupt, während geschrieben wird.
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.
Mal eine Idee wie sowas aussehen könnte:
1 | uint8_t myMatrix1[8]; |
2 | uint8_t myMatrix2[8]; |
3 | |
4 | uint8_t *readPtr myMatrix1; |
5 | uint8_t *writePtr myMatrix2; |
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 | uint8_t *tmpPtr; |
2 | |
3 | cli(); |
4 | |
5 | tmpPtr = readPtr; |
6 | readPtr = writePtr; |
7 | writePtr = tmpPtr; |
8 | |
9 | sei() |
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
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.