Hi, in einem Projekt möchte ích mit einem AT89S8051 Prozessor eine LED-Matrix ansprechen die durch Multiplexing insgesamt 20 Spalten und 14 Spalten besitzt (eine Matrix besteht aus 7 Zeilen und 5 Spalten) Als Programmiersprache dient C. Den Inhalt des Displays soll der Prozessor im Ram halten und per Interrupt (Timer ca. alle 20ms) auf das Display Spaltenweise schreiben. Mein Problem besteht darin die Datenmenge im Ram zu halten. Ich dachte an ein Array der Dimension 20x14. Leider unterstützt C jedoch kein Bit-Array. Könnt ihr mir sagen wie man solch einen "Display-Buffer" effizient programmieren kann? Viele Grüße,
Sven W. schrieb: > Mein Problem besteht darin die Datenmenge im Ram zu halten. Ich dachte > an ein Array der Dimension 20x14. Leider unterstützt C jedoch kein > Bit-Array. Nicht direkt, aber es geht trotzdem in C, siehe Bitmanipulation.
1 | #define N_LINES 20
|
2 | #define N_COLUMNS 14
|
3 | |
4 | uint16 display[NUM_LINES]; |
Da passen dann 20 x 16 Bit rein, wovon Du aber nur 20 x 14 brauchst. Der Speicherverbrauch liegt also bei 40 Bytes. Den Rest zur Speicherung/Abfrage entnimmst Du dem oben genannten Artikel.
Du wirst ja die 7 Zeilen multiplexen. Dann sollte man das für die Anzeige optimieren, also 7 * 40 Bit = 7 * 5 Byte.
1 | uint8_t disp_buff[7][5]; |
Es ist natürlich toll, wenn man den Displayinhalt in möglichst wenig Speicher quetschen kann. Aber wenn du nicht grad mit einem Tiny unterwegs bist (wovon ich mangels genug I/O Pins ausgehe) hast du den Speicher. Beispiel: Ich könnte bei einem LED-Cube (8*8*8) mit 64 Byte speicher auskommen. Aber ich definiere mir mein Array als uint8_t cube[8][8][8]; Mein ATmega1284P hat 16k RAM, da drück ich die 512 Byte doch locker ab. Vorteile: 1) höchstwahrscheinlich schnellerer Code da Bitgeschiebe und -verknüpfungen entfallen 2) Die Schnittstellen ändern sich nicht (kaum) wenn ich mal auf RGB LEDs umsteigen wollte. Dann hab ich z.B. 1 Byte für Farbinformationen. Wenn du das Display nicht gerade kommerziell vertreibst dann zahl den Euro mehr den der ATmega1284P gegenüber einem alten 16er kostet.
Sven W. schrieb: > Mein Problem besteht darin die Datenmenge im Ram zu halten. Ich dachte > an ein Array der Dimension 20x14. Leider unterstützt C jedoch kein > Bit-Array. Kann man ja auch selber machen. Wenn du (nur so als Beispiel) 40 Bits nebeneinander brauchst, dann kannst du die in 5 Bytes unterbringen. Warum? Weil 5*8 die 40 ergeben Also: uint8_t Line[5]; In welchem Byte befindet sich daher das Bit mit der Nummer 12? Na, wenn in jedem Byte jeweils 8 Bit sind, dann ist das Bit mit der Nummer 12 in Line[1]. Warum? Weil 12/8 gleich 1 ergibt. In diesem Byte, an welcher Bitposition ist denn da das 12-te Bit? (mal kurz eine Skizze machen 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 absolute Bitnummer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 Bit im Byte | | | +--- Line[0] -----------+------ Line[1] --------+ so, nachdem das soweit klar ist, zurück zur Frage: das wievielte Bit ist denn das Bit Nummer 12, gesehen aus der Sicht von Line[1]. Aus der Zeichnug sehen wir: das ist Bit 3) Warum ist das so? Weil 12 % 8 gleich 4 ergibt, und 7 - 4 die 3 macht. Wenn das Display die Bits genau anders rum haben will, so dass Bit 0 links ist, anstatt rechts, dann ist es noch einfacher. Dann ist 12 % 8, also 4 die Bitnummer. D.h. wird ein Pixel gesetzt, dann setzt man in Line[ xPos / 8 ] das Pixel mit der Nummer ( 1 << ( 7 - xPos%8 ); oder, wenn das Bit 0 links ist (wie meistens), dann eben das Bit ( 1 << (xPos%8) ); Alles zusammengenommen: void setPixel( uint8_t xPos ) { Line[xPos/8] |= ( 1 << xPos%8 ); } Und das ganze hat dann auch noch den Vorteil, dass du wahrscheinlich diese ganzen 8 Bits in dem Byte als ganzes zum LCD schicken kannst, ohne dass du erst mal die Einzel-Bits aus 8 Einzelvariablen zusammensetzen musst. D.h. deine ISR hat die auszugebenden Bytes schon fix fertig vorliegen und muss sie nur ans LCD weitergeben. Und das ist gut so. Denn deine ISR ackerte früher x mal in der Sekunde, um die Einzelbits zum im wesentlichen immer gleichen Byte zusammenzusetzen, weil sich der Display Inhalt viel seltener ändert, als ihn die ISR benötigt. D.h. du verschiebst zwar ein wenig Aufwand in den Funktionsblock Pixel-Setzen. Dafür entlastest du aber im Gegenzug die ISR massiv. Und im Summe bringt dir das mehr, weil die ISR ja dauernd läuft, während du im Vergleich dazu eher selten ein Pixel setzt oder löscht. Sind die Pixel am LCD nicht zeilenweise in Bytes zusammengefasst, sondern spaltenweise (also immmer 8 Pixel übereinander in einem Byte), dann ist das genau so einfach. Einfach mal aufmalen und überlegen, wie man aus der x/y Position des zu setzenden Pixels, auf das Byte und auf die Bitnummer in diesem Byte kommt. Jaaa, man kann sich Formeln auch selber herleiten. Das wird auf dieser Ebene selten komplizierter als eine Multiplikation und/oder Division und/oder Division mit Rest und vielleicht, möglicherweise noch eine Addition dazu. Aber schwieriger wirds nicht. Eine kleine Skizze, in der man sich die Dinge einträgt, hilft da oft Wunder, die Zusammenhänge zu sehen.
Vielen Dank für die vielen Informationen. Nun habe ich einen Ansatz den ich verfolgen werde :)
le x. schrieb: > Vorteile: 1) höchstwahrscheinlich schnellerer Code da Bitgeschiebe und > -verknüpfungen entfallen Nö, im Gegenteil. Du mußt immer umständlich schieben, um die 8 einzelnen Bits wieder zu einem Byte zusammen zu friemeln. Neben mehr RAM brauchst Du deutlich mehr Code. Wenn aber schon 8 Bits in einem Byte sind, dann kannst Du sie einfach parallel an ein Latch (74HC573) für 8 LEDs ausgeben oder seriell per SPI an einen 74HC595. In jedem Timerinterrupt werden dann einfach 5 Bytes auf 5 Latches gegeben und die nächste Zeile eingeschaltet. Peter
Da hast du natürlich recht Peter! Mir gings aber eher um "aufwendige" Animationen. Die Ausgabe sollte normalerweise nicht so das Problem sein, aber das nächste Bild sollte nach Möglichkeit fertig berechnet sein...
lex schrieb: > Da hast du natürlich recht Peter! > > Mir gings aber eher um "aufwendige" Animationen. > Die Ausgabe sollte normalerweise nicht so das Problem sein, aber das > nächste Bild sollte nach Möglichkeit fertig berechnet sein... Reißt sich aber trotzdem um nix. Denn die ISR muss das Bitgepfriemel zwingend ein paar Hundert mal in der Sekunde machen, die Animationsroutine nur dann, wenn sich ein Pixel auch tatsächlich ändert.
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.