Nehmen wir an, ich habe einen Arduino, der mit einer 8x8 LED matrix
.
74HC595
In meinem Fall wird die LED-Matrix mit zwei Schieberegistern (eines für die Zeilen und eines für die Spalten) angesteuert .
Da es nur den Status von 8 LEDs gleichzeitig (eine Reihe) einstellen kann, ist die Idee, die Reihen schnell genug zu aktualisieren, damit das menschliche Auge das Blinken nicht bemerkt.
Dies geschieht normalerweise in der loop()
Methode:
int led_status[8]; //contains LED status (which is on/off) for each row
void loop() {
process_otherstuff(); //eg: key inputs,...
display(); //shift led_status[] to shift register and latch result.
}
Hier ist ein potenzielles Problem: Was ist, wenn die CPU einen zeitaufwändigen Prozess in der Schleifenmethode ausführen muss (zB: schwere Mathematik)? Die Methode display() wird mit einer gewissen Verzögerung aufgerufen, die sich bemerkbar machen könnte (LED beginnt zu blinken oder noch schlimmer: stoppt aktualisiert, scheint in einer Zeile hängen zu bleiben).
Eine mögliche Lösung, die mir einfällt, ist die Aktualisierung der LED-Matrix in einem Interrupt-Handler:
void setup()
{
analogWrite(3, 100);
attachInterrupt(1, refreshdisplay, RISING);
}
int row = 0;
void refreshdisplay()
{
//refresh one single row
refreshrow(row++);
if(row > 7) row = 0;
}
Ist das eine gute Idee? Auf diese Weise wird die Anzeige so schnell wie nötig aktualisiert, egal wie viel Zeit in der Methode loop() verbracht wird. Ein potenzielles Problem, das ich sehe, ist, dass jetzt viel Zeit im Interrupt verbracht wird, was normalerweise eine schlechte Sache ist (der Interrupt-Handler sollte so kurz wie möglich sein).
Eine andere Lösung besteht darin, einen separaten LED-Controller-Treiber zu verwenden (z. B. über einen I2C-Bus mit Arduino verbunden), dies erfordert jedoch eine Änderung der Komponentenliste.
Ja, das ist der richtige Ansatz – aktualisieren Sie die Anzeige in einem ISR.
Selbst geringfügige Timing-Änderungen können zu visuellen Artefakten führen, daher ist es notwendig, das Timing ziemlich eng zu halten, wenn Sie ein qualitativ hochwertiges Erscheinungsbild der Anzeige wünschen.
Verwenden Sie nach Möglichkeit Hardware (z. B. das SPI-Peripheriegerät), um in die Schieberegister zu schreiben, und verwenden Sie natürlich eine relativ hohe Taktrate. Wenn Sie dies tun, sollte die Gesamtzeit, die in der ISR verbracht wird, nur wenige Prozent der Prozessorbandbreite betragen, und da sie in kleinen „Blöcken“ verwendet wird, wird die Hintergrundverarbeitung fast so ablaufen, als ob Sie einen Prozessor hätten, der beispielsweise mit 12 MHz läuft statt 16 MHz.
Einfache und (relativ) zeitkritische Prozesse wie das Aktualisieren einer Anzeige sind genau das, wofür ISRs gut sind. Es ist auch eine gute Zeit (während Sie sich in einer periodischen ISR befinden), um beispielsweise Eingangsschalter auf Entprellung zu scannen.
Normalerweise werden Interrupt-Handler tatsächlich für kurze Aktionen verwendet. Der Grund ist, dass das Hauptprogramm blockiert.
Wenn der Haupthandler jedoch keine zeitkritischen Aktionen ausführt, ist dies ein geringeres Problem.
Stellen Sie sicher, dass der Interrupt-Handler nicht länger als den nächsten Interrupt-Aufruf braucht. Dann erhalten Sie einen Unterbrechungsruf innerhalb eines Unterbrechungsrufs usw.
In Ihrem Fall dauert Ihre Aktualisierungsfunktion wahrscheinlich immer gleich lange. Sie können es messen (führen Sie einen Test mit 1000 Iterationen durch und teilen Sie die Zeit durch 1000, oder 1M ist, dass Sie es nicht messen können). Und Sie kennen die Bildwiederholfrequenz. Dann wissen Sie, wie viel Prozent (abzüglich etwas Overhead) für Ihr Hauptprogramm übrig bleiben.
Persönlich denke ich, dass das Schreiben von 64 GPIO-Pins, auch mit Schieberegistern, sehr schnell erledigt sein sollte, aber Testen ist besser als Annehmen.
Gerstenmann
glen_geek